kDB: Knowledge DataBase
Loading...
Searching...
No Matches
BinaryInterface_read_p.h
1#include <arpa/inet.h>
2
3#include <knowCore/Timestamp.h>
4
5#include <QJsonArray>
6#include <QJsonDocument>
7#include <QJsonObject>
8#include <QJsonValue>
9
10#include "BinaryInterfaceTimeStamp_p.h"
11#include <clog_qt>
12#include <knowCore/Array.h>
13#include <knowCore/BigNumber.h>
14#include <knowCore/Vector.h>
15
16namespace kDB::Repository::DatabaseInterface::PostgreSQL::BinaryInterface
17{
18 template<typename _T_>
20
21 template<typename _T_>
22 inline _T_ read(const char* data, int _size)
23 {
24 return read_details<_T_>::do_read(data, _size);
25 }
26
27 template<>
28 inline qint64 read<qint64>(const char* data, int _size)
29 {
30 clog_assert(_size == sizeof(qint64));
31 qint32 h32 = *(qint32*)data;
32 qint32 l32 = *(qint32*)(data + 4);
33
34 qint64 result;
35 result = ntohl(h32);
36 result <<= 32;
37 result |= ntohl(l32);
38
39 return result;
40 }
41 template<>
42 inline quint64 read<quint64>(const char* data, int _size)
43 {
44 clog_assert(_size == sizeof(quint64));
45 return read<qint64>(data, _size);
46 }
47 template<>
48 inline qint32 read<qint32>(const char* data, int _size)
49 {
50 clog_assert(_size == sizeof(qint32));
51 return ntohl(*(qint32*)data);
52 }
53 template<>
54 inline quint32 read<quint32>(const char* data, int _size)
55 {
56 clog_assert(_size == sizeof(quint32));
57 return read<qint32>(data, _size);
58 }
59 template<>
60 inline qint16 read<qint16>(const char* data, int _size)
61 {
62 clog_assert(_size == sizeof(qint16));
63 return ntohs(*(qint16*)data);
64 }
65 template<>
66 inline quint16 read<quint16>(const char* data, int _size)
67 {
68 clog_assert(_size == sizeof(quint16));
69 return read<qint16>(data, _size);
70 }
71 template<>
72 inline char read<char>(const char* data, int _size)
73 {
74 clog_assert(_size == sizeof(char));
75 return *data;
76 }
77 template<>
78 inline bool read<bool>(const char* data, int _size)
79 {
80 clog_assert(_size == 1);
81 return *data != 0;
82 }
83 template<>
84 inline float read<float>(const char* data, int _size)
85 {
86 clog_assert(_size == sizeof(float));
87 union
88 {
89 float f;
90 qint32 i;
91 } swap;
92 swap.i = read<qint32>(data, _size);
93 return swap.f;
94 }
95 template<>
96 inline double read<double>(const char* data, int _size)
97 {
98 clog_assert(_size == sizeof(double));
99 union
100 {
101 double f;
102 qint64 i;
103 } swap;
104 swap.i = read<qint64>(data, _size);
105 return swap.f;
106 }
107
108 template<>
109 inline knowCore::Timestamp read<knowCore::Timestamp>(const char* data, int _size)
110 {
111 clog_assert(_size == sizeof(qint64));
112 qint64 timestamp = read<qint64>(data, _size);
113 fsec_t fsec;
114 struct pg_tm tt;
115 if(BinaryInterface::timestamp2tm(timestamp, &tt, &fsec, NULL) == 0)
116 {
117 return knowCore::Timestamp::from(
118 QDateTime(QDate(tt.tm_year, tt.tm_mon, tt.tm_mday),
119 QTime(tt.tm_hour, tt.tm_min, tt.tm_sec, fsec / 1000)));
120 }
121 else
122 {
123 return knowCore::Timestamp();
124 }
125 }
126
127 template<>
128 inline QString read<QString>(const char* data, int _size)
129 {
130 return QString::fromUtf8(data, _size);
131 }
132
133 // template<>
134 // inline QStringList read<QStringList>(const char* data, int _size)
135 // {
136 // return read<QList<QString>>(data, _size);
137 // }
138 template<>
139 inline QByteArray read<QByteArray>(const char* data, int _size)
140 {
141 return QByteArray(data, _size);
142 }
143
144 template<>
145 inline knowCore::BigNumber read<knowCore::BigNumber>(const char* data, int _size)
146 {
147 Q_UNUSED(_size);
148 quint16 ndigits = BinaryInterface::read<quint16>(data, 2);
149 data += 2;
150 quint16 weight = BinaryInterface::read<quint16>(data, 2);
151 data += 2;
152 quint16 sign = BinaryInterface::read<quint16>(data, 2);
153 data += 2;
154 knowCore::BigNumber::Sign sign_bn;
155 switch(sign)
156 {
157 case 0x4000: // NUMERIC_NEG
158 sign_bn = knowCore::BigNumber::Sign::Negative;
159 break;
160 case 0x0000: // NUMERIC_POS
161 sign_bn = knowCore::BigNumber::Sign::Positive;
162 break;
163 case 0xF000: // NUMERIC_NEG
164 sign_bn = knowCore::BigNumber::Sign::NegativeInfinite;
165 break;
166 case 0xD000: // NUMERIC_POS
167 sign_bn = knowCore::BigNumber::Sign::PositiveInfinite;
168 break;
169 default:
170 sign_bn = knowCore::BigNumber::Sign::NaN;
171 break;
172 }
173 qint16 dscale = BinaryInterface::read<quint16>(data, 2);
174 data += 2;
175 QList<quint16> digits;
176 digits.reserve(ndigits);
177 for(int i = 0; i < ndigits; ++i)
178 {
179 digits.append(BinaryInterface::read<quint16>(data, 2));
180 data += 2;
181 }
182 return knowCore::BigNumber(weight, sign_bn, dscale, digits);
183 }
184
185 template<typename _T_>
186 struct read_details<knowCore::Array<_T_>>
187 {
188 static knowCore::Array<_T_> do_read(const char* data, int _size)
189 {
190 Q_UNUSED(_size);
191
192 qint32 ndim = read<qint32>(data, 4);
193 data += 4;
194
195 if(ndim == 0)
196 return knowCore::Array<_T_>();
197
198 qint32 has_null = read<qint32>(data, 4);
199 data += 4;
200 Oid type = read<Oid>(data, 4);
201 data += 4;
202 Q_UNUSED(has_null);
203 Q_UNUSED(type);
204
205 Q_UNUSED(ndim);
206
207 QList<qsizetype> dimensions;
208 int total_dim = 1;
209 for(int i = 0; i < ndim; ++i)
210 {
211 qint32 dim = read<qint32>(data, 4);
212 data += 4;
213 qint32 lbound = read<qint32>(data, 4);
214 data += 4;
215 Q_UNUSED(lbound);
216 dimensions.append(dim);
217 total_dim *= dim;
218 }
219
220 Q_UNUSED(total_dim);
221 QVector<_T_> r_data;
222 r_data.reserve(total_dim);
223
224 for(int i = 0; i < total_dim; ++i)
225 {
226 std::size_t s = read<qint32>(data, 4);
227 ;
228 data += 4;
229 r_data.append(read<_T_>(data, s));
230 data += s;
231 }
232 return knowCore::Array<_T_>(r_data, dimensions);
233 }
234 };
235 template<typename _T_>
236 struct read_details<QList<_T_>>
237 {
238 static QList<_T_> do_read(const char* _data, int _size)
239 {
240 return read<knowCore::Array<_T_>>(_data, _size).toList().expect_success();
241 }
242 };
243 // Json
244 template<>
245 inline QJsonArray read<QJsonArray>(const char* _data, int _size)
246 {
247 Q_UNUSED(_data);
248 Q_UNUSED(_size);
249 qFatal("should not called");
250 }
251 template<>
252 inline QJsonObject read<QJsonObject>(const char* _data, int _size)
253 {
254 Q_UNUSED(_data);
255 Q_UNUSED(_size);
256 qFatal("should not called");
257 }
258 template<>
259 inline QJsonValue read<QJsonValue>(const char* _data, int _size)
260 {
261 QByteArray doc_data(_data, _size);
262 QJsonDocument doc = QJsonDocument::fromJson(doc_data);
263 if(doc.isEmpty() or doc.isNull())
264 {
265 if(_size > 0)
266 {
267 return QJsonValue(QString::fromUtf8(doc_data));
268 }
269 else
270 {
271 return QJsonValue();
272 }
273 }
274 else if(doc.isArray())
275 {
276 return doc.array();
277 }
278 else if(doc.isObject())
279 {
280 return doc.object();
281 }
282 return QJsonValue();
283 }
284 namespace details
285 {
286 template<int _N_, typename... T>
288 {
289 static void do_read(std::tuple<T...>* data, const char* ptr)
290 {
291 ptr += 4; // skip oid TODO find a way to validate
292 quint32 s = read<quint32>(ptr, 4);
293 ptr += 4;
294 std::get<sizeof...(T) - _N_>(*data)
295 = read<std::remove_reference_t<decltype(std::get<sizeof...(T) - _N_>(*data))>>(ptr, s);
297 }
298 };
299 template<typename... T>
300 struct struct_reader<0, T...>
301 {
302 static void do_read(std::tuple<T...>* data, const char* ptr)
303 {
304 Q_UNUSED(data);
305 Q_UNUSED(ptr);
306 }
307 };
308 } // namespace details
309 template<typename... T>
311 {
312 struct_reader() {}
313
314 void read(const char* ptr)
315 {
316 quint32 f = BinaryInterface::read<quint32>(ptr, 4);
317 clog_assert(f == sizeof...(T));
318 ptr += 4;
319 details::struct_reader<sizeof...(T), T...>::do_read(&data, ptr);
320 }
321
322 std::tuple<T...> data;
323 };
324
325 template<typename... T>
326 struct read_details<std::tuple<T...>>
327 {
328 static std::tuple<T...> do_read(const char* data, int /*_size*/)
329 {
330 struct_reader<T...> sr;
331 sr.read(data);
332 return sr.data;
333 }
334 };
335} // namespace kDB::Repository::DatabaseInterface::PostgreSQL::BinaryInterface
Definition Revision.h:9
Definition Array.h:16
Class that can contains large numeric value.
Definition BigNumber.h:51
Definition Timestamp.h:39