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