boost_sqlite 1
A sqlite C++ library
Loading...
Searching...
No Matches
result.hpp
1//
2// Copyright (c) 2022 Klemens Morgenstern (klemens.morgenstern@gmx.net)
3//
4// Distributed under the Boost Software License, Version 1.0. (See accompanying
5// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
6//
7
8#ifndef BOOST_SQLITE_RESULT_HPP
9#define BOOST_SQLITE_RESULT_HPP
10
11#include <boost/sqlite/blob.hpp>
12#include <boost/sqlite/detail/config.hpp>
13#include <boost/sqlite/value.hpp>
14
15#include <boost/variant2/variant.hpp>
16
17
18BOOST_SQLITE_BEGIN_NAMESPACE
19
20
21struct set_result_tag {};
22
23
24inline void tag_invoke(set_result_tag, sqlite3_context * ctx, blob b)
25{
26 auto sz = b.size();
27 sqlite3_result_blob(ctx, std::move(b).release(), sz, &operator delete);
28}
29
30
31inline void tag_invoke(set_result_tag, sqlite3_context * ctx, zero_blob zb)
32{
33 sqlite3_result_zeroblob64(ctx, static_cast<sqlite3_uint64>(zb));
34}
35
36inline void tag_invoke(set_result_tag, sqlite3_context * ctx, double dbl) { sqlite3_result_double(ctx, dbl); }
37
38template<typename I,
39 typename = typename std::enable_if<std::is_integral<I>::value>::type>
40inline void tag_invoke(set_result_tag, sqlite3_context * ctx, I value)
41{
42 BOOST_IF_CONSTEXPR ((sizeof(I) == sizeof(int) && std::is_unsigned<I>::value) || (sizeof(I) > sizeof(int)))
43 sqlite3_result_int64(ctx, static_cast<sqlite3_int64>(value));
44 else
45 sqlite3_result_int(ctx, static_cast<int>(value));
46}
47
48inline void tag_invoke(set_result_tag, sqlite3_context * ctx, std::nullptr_t) { sqlite3_result_null(ctx); }
49inline void tag_invoke(set_result_tag, sqlite3_context * ctx, string_view str)
50{
51 sqlite3_result_text(ctx, str.data(), str.size(), SQLITE_TRANSIENT);
52}
53template<typename String>
54inline auto tag_invoke(set_result_tag, sqlite3_context * ctx, String && str)
55 -> typename std::enable_if<std::is_convertible<String, string_view>::value>::type
56{
57 return tag_invoke(set_result_tag{}, ctx, string_view(str));
58}
59
60
61inline void tag_invoke(set_result_tag, sqlite3_context * ctx, variant2::monostate) { }
62inline void tag_invoke(set_result_tag, sqlite3_context * ctx, const value & val)
63{
64 sqlite3_result_value(ctx, val.handle());
65}
66
67struct set_variant_result
68{
69 sqlite3_context * ctx;
70 template<typename T>
71 void operator()(T && val)
72 {
73 tag_invoke(set_result_tag{}, ctx, std::forward<T>(val));
74 }
75};
76
77template<typename ... Args>
78inline void tag_invoke(set_result_tag, sqlite3_context * ctx, const variant2::variant<Args...> & var)
79{
80 visit(set_variant_result{ctx}, var);
81}
82
83template<typename T>
84inline void tag_invoke(set_result_tag, sqlite3_context * ctx, std::unique_ptr<T> ptr)
85{
86 sqlite3_result_pointer(ctx, ptr.release(), typeid(T).name(), +[](void * ptr){delete static_cast<T*>(ptr);});
87}
88
89template<typename T>
90inline void tag_invoke(set_result_tag, sqlite3_context * ctx, std::unique_ptr<T, void(*)(T*)> ptr)
91{
92 sqlite3_result_pointer(ctx, ptr.release(), typeid(T).name(), static_cast<void(*)(void*)>(ptr.get_deleter()));
93}
94
95template<typename T, typename Deleter>
96inline auto tag_invoke(set_result_tag, sqlite3_context * ctx, std::unique_ptr<T> ptr)
97 -> typename std::enable_if<std::is_empty<Deleter>::value &&
98 std::is_default_constructible<Deleter>::value>::type
99{
100 sqlite3_result_pointer(ctx, ptr.release(), typeid(T).name(), +[](void * ptr){Deleter()(static_cast<T*>(ptr));});
101}
102
103inline void tag_invoke(set_result_tag tag, sqlite3_context * ctx, error err)
104{
105 sqlite3_result_error_code(ctx, err.code);
106 if (err.info)
107 sqlite3_result_error(ctx, err.info.message().c_str(), -1);
108}
109
110
111template<typename T>
112inline void tag_invoke(set_result_tag tag, sqlite3_context * ctx, result<T> res)
113{
114 if (res.has_value())
115 tag_invoke(tag, ctx, std::move(res).value());
116 else
117 tag_invoke(tag, ctx, std::move(res).error());
118}
119
120inline void tag_invoke(set_result_tag tag, sqlite3_context * ctx, result<void> res)
121{
122 if (res.has_error())
123 tag_invoke(tag, ctx, std::move(res).error());
124}
125
126
127namespace detail
128{
129
130template<typename Value>
131inline auto set_result(sqlite3_context * ctx, Value && value)
132 -> decltype(tag_invoke(set_result_tag{}, ctx, std::forward<Value>(value)))
133{
134 tag_invoke(set_result_tag{}, ctx, std::forward<Value>(value));
135}
136
137
138}
139
140
141BOOST_SQLITE_END_NAMESPACE
142
143#endif //BOOST_SQLITE_RESULT_HPP