kDB: Knowledge DataBase
Loading...
Searching...
No Matches
BinaryInterface_write_p.h
1#include <knowCore/BigNumber.h>
2#include <knowCore/Array.h>
3#include <knowCore/Vector.h>
4
5#include <QJsonArray>
6#include <QJsonDocument>
7#include <QJsonObject>
8#include <QJsonValue>
9
10#include "postgresql_p.h"
11
12#include "BinaryInterface_traits_p.h"
13
14namespace kDB::Repository::DatabaseInterface::PostgreSQL::BinaryInterface
15{
16 template<typename _T_>
18 {
19 static inline std::size_t do_calculate_size(const _T_&)
20 {
21 return sizeof(_T_);
22 }
23 };
24
25 template<typename _T_>
26 inline std::size_t calculate_size(const _T_& _v)
27 {
29 }
30
31 template<typename _T_>
32 inline void write(const _T_& _value, char* _data)
33 {
34 write_details<_T_>::do_write(_value, _data);
35 }
36
37 template<typename _T_>
38 inline void write(const _T_& _value, QByteArray* _array)
39 {
40 _array->resize(calculate_size<_T_>(_value));
41 write(_value, _array->data());
42 }
43 template<typename _T_>
44 inline QByteArray write(_T_ _value) Q_REQUIRED_RESULT;
45 template<typename _T_>
46 inline QByteArray write(_T_ _value)
47 {
48 QByteArray r;
49 write<_T_>(_value, &r);
50 return r;
51 }
52
53 template<>
54 inline void write<qint64>(const qint64& _value, char* _data)
55 {
56 qint32* h32 = (qint32*)_data;
57 qint32* l32 = (qint32*)(_data+4);
58
59 *h32 = htonl(_value >> 32);
60 *l32 = htonl(_value & 0xFFFFFFFF);
61 }
62 template<>
63 inline void write<quint64>(const quint64& _value, char* _data)
64 {
65 write<qint64>(_value, _data);
66 }
67 template<>
68 inline void write<qint32>(const qint32& _value, char* _data)
69 {
70 *reinterpret_cast<qint32*>(_data) = htonl(_value);
71 }
72 template<>
73 inline void write<quint32>(const quint32& _value, char* _data)
74 {
75 write<qint32>(_value, _data);
76 }
77 template<>
78 inline void write<qint16>(const qint16& _value, char* _data)
79 {
80 *reinterpret_cast<qint16*>(_data) = htons(_value);
81 }
82 template<>
83 inline void write<quint16>(const quint16& _value, char* _data)
84 {
85 write<qint16>(_value, _data);
86 }
87 template<>
88 inline void write<bool>(const bool& _value, char* _data)
89 {
90 *_data = _value ? 1 : 0;
91 }
92
93 template<>
94 inline void write<float>(const float& _fl, char* data)
95 {
96 union { float f; qint32 i; } swap;
97 swap.f = _fl;
98 write<qint32>(swap.i, data);
99 }
100 template<>
101 inline void write<double>(const double& _fl, char* data)
102 {
103 union { double f; qint64 i; } swap;
104 swap.f = _fl;
105 write<qint64>(swap.i, data);
106 }
107 template<>
108 inline std::size_t calculate_size<knowCore::Timestamp>(const knowCore::Timestamp& _v)
109 {
110 Q_UNUSED(_v);
111 return calculate_size<qint64>(0);
112 }
113 template<>
114 inline void write<knowCore::Timestamp>(const knowCore::Timestamp& _dt, char* _data)
115 {
116 Q_UNUSED(_dt);
117 Q_UNUSED(_data);
118 qFatal("Unimplemented");
119 }
120 template<>
121 inline std::size_t calculate_size<QString>(const QString& _v)
122 {
123 return _v.toUtf8().size();
124 }
125 template<>
126 inline void write<QString>(const QString& _dt, char* data)
127 {
128 QByteArray r = _dt.toUtf8();
129 memcpy(data, r.data(), r.size());
130 }
131
132 template<>
133 inline std::size_t calculate_size<QStringList>(const QStringList& _v)
134 {
135 return calculate_size<QList<QString>>(_v);
136 }
137 template<>
138 inline void write<QStringList>(const QStringList& _dt, char* data)
139 {
140 write<QList<QString>>(_dt, data);
141 }
142
143 template<>
144 inline std::size_t calculate_size<QByteArray>(const QByteArray& _v)
145 {
146 return _v.size();
147 }
148 template<>
149 inline void write<QByteArray>(const QByteArray& _dt, char* data)
150 {
151 std::copy(_dt.begin(), _dt.end(), data);
152 }
153
154 template<>
155 inline void write<knowCore::BigNumber>(const knowCore::BigNumber& _number, char* data)
156 {
157 write<quint16>(_number.digits().size(), data); data += 2;
158 write<quint16>(_number.weight(), data); data += 2;
159 quint16 sign = 0xC000;
160 switch(_number.sign())
161 {
162 case knowCore::BigNumber::Sign::Negative:
163 sign = 0x4000;
164 break;
165 case knowCore::BigNumber::Sign::Positive:
166 sign = 0x0000;
167 break;
168 case knowCore::BigNumber::Sign::NaN:
169 sign = 0xC000;
170 break;
171 case knowCore::BigNumber::Sign::PositiveInfinite:
172 sign = 0xD000;
173 break;
174 case knowCore::BigNumber::Sign::NegativeInfinite:
175 sign = 0xF000;
176 break;
177 }
178 write<quint16>(sign, data); data += 2;
179 write<quint16>(_number.dscale(), data); data += 2;
180
181 for(quint16 d : _number.digits())
182 {
183 write<quint16>(d, data);
184 data += 2;
185 }
186 }
187 template<>
188 inline std::size_t calculate_size<knowCore::BigNumber>(const knowCore::BigNumber& _number)
189 {
190 return (4 + _number.digits().size())*sizeof(quint16);
191 }
192 namespace details {
193 inline char* write_enum(const char* enum_name, char* data)
194 {
195 const std::size_t s = strlen(enum_name);
196 write<quint32>(s, data); data += sizeof(quint32);
197 std::copy(enum_name, enum_name + s, data); data += s;
198 return data;
199 }
200 inline char* write_empty(Oid _oid, char* data)
201 {
202 write<Oid>(_oid, data); data += sizeof(Oid);
203 write<quint32>(0xFFFFFFFF, data); data += sizeof(quint32);
204 return data;
205 }
206 template<typename _T_>
207 inline char* write_value(Oid _oid, const _T_& _value, char* data)
208 {
209 std::size_t s = calculate_size<_T_>(_value);
210 write<Oid>(_oid, data); data += sizeof(Oid);
211 write<quint32>(s, data); data += sizeof(quint32);
212 write<_T_>(_value, data); data += s;
213 return data;
214 }
215 }
216 template<typename _T_>
217 struct write_details<QList<_T_>>
218 {
219 static inline std::size_t do_calculate_size(const QList<_T_>& _val)
220 {
221 std::size_t s = 4 * 5;
222 for(const _T_& t : _val)
223 {
224 s += 4 + calculate_size<_T_>(t);
225 }
226 return s;
227 }
228 static inline void do_write(const QList<_T_>& _value, char* data)
229 {
230 write<quint32>(1, data); data += 4; // ndim
231
232 write<quint32>(0, data); data += 4; // has_null
233 write<quint32>(traits<_T_>::oid(), data); data += 4;
234
235 write<quint32>(_value.size(), data); data += 4;
236 write<quint32>(0, data); data += 4; // lbound
237
238 for(int i = 0; i < _value.size(); ++i)
239 {
240 const _T_& val = _value[i];
241 std::size_t s = calculate_size<_T_>(val);
242 write<quint32>(s, data); data += 4;
243 write<_T_>(val, data);
244 data += s;
245 }
246 }
247 };
248 template<typename _T_, std::size_t _dimension>
249 struct write_details<knowCore::Vector<_T_, _dimension>>
250 {
251 static inline std::size_t do_calculate_size(const knowCore::Vector<_T_, _dimension>& _val)
252 {
253 return 4 * 5 + _dimension * (4 + calculate_size<_T_>(_val[0]));
254 }
255 static inline void do_write(const knowCore::Vector<_T_, _dimension>& _value, char* data)
256 {
257 write<QList<_T_>>(_value, data);
258 }
259 };
260
261 template<typename _T_, std::size_t _dimension>
262 struct write_details<QList<knowCore::Vector<_T_, _dimension>>>
263 {
264 static inline std::size_t do_calculate_size(const QList<knowCore::Vector<_T_, _dimension>>& _val)
265 {
266 std::size_t s = 4 * 7;
267 for(const knowCore::Vector<_T_, _dimension>& t : _val)
268 {
269 for(std::size_t j = 0; j < _dimension; ++j)
270 {
271 s += 4 + calculate_size<_T_>(t[j]);
272 }
273 }
274 return s;
275 }
276 static inline void do_write(const QList<knowCore::Vector<_T_, _dimension>>& _value, char* data)
277 {
278 write<quint32>(2, data); data += 4; // ndim
279
280 write<quint32>(0, data); data += 4; // has_null
281 write<quint32>(traits<_T_>::oid(), data); data += 4;
282
283 write<quint32>(_value.size(), data); data += 4;
284 write<quint32>(0, data); data += 4; // lbound
285 write<quint32>(_dimension, data); data += 4;
286 write<quint32>(0, data); data += 4; // lbound
287
288 for(int i = 0; i < _value.size(); ++i)
289 {
290 const knowCore::Vector<_T_, _dimension>& v = _value[i];
291 for(std::size_t j = 0; j < _dimension; ++j)
292 {
293 std::size_t s = calculate_size<_T_>(v[j]);
294 write<quint32>(s, data); data += 4;
295 write<_T_>(v[j], data);
296 data += s;
297 }
298 }
299 }
300 };
301 template<typename _T_>
302 struct write_details<knowCore::Array<_T_>>
303 {
304 static inline std::size_t do_calculate_size(const knowCore::Array<_T_>& _val)
305 {
306 std::size_t s = 4 * (3 + 2 * _val.dimensions().size());
307 for(const _T_& t : _val.data())
308 {
309 s += 4 + calculate_size<_T_>(t);
310 }
311 return s;
312 }
313 static inline void do_write(const knowCore::Array<_T_>& _value, char* data)
314 {
315 write<quint32>(_value.dimensions().size(), data); data += 4; // ndim
316
317 write<quint32>(0, data); data += 4; // has_null
318 write<quint32>(traits<_T_>::oid(), data); data += 4;
319
320 for(int d : _value.dimensions())
321 {
322 write<quint32>(d, data); data += 4;
323 write<quint32>(0, data); data += 4; // lbound
324 }
325
326 for(const _T_& val : _value.data())
327 {
328 std::size_t s = calculate_size<_T_>(val);
329 write<quint32>(s, data); data += 4;
330 write<_T_>(val, data);
331 data += s;
332 }
333 }
334 };
335
336 // Json
337 template<>
338 inline void write<QJsonDocument>(const QJsonDocument& _document, QByteArray* _array)
339 {
340 write(_document.toJson(QJsonDocument::Compact), _array);
341 }
342 template<>
343 inline void write<QJsonArray>(const QJsonArray& _value, QByteArray* _array)
344 {
345 QJsonDocument doc;
346 doc.setArray(_value);
347 write(doc, _array);
348 }
349 template<>
350 inline void write<QJsonObject>(const QJsonObject& _value, QByteArray* _array)
351 {
352 QJsonDocument doc;
353 doc.setObject(_value);
354 write(doc, _array);
355 }
356 template<>
357 inline void write<QJsonValue>(const QJsonValue& _value, QByteArray* _array)
358 {
359 switch(_value.type())
360 {
361 case QJsonValue::Null:
362 case QJsonValue::Undefined:
363 *_array = QByteArray();
364 break;
365 case QJsonValue::Bool:
366 case QJsonValue::Double:
367 case QJsonValue::String:
368 KNOWCORE_LOG_FATAL("Invalid type of QJsonValue: {}", _value);
369 case QJsonValue::Array:
370 write(_value.toArray(), _array);
371 break;
372 case QJsonValue::Object:
373 write(_value.toObject(), _array);
374 break;
375 }
376 }
377
378 namespace details
379 {
380 template<int _N_, typename... T>
382 {
383 static int do_calculate_size(const std::tuple<T...>& data)
384 {
385 return struct_writer<_N_- 1, T...>::do_calculate_size(data) + calculate_size(std::get<sizeof...(T) - _N_>(data)) + 4 /* oid */ + 4 /* size */;
386 }
387 static void do_write(const std::tuple<T...>& data, char *ptr)
388 {
389 auto v = std::get<sizeof...(T) - _N_>(data);
390 std::size_t s = calculate_size(v);
391 write(traits<decltype(v)>::oid(), ptr);
392 ptr += 4;
393 write(s);
394 ptr += 4;
395 write(v, ptr);
396 ptr += s;
398 }
399 };
400 template<typename... T>
401 struct struct_writer<0, T...>
402 {
403 static int do_calculate_size(std::tuple<T...> data)
404 {
405 Q_UNUSED(data);
406 return 4; // For the fields
407 }
408 static void do_write(const std::tuple<T...>& data, char *ptr)
409 {
410 Q_UNUSED(data);
411 Q_UNUSED(ptr);
412 }
413 };
414 }
415
416 template<typename... T>
418 {
419 struct_writer(Oid oid, T... _t) : m_data(_t...), m_oid(oid) {}
420 int calculate_size() const
421 {
422 return details::struct_writer<sizeof...(T), T...>::do_calculate_size(m_data);
423 }
424 void write(char* ptr) const
425 {
426 BinaryInterface::write<quint32>(sizeof...(T), ptr); ptr += 4;
428 }
429 Oid oid() const
430 {
431 return m_oid;
432 }
433 private:
434 std::tuple<T...> m_data;
435 Oid m_oid;
436 };
437
438 template<typename... T>
440 {
441 static inline std::size_t do_calculate_size(const struct_writer<T...>& _t)
442 {
443 return _t.calculate_size();
444 }
445 static inline void write(const struct_writer<T...>& _value, char* _data)
446 {
447 _value.write(_data);
448 }
449 };
450}
Definition Array.h:16
Class that can contains large numeric value.
Definition BigNumber.h:51
Definition Timestamp.h:39
Definition Vector.h:13