DCL 3.7.4
Loading...
Searching...
No Matches
SqTypes.cpp
Go to the documentation of this file.
1#include <dcl/Config.h>
2
3#include <errno.h> // errno
4#include <stdlib.h> // strol
5#include <string.h> // memset
6
7#include <sqlite3.h>
8
9#include <dcl/Object.h>
10#if __DCL_HAVE_ALLOC_DEBUG
11#undef __DCL_ALLOC_LEVEL
12#define __DCL_ALLOC_LEVEL __DCL_ALLOC_INTERNAL
13#endif
14
15#include <dcl/SQLCore.h>
16#include "SqTypes.h"
17
18#define __TRACE_THIS 0
19#if __TRACE_THIS
20#define __DCL_TRACE0_N __DCL_TRACE0
21#define __DCL_TRACE1_N __DCL_TRACE1
22#define __DCL_TRACE2_N __DCL_TRACE2
23#define __DCL_TRACE3_N __DCL_TRACE3
24#define __DCL_TRACE4_N __DCL_TRACE4
25#else
26#define __DCL_TRACE0_N(fmt)
27#define __DCL_TRACE1_N(fmt, arg)
28#define __DCL_TRACE2_N(fmt, arg1, arg2)
29#define __DCL_TRACE3_N(fmt, arg1, arg2, arg3)
30#define __DCL_TRACE4_N(fmt, arg1, arg2, arg3, arg4)
31#endif
32
33#if __DCL_HAVE_THIS_FILE__
34#undef __THIS_FILE__
35static const char_t __THIS_FILE__[] = __T("dcl/sql/SqTypes.cpp");
36#endif
37
38__DCL_BEGIN_NAMESPACE
39
40static int32_t __fraction_normalize(long _n)
41{
42 if (_n > 999999999) {
43 // fraction이 999,999,999 보다 크면 오류값이다.
44 _n = 0;
45 }
46 int divider = 10;
47 for (; ; ) {
48 if (!(_n / divider))
49 break;
50 divider *= 10;
51 }
52 return _n * (1000000000 / divider);
53}
54
56 const char* _s, const char** _endptr,
58)
59{
60 __DCL_ASSERT(_s);
61#ifndef __DCL_DEBUG
62 if (!_s) {
63 if (_endptr) {
64 *_endptr = _s;
65 }
66 return false;
67 }
68#endif
69
70#define __START 0
71#define __yyyy 1
72#define __MM 2
73#define __dd 3
74#define __HH 4
75#define __mm 5
76#define __ss 6
77#define __SSS 7
78#define __ZH 8
79#define __Zm 9
80#define __Zs 10
81#define __BC 11
82#define __DONE 12
83
84 int state = __START; // yyyy-MM-dd'T'HH:mm:ss.SSSZ
85 memset(&_r, 0, sizeof(_r));
86 _r.tzoff = INT16_MIN;
87
88 bool r = true;
89 char* endptr = (char*)_s;
90 for (; ; ) {
91 errno = 0;
92 const char* nptr = endptr;
93 long n = strtol(nptr, &endptr, 10);
94 if (errno == ERANGE) {
95 // invalid string
96 r = false;
97 break;
98 }
99 if (state == __START) {
100 if (*endptr == '-') {
101 state = __yyyy;
102 }
103 else if (*endptr == ':') {
104 state = __HH;
105 }
106 else {
107 // invalid string
108 r = false;
109 break;
110 }
111 }
112 else if (*endptr == 'B') {
113 state = __BC;
114 }
115 else {
116 // '\0' == *endptr || strchr("- T:.+", *endptr)
117 state++;
118 }
119
120 __DCL_TRACE4_N(L"state[%2d] n[%10d] [%p][%hc]\n",
121 state, n, endptr, *endptr ? *endptr : '$');
122 switch (state) {
123 case __yyyy:
124 _r.year = (int16_t)n;
125 break;
126 case __MM:
127 _r.month = (uint8_t)n;
128 break;
129 case __dd:
130 _r.day = (uint8_t)n;
131 break;
132 case __HH:
133 _r.hour = (uint8_t)n;
134 break;
135 case __mm:
136 _r.min = (uint8_t)n;
137 break;
138 case __ss:
139 _r.sec = (uint8_t)n;
140 break;
141 case __SSS:
142 _r.frac = __fraction_normalize(n);
143 break;
144 case __ZH:
145 _r.tzoff = (int16_t)(n * 60);
146 break;
147 case __Zm:
148 _r.tzoff += (int16_t)n;
149 break;
150 case __Zs:
151 // +08:27:52 BC PostgreSQL Bug!! ignore
152 break;
153 case __BC: {
154 __DCL_ASSERT(*(endptr + 1) == 'C');
155 _r.year *= -1;
156 state = __DONE;
157 break;
158 }
159 default: {
160 __DCL_ASSERT(false);
161 }
162 }
163
164 if (*endptr == '\0' || state == __DONE) {
165 break;
166 }
167 else {
168 __DCL_TRACE1_N(L"[%hs]\n", (*endptr ? endptr : "(nil)"));
169 if ((state == __ss || state == __SSS)
170 && (*endptr == '+' || *endptr == '-')
171 ) {
172 state = __SSS;
173 // 부호와 함께 strtol 후 __ZH 상태가 된다.
174 }
175 else {
176 endptr++;
177 }
178 }
179 }
180
181 if (_endptr) {
182 *_endptr = endptr;
183 }
184 return r;
185}
186
188 const char* _s, const char** _endptr,
189 SQL::Interval& _r
190)
191{
192 __DCL_ASSERT(_s);
193#ifndef __DCL_DEBUG
194 if (!_s) {
195 if (_endptr) {
196 *_endptr = _s;
197 }
198 return false;
199 }
200#endif
201
202 if (*_s != 'P') {
203 // invalid string
204 if (_endptr) {
205 *_endptr = _s;
206 }
207 return false;
208 }
209 _s++;
210
211#define __P0 0
212#define __PT 1
213#define __PTDOT 2
214#define __PDONE 3
215
216 bool r = true;
217 int state = __P0; // P3Y6M4DT12H30M5S
218 memset(&_r, 0, sizeof(_r));
219
220 char dotsign = '+'; // '.'에서 부호를 보관해야 SSS 사용할 수 있다.
221 char* endptr = (char*)_s;
222 for (; ; ) {
223 errno = 0;
224 const char* nptr = endptr;
225 long n = strtol(nptr, &endptr, 10);
226 if (errno == ERANGE) {
227 // invalid string
228 r = false;
229 break;
230 }
231 __DCL_TRACE4_N(L"state[%d] [%p][%hc] [%d]\n",
232 state, endptr, (*endptr ? *endptr : '$'), n);
233 switch (*endptr) {
234 case 'Y':
235 _r.years = (int32_t)n;
236 break;
237 case 'M':
238 if (state == __PT) {
239 _r.mins = (int8_t)n;
240 }
241 else {
242 _r.months = (int8_t)n;
243 }
244 break;
245 case 'D':
246 _r.days = (int32_t)n;
247 break;
248 case 'T':
249 state = __PT;
250 break;
251 case 'H':
252 _r.hours = (int8_t)n;
253 break;
254 case '.':
255 state = __PTDOT;
256 dotsign = *nptr;
257 _r.secs = (int8_t)n;
258 break;
259 case 'S': {
260 if (state == __PTDOT) {
261 _r.fracs = __fraction_normalize(n)
262 * (dotsign == '-' ? -1 : 1);
263 }
264 else {
265 _r.secs = (int8_t)n;
266 }
267 state = __PDONE;
268 break;
269 }
270 case '\0': {
271 state = __PDONE;
272 break;
273 }
274 default: {
275 // invalid string
276 r = false;
277 state = __PDONE;
278 }
279 }
280
281 if (state == __PDONE) {
282 break;
283 }
284 else {
285 endptr++;
286 }
287 }
288
289 if (_endptr) {
290 *_endptr = endptr;
291 }
292 return r;
293}
294
295#define SQLTYPE_NAME(_type, _name) case _type : return L ## _name
296
297const wchar_t* __dataTypeName(int _type)
298{
299 switch (_type) {
300 SQLTYPE_NAME(SQLITE_INTEGER, "INTEGER"); // 1
301 SQLTYPE_NAME(SQLITE_FLOAT, "FLOAT"); // 2
302 SQLTYPE_NAME(SQLITE_TEXT, "TEXT"); // 3
303 SQLTYPE_NAME(SQLITE_BLOB, "BLOB"); // 4
304 SQLTYPE_NAME(SQLITE_NULL, "NULL"); // 5
305 default: return L"Unknown Type (Binary Mapped)";
306 }
307}
308
309typedef sqlite_int64 i64;
310
311struct DateTime {
312 sqlite3_int64 iJD; /* The julian day number times 86400000 */
313 int Y, M, D; /* Year, month, and day */
314 int h, m; /* Hour and minutes */
315 int tz; /* Timezone offset in minutes */
316 double s; /* Seconds */
317 int ms;
318};
319
320#define INT_464269060799999 ((((i64)0x1a640)<<32)|0x1072fdff)
321
322static int validJulianDay(sqlite3_int64 iJD) {
323 return iJD >= 0 && iJD <= INT_464269060799999;
324}
325
326static void computeYMD_HMS(DateTime* p)
327{
328 int Z, alpha, A, B, C, D, E, X1;
329 Z = (int)((p->iJD + 43200000) / 86400000);
330 alpha = (int)((Z + 32044.75) / 36524.25) - 52;
331 A = Z + 1 + alpha - ((alpha + 100) / 4) + 25;
332 B = A + 1524;
333 C = (int)((B - 122.1) / 365.25);
334 D = (36525 * (C & 32767)) / 100;
335 E = (int)((B - D) / 30.6001);
336 X1 = (int)(30.6001 * E);
337 p->D = B - D - X1;
338 p->M = E < 14 ? E - 1 : E - 13;
339 p->Y = p->M > 2 ? C - 4716 : C - 4715;
340
341 int day_ms, day_min;
342 day_ms = (int)((p->iJD + 43200000) % 86400000);
343 p->s = (day_ms % 60000) / 1000.0;
344 day_min = day_ms / 60000;
345 p->m = day_min % 60;
346 p->h = day_min / 60;
347
348 p->ms = day_ms % 1000;
349}
350
351// See. sqlite3.c: juliandayFunc
352// x.iJD/86400000.0
353
355{
356 DateTime dt;
357 // setRawDateNumber
358 dt.iJD = (sqlite3_int64)(_julianday * 86400000.0 + 0.5);
359 if (!validJulianDay(dt.iJD)) {
360 return false;
361 }
362 computeYMD_HMS(&dt);
363
364 _r.year = dt.Y;
365 _r.month = dt.M;
366 _r.day = dt.D;
367
368 _r.hour = dt.h;
369 _r.min = dt.m;
370 _r.sec = (uint8_t) dt.s;
371 _r.frac = dt.ms * 1000000;
372 _r.tzoff = INT16_MIN;
373
374 return true;
375}
376
377// See. sqlite3.c: unixepochFunc, datetimeFunc
378// x.iJD/1000 - 21086676*(i64)10000
379
380bool __decode_timestamp_unixepoch(int64_t _unixepoch, SQL::TimeStamp& _r)
381{
382 DateTime dt;
383 dt.iJD = (_unixepoch + 21086676 * (i64)10000) * 1000;
384 __DCL_TRACE2_N(L"[%lld] [%lld]\n", _unixepoch, dt.iJD);
385 if (!validJulianDay(dt.iJD)) {
386 return false;
387 }
388 computeYMD_HMS(&dt);
389
390 _r.year = dt.Y;
391 _r.month = dt.M;
392 _r.day = dt.D;
393
394 _r.hour = dt.h;
395 _r.min = dt.m;
396 _r.sec = (uint8_t)dt.s;
397 _r.frac = dt.ms * 1000000;
398 _r.tzoff = INT16_MIN;
399
400 return true;
401}
402
403__DCL_END_NAMESPACE
#define __THIS_FILE__
Definition _trace.h:14
wchar_t char_t
Definition Config.h:247
#define INT16_MIN
Definition Config.h:284
IOException *size_t r
Definition MediaInfo.cpp:82
#define __DCL_ASSERT(expr)
Definition Object.h:394
#define __T(str)
Definition Object.h:60
#define __SSS
#define __DONE
#define __PTDOT
#define __yyyy
#define __Zm
#define __MM
#define __P0
#define __BC
#define __dd
#define __mm
#define __START
#define __PDONE
#define __Zs
#define __ZH
#define __HH
#define __PT
#define __ss
#define __DCL_TRACE4_N(fmt, arg1, arg2, arg3, arg4)
Definition SqTypes.cpp:30
const wchar_t * __dataTypeName(int _type)
Definition SqTypes.cpp:297
sqlite_int64 i64
Definition SqTypes.cpp:309
bool __decode_timestamp_julianday(double _julianday, SQL::TimeStamp &_r)
Definition SqTypes.cpp:354
bool __decode_timestamp_iso(const char *_s, const char **_endptr, SQL::TimeStamp &_r)
Definition SqTypes.cpp:55
#define SQLTYPE_NAME(_type, _name)
Definition SqTypes.cpp:295
bool __decode_timestamp_unixepoch(int64_t _unixepoch, SQL::TimeStamp &_r)
Definition SqTypes.cpp:380
#define __DCL_TRACE1_N(fmt, arg)
Definition SqTypes.cpp:27
#define __DCL_TRACE2_N(fmt, arg1, arg2)
Definition SqTypes.cpp:28
bool __decode_interval_iso(const char *_s, const char **_endptr, SQL::Interval &_r)
Definition SqTypes.cpp:187
#define INT_464269060799999
Definition SqTypes.cpp:320
double s
Definition SqTypes.cpp:316
sqlite3_int64 iJD
Definition SqTypes.cpp:312
int32_t years
Definition SQLCore.h:126
int32_t days
Definition SQLCore.h:128
int8_t hours
Definition SQLCore.h:129
int8_t mins
Definition SQLCore.h:130
int32_t fracs
Definition SQLCore.h:132
int8_t months
Definition SQLCore.h:127
int8_t secs
Definition SQLCore.h:131
uint32_t frac
Definition SQLCore.h:118
int16_t tzoff
Definition SQLCore.h:119
uint8_t min
Definition SQLCore.h:116
uint8_t sec
Definition SQLCore.h:117
uint8_t hour
Definition SQLCore.h:115
uint8_t day
Definition SQLCore.h:114
int16_t year
Definition SQLCore.h:112
uint8_t month
Definition SQLCore.h:113