Branch data Line data Source code
1 : : /******************************************************************************
2 : : ------------- Copyright (c) 2009-2023 H a r a l d A c h i t z ---------------
3 : : ---------- < h a r a l d dot a c h i t z at g m a i l dot c o m > ------------
4 : : ---- This Source Code Form is subject to the terms of the Mozilla Public -----
5 : : ---- License, v. 2.0. If a copy of the MPL was not distributed with this -----
6 : : ---------- file, You can obtain one at http://mozilla.org/MPL/2.0/. ----------
7 : : ******************************************************************************/
8 : :
9 : : #ifndef SL3_VALUE_HPP_
10 : : #define SL3_VALUE_HPP_
11 : :
12 : : #include <string>
13 : :
14 : : #include <sl3/config.hpp>
15 : : #include <sl3/error.hpp>
16 : : #include <sl3/types.hpp>
17 : :
18 : : namespace sl3
19 : : {
20 : :
21 : : /**
22 : : * \brief
23 : : *
24 : : * This class models the duck typing sqlite uses.
25 : : * It supports int, real, text, blob and null values.
26 : : *
27 : : * The class has the current type info available.
28 : : *
29 : : *
30 : : */
31 : : class LIBSL3_API Value
32 : : {
33 : : public:
34 : : /**
35 : : * \brief Constructor
36 : : *
37 : : * Creates a Null Value
38 : : */
39 : : Value () noexcept;
40 : :
41 : : /** \brief Constructor
42 : : *
43 : : * This constructor takes an initialization value.
44 : : * \param val
45 : : * initial value
46 : : */
47 : : explicit Value (int val) noexcept;
48 : :
49 : : /**
50 : : * \copydoc Value(int val)
51 : : */
52 : : explicit Value (int64_t val) noexcept;
53 : :
54 : : /**
55 : : * \copydoc Value(int val)
56 : : */
57 : : explicit Value (std::string val) noexcept;
58 : :
59 : : /**
60 : : * \copydoc Value(int val)
61 : : */
62 : : explicit Value (const char* val);
63 : :
64 : : /**
65 : : * \copydoc Value(int val)
66 : : */
67 : : explicit Value (double val) noexcept;
68 : :
69 : : /**
70 : : * \copydoc Value(int val)
71 : : */
72 : : explicit Value (Blob val) noexcept;
73 : :
74 : : /**
75 : : * \brief Destructor
76 : : */
77 : : ~Value () noexcept;
78 : :
79 : : /**
80 : : * \brief Copy constructor
81 : : */
82 : : Value (const Value&) noexcept;
83 : :
84 : : /**
85 : : * \brief Move constructor
86 : : */
87 : : Value (Value&&) noexcept;
88 : :
89 : : /** \brief Assignment
90 : : * \throw sl3::ErrTypeMisMatch if getType is incompatible
91 : : * \note , only value assignment happens here,
92 : : * the type does not change; the storage type might change if the type is
93 : : * a variant.
94 : : *
95 : : * \param val new value
96 : : * \return reference to this
97 : : */
98 : : Value& operator= (const Value& val);
99 : :
100 : : /**
101 : : * \copydoc operator=(const Value& val)
102 : : */
103 : : Value& operator= (Value&& val);
104 : :
105 : : /**
106 : : * \copydoc operator=(const Value& val)
107 : : */
108 : : Value& operator= (int val);
109 : :
110 : : /**
111 : : * \copydoc operator=(const Value& val)
112 : : */
113 : : Value& operator= (const int64_t& val);
114 : :
115 : : /**
116 : : * \copydoc operator=(const Value& val)
117 : : */
118 : : Value& operator= (const double& val);
119 : :
120 : : /**
121 : : * \copydoc operator=(const Value& val)
122 : : */
123 : : Value& operator= (const std::string& val);
124 : :
125 : : /**
126 : : * \copydoc operator=(const Value& val)
127 : : */
128 : : Value& operator= (const Blob& val);
129 : :
130 : : /** \brief Implicit conversion operator
131 : : * \throw sl3::ErrNullValueAccess if value is null.
132 : : * \throw sl3::ErrTypeMisMatch if getType is incompatible
133 : : * \throw sl3::ErrOutOfRange if the stored value is an int64_t
134 : : *
135 : : * \return the value
136 : : */
137 : : explicit operator int () const;
138 : :
139 : : /** \brief Implicit conversion operator
140 : : * \throw sl3::ErrNullValueAccess if value is null.
141 : : * \throw sl3::ErrTypeMisMatch if getType is incompatible
142 : : * \return the value
143 : : */
144 : : explicit operator int64_t () const;
145 : :
146 : : /** \brief Implicit conversion operator
147 : : * \throw sl3::ErrNullValueAccess if value is null.
148 : : * \throw sl3::ErrTypeMisMatch if getType is incompatible
149 : : * \throw sl3::ErrOutOfRange if the stored value is an int64_t and out of
150 : : * the min or max double range.
151 : : * \return the value
152 : : */
153 : : explicit operator double () const;
154 : :
155 : : /** \brief Implicit conversion operator
156 : : * \throw sl3::ErrNullValueAccess if value is null.
157 : : * \throw sl3::ErrTypeMisMatch if getType is incompatible
158 : : * \return the value
159 : : */
160 : : explicit operator const std::string&() const; // TODO ref or val
161 : :
162 : : /** \brief Implicit conversion operator
163 : : * \throw sl3::ErrNullValueAccess if value is null.
164 : : * \throw sl3::ErrTypeMisMatch if getType is incompatible
165 : : * \return the value
166 : : */
167 : : explicit operator const Blob&() const; // TODO ref or val
168 : :
169 : : /** \brief Access the value
170 : : * \throw sl3::ErrNullValueAccess if value is null.
171 : : * \throw sl3::ErrTypeMisMatch if the current value has a different type.
172 : : * \return reference to the value
173 : : */
174 : : const int64_t& int64 () const;
175 : :
176 : : /** \brief Access the value
177 : : * \throw sl3::ErrNullValueAccess if value is null.
178 : : * \throw sl3::ErrTypeMisMatch if the current value has a different type.
179 : : * \return reference to the value
180 : : */
181 : : const double& real () const;
182 : :
183 : : /** \brief Access the value
184 : : * \throw sl3::ErrNullValueAccess if value is null.
185 : : * \throw sl3::ErrTypeMisMatch if the current value has a different type.
186 : : * \return reference to the value
187 : : */
188 : : const std::string& text () const;
189 : :
190 : : /** \brief Access the value
191 : : * \throw sl3::ErrNullValueAccess if value is null.
192 : : * \throw sl3::ErrTypeMisMatch if the current value has a different type.
193 : : * \return reference to the value
194 : : */
195 : : const Blob& blob () const;
196 : :
197 : : /** \brief Moves the current value into the return value
198 : : *
199 : : * After calling this function the value will be Null.
200 : : *
201 : : * \throw sl3::ErrTypeMisMatch in case of wrong type.
202 : : * \return The value
203 : : */
204 : : std::string ejectText ();
205 : :
206 : : /**
207 : : * \copydoc ejectText()
208 : : */
209 : : Blob ejectBlob ();
210 : :
211 : : /**
212 : : * \brief Set to NULL
213 : : */
214 : : void setNull () noexcept;
215 : :
216 : : /**
217 : : * \brief Check Null
218 : : * \return if the value is null
219 : : */
220 : : bool isNull () const noexcept;
221 : :
222 : : /**
223 : : * \brief The Type of the value.
224 : : *
225 : : * \return the type
226 : : */
227 : : Type getType () const noexcept;
228 : :
229 : : // friend bool operator== (const Value& a, const Value& b) noexcept;
230 : : // friend bool operator< (const Value& a, const Value& b) noexcept;
231 : : friend LIBSL3_API std::ostream& operator<< (std::ostream& stm,
232 : : const sl3::Value& v);
233 : :
234 : : friend LIBSL3_API bool value_type_eq (const Value& a,
235 : : const Value& b) noexcept;
236 : : friend LIBSL3_API bool value_type_lt (const Value& a,
237 : : const Value& b) noexcept;
238 : :
239 : : friend LIBSL3_API bool value_eq (const Value& a, const Value& b) noexcept;
240 : : friend LIBSL3_API bool value_lt (const Value& a, const Value& b) noexcept;
241 : :
242 : : /**
243 : : * \brief swap function
244 : : *
245 : : * Independent of the type, a Value is always swappable.
246 : : *
247 : : * \param other value to swap with
248 : : */
249 : : void swap (Value& other) noexcept;
250 : :
251 : : private:
252 : : Type _type{Type::Null};
253 : :
254 : : // that's the type for the union and what is applied in the db
255 : : union Store
256 : : {
257 : 1416 : Store () {}
258 : 1416 : ~Store () {}
259 : : int64_t intval;
260 : : double realval;
261 : : std::string textval;
262 : : Blob blobval;
263 : : };
264 : :
265 : : Store _store;
266 : : };
267 : :
268 : : /**
269 : : * \brief Stream op for a Value
270 : : *
271 : : * \param stm an outstream
272 : : * \param v the value to stream
273 : : * \return ostream
274 : : */
275 : : LIBSL3_API std::ostream& operator<< (std::ostream& stm, const sl3::Value& v);
276 : :
277 : : /**
278 : : * \brief equality, including type info
279 : : *
280 : : * Check if 2 Value instances are of the same type and of the same value.
281 : : *
282 : : * \param a first element to compare
283 : : * \param b second element to compare
284 : : *
285 : : * \return true if the type and the current value are equal, false otherwise
286 : : */
287 : : LIBSL3_API bool value_type_eq (const Value& a, const Value& b) noexcept;
288 : :
289 : : /**
290 : : * \brief less than, including type info
291 : : *
292 : : * Applies following rules which are equal to the sorting rules of sqlite.
293 : : *
294 : : * - Type::Null is always less than any other storage type.
295 : : * -
296 : : * Type::Integer or Type::Real
297 : : * -- if the type is different, but the
298 : : * value is equal,
299 : : * then Type::Int < Type::Real.
300 : : * if this is
301 : : * unwanted, use the weak_lt function.
302 : : * -- always less than Type::Text or Type::Blob
303 : : * - Type::Text is less than Type::Blob
304 : : *
305 : : * The comparison of the value itself is implemented via std::less.
306 : : *
307 : : * \param a first element to compare
308 : : * \param b second element to compare
309 : : *
310 : : * \returns true if given Value a is less than given Value b
311 : : */
312 : : LIBSL3_API bool value_type_lt (const Value& a, const Value& b) noexcept;
313 : :
314 : : /**
315 : : * \brief equality, ignoring type info
316 : : *
317 : : * Compares only the stored value and ignores type information.
318 : : *
319 : : * \param a first value to compare
320 : : * \param b second value to compare
321 : : * \return the comparison result
322 : : */
323 : : LIBSL3_API bool value_eq (const Value& a, const Value& b) noexcept;
324 : :
325 : : /**
326 : : * \brief less than, ignoring type info
327 : : *
328 : : * Compares only the stored value and ignores type information.
329 : : *
330 : : * \param a first value to compare
331 : : * \param b second value to compare
332 : : * \return the comparison result
333 : : */
334 : : LIBSL3_API bool value_lt (const Value& a, const Value& b) noexcept;
335 : :
336 : : /**
337 : : * \brief Value specialized swap function
338 : : *
339 : : * Independent of the type, a Value is always swappable.
340 : : *
341 : : * \param a first value to swap with second value
342 : : * \param b second value to swap with first value
343 : : */
344 : : LIBSL3_API void swap (Value& a, Value& b) noexcept;
345 : :
346 : : /// Define a constant for a Value that is null
347 : : // static const Value NullValue{};
348 : : }
349 : :
350 : : namespace std
351 : : { // only allowed to extend namespace std with specializations
352 : :
353 : : template <> // specialization
354 : : inline void
355 : 1 : swap<sl3::Value> (sl3::Value& lhs, sl3::Value& rhs)
356 : : {
357 : 1 : sl3::swap (lhs, rhs);
358 : 1 : }
359 : : }
360 : :
361 : : #endif
|