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