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 std::ostream& operator<< (std::ostream& stm, const sl3::Value& v);
232 : :
233 : : friend bool value_type_eq (const Value& a, const Value& b) noexcept;
234 : : friend bool value_type_lt (const Value& a, const Value& b) noexcept;
235 : :
236 : : friend bool value_eq (const Value& a, const Value& b) noexcept;
237 : : friend bool value_lt (const Value& a, const Value& b) noexcept;
238 : :
239 : : /**
240 : : * \brief swap function
241 : : *
242 : : * Independent of the type, a Value is always swappable.
243 : : *
244 : : * \param other value to swap with
245 : : */
246 : : void swap (Value& other) noexcept;
247 : :
248 : : private:
249 : : Type _type{Type::Null};
250 : :
251 : : // that's the type for the union and what is applied in the db
252 : : union Store
253 : : {
254 : 1416 : Store () {}
255 : 1416 : ~Store () {}
256 : : int64_t intval;
257 : : double realval;
258 : : std::string textval;
259 : : Blob blobval;
260 : : };
261 : :
262 : : Store _store;
263 : : };
264 : :
265 : : /**
266 : : * \brief Stream op for a Value
267 : : *
268 : : * \param stm an outstream
269 : : * \param v the value to stream
270 : : * \return ostream
271 : : */
272 : : std::ostream& operator<< (std::ostream& stm, const sl3::Value& v);
273 : :
274 : : /**
275 : : * \brief equality, including type info
276 : : *
277 : : * Check if 2 Value instances are of the same type and of the same value.
278 : : *
279 : : * \param a first element to compare
280 : : * \param b second element to compare
281 : : *
282 : : * \return true if the type and the current value are equal, false otherwise
283 : : */
284 : : bool value_type_eq (const Value& a, const Value& b) noexcept;
285 : :
286 : : /**
287 : : * \brief less than, including type info
288 : : *
289 : : * Applies following rules which are equal to the sorting rules of sqlite.
290 : : *
291 : : * - Type::Null is always less than any other storage type.
292 : : * -
293 : : * Type::Integer or Type::Real
294 : : * -- if the type is different, but the
295 : : * value is equal,
296 : : * then Type::Int < Type::Real.
297 : : * if this is
298 : : * unwanted, use the weak_lt function.
299 : : * -- always less than Type::Text or Type::Blob
300 : : * - Type::Text is less than Type::Blob
301 : : *
302 : : * The comparison of the value itself is implemented via std::less.
303 : : *
304 : : * \param a first element to compare
305 : : * \param b second element to compare
306 : : *
307 : : * \returns true if given Value a is less than given Value b
308 : : */
309 : : bool value_type_lt (const Value& a, const Value& b) noexcept;
310 : :
311 : : /**
312 : : * \brief equality, ignoring type info
313 : : *
314 : : * Compares only the stored value and ignores type information.
315 : : *
316 : : * \param a first value to compare
317 : : * \param b second value to compare
318 : : * \return the comparison result
319 : : */
320 : : bool value_eq (const Value& a, const Value& b) noexcept;
321 : :
322 : : /**
323 : : * \brief less than, ignoring type info
324 : : *
325 : : * Compares only the stored value and ignores type information.
326 : : *
327 : : * \param a first value to compare
328 : : * \param b second value to compare
329 : : * \return the comparison result
330 : : */
331 : : bool value_lt (const Value& a, const Value& b) noexcept;
332 : :
333 : : /**
334 : : * \brief Value specialized swap function
335 : : *
336 : : * Independent of the type, a Value is always swappable.
337 : : *
338 : : * \param a first value to swap with second value
339 : : * \param b second value to swap with first value
340 : : */
341 : : void swap (Value& a, Value& b) noexcept;
342 : :
343 : : /// Define a constant for a Value that is null
344 : : // static const Value NullValue{};
345 : : }
346 : :
347 : : namespace std
348 : : { // only allowed to extend namespace std with specializations
349 : :
350 : : template <> // specialization
351 : : inline void
352 : 1 : swap<sl3::Value> (sl3::Value& lhs, sl3::Value& rhs)
353 : : {
354 : 1 : sl3::swap (lhs, rhs);
355 : 1 : }
356 : : }
357 : :
358 : : #endif
|