Line data Source code
1 : /* FreeTDS - Library of routines accessing Sybase and Microsoft databases
2 : * Copyright (C) 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005 Brian Bruns
3 : * Copyright (C) 2010-2015 Frediano Ziglio
4 : *
5 : * This library is free software; you can redistribute it and/or
6 : * modify it under the terms of the GNU Library General Public
7 : * License as published by the Free Software Foundation; either
8 : * version 2 of the License, or (at your option) any later version.
9 : *
10 : * This library is distributed in the hope that it will be useful,
11 : * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 : * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 : * Library General Public License for more details.
14 : *
15 : * You should have received a copy of the GNU Library General Public
16 : * License along with this library; if not, write to the
17 : * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
18 : * Boston, MA 02111-1307, USA.
19 : */
20 :
21 : #include <config.h>
22 :
23 : #include <stdarg.h>
24 : #include <stdio.h>
25 :
26 : #include <freetds/time.h>
27 :
28 : #include <assert.h>
29 : #include <ctype.h>
30 :
31 : #if HAVE_ERRNO_H
32 : #include <errno.h>
33 : #endif /* HAVE_ERRNO_H */
34 :
35 : #if HAVE_STDLIB_H
36 : #include <stdlib.h>
37 : #endif /* HAVE_STDLIB_H */
38 :
39 : #if HAVE_STRING_H
40 : #include <string.h>
41 : #endif /* HAVE_STRING_H */
42 :
43 : #if HAVE_STRINGS_H
44 : #include <strings.h>
45 : #endif /* HAVE_STRINGS_H */
46 :
47 : #include <freetds/tds.h>
48 : #include <freetds/tds/convert.h>
49 : #include <freetds/bytes.h>
50 : #include <freetds/replacements.h>
51 : #include <freetds/utils.h>
52 : #include <freetds/tds/checks.h>
53 :
54 : typedef unsigned short utf16_t;
55 :
56 : struct tds_time
57 : {
58 : int tm_year; /**< year (0=1900) */
59 : int tm_mon; /**< month (0-11) */
60 : int tm_mday; /**< month day (1-31) */
61 : int tm_hour; /**< hours (0-23) */
62 : int tm_min; /**< minutes (0-59) */
63 : int tm_sec; /**< seconds (0-59) */
64 : int tm_ns; /**< nanoseconds (0-999999999) */
65 : };
66 :
67 : static TDS_INT tds_convert_int(TDS_INT num, int desttype, CONV_RESULT * cr);
68 : static TDS_INT tds_convert_uint8(const TDS_UINT8 * src, int desttype, CONV_RESULT * cr);
69 : static int string_to_datetime(const char *datestr, TDS_UINT len, int desttype, CONV_RESULT * cr);
70 : static bool is_dd_mon_yyyy(char *t);
71 : static int store_dd_mon_yyy_date(char *datestr, struct tds_time *t);
72 : static const char *parse_numeric(const char *buf, const char *pend,
73 : bool * p_negative, size_t *p_digits, size_t *p_decimals);
74 :
75 : #define test_alloc(x) {if ((x)==NULL) return TDS_CONVERT_NOMEM;}
76 :
77 : /*
78 : * Macros for number checks.
79 : * They work for signed/unsigned integers and floating point values
80 : * (accounting for truncation of any fractional portions of the latter).
81 : */
82 : #define IS_TINYINT(x) ( -1 < (x) && (x) < 0x100 )
83 : #define IS_SMALLINT(x) ( -32769 < (x) && (x) < 32768 )
84 : #define IS_USMALLINT(x) ( -1 < (x) && (x) < 65536 )
85 : #define IS_SINT1(x) ( -129 < (x) && (x) < 128 )
86 :
87 : /*
88 : * Macros for integer number checks.
89 : *
90 : * f77: I don't write -2147483648, some compiler seem to have some problem
91 : * with this constant although is a valid 32bit value
92 : */
93 : #define TDS_INT_MIN (-2147483647-1)
94 : #define TDS_INT_MAX 2147483647
95 : #define INT_IS_INT(x) (TDS_INT_MIN <= (x) && (x) <= TDS_INT_MAX)
96 : #define TDS_UINT_MAX 4294967295u
97 : #define INT_IS_UINT(x) (0 <= (x) && (x) <= (TDS_INT8) TDS_UINT_MAX)
98 : #define TDS_INT8_MIN (-INT64_C(9223372036854775807)-1)
99 : #define TDS_INT8_MAX INT64_C(9223372036854775807)
100 :
101 : /*
102 : * Macros for floating point number checks.
103 : * To avoid possible loss of precision, use upper bounds for floating point
104 : * values and test MIN - (x) < 1 rather than MIN - 1 < (x) for signed
105 : * destination types.
106 : */
107 : #define TDS_INT_UPPER_FLOAT 2147483648.0f
108 : #define FLOAT_IS_INT(x) (TDS_INT_MIN - (x) < 1.0f && (x) < TDS_INT_UPPER_FLOAT)
109 : #define TDS_UINT_UPPER_FLOAT 4294967296.0f
110 : #define FLOAT_IS_UINT(x) (-1.0f < (x) && (x) < TDS_UINT_UPPER_FLOAT)
111 : #define TDS_INT8_MIN_FLOAT (-9223372036854775808.0f)
112 : #define TDS_INT8_UPPER_FLOAT 9223372036854775808.0f
113 : #define FLOAT_IS_INT8(x) (TDS_INT8_MIN_FLOAT - (x) < 1.0f && (x) < TDS_INT8_UPPER_FLOAT)
114 : #define TDS_UINT8_UPPER 18446744073709551616.0f
115 : #define FLOAT_IS_UINT8(x) (-1.0f < (x) && (x) < TDS_UINT8_UPPER)
116 :
117 : #define TDS_ISDIGIT(c) ((c) >= '0' && (c) <= '9')
118 :
119 : #define BIGDATETIME_BIAS 693961
120 :
121 : /**
122 : * \ingroup libtds
123 : * \defgroup convert Conversion
124 : * Conversions between datatypes. Supports, for example, dbconvert().
125 : */
126 :
127 : /**
128 : * \addtogroup convert
129 : * @{
130 : */
131 :
132 : /**
133 : * convert a number in string to a TDSNUMERIC
134 : * @return sizeof(TDS_NUMERIC) on success, TDS_CONVERT_* failure code on failure
135 : */
136 : static int string_to_numeric(const char *instr, const char *pend, CONV_RESULT * cr);
137 :
138 : /**
139 : * convert a zero terminated string to NUMERIC
140 : * @return sizeof(TDS_NUMERIC) on success, TDS_CONVERT_* failure code on failure
141 : */
142 : static int stringz_to_numeric(const char *instr, CONV_RESULT * cr);
143 :
144 : static TDS_INT string_to_int(const char *buf, const char *pend, TDS_INT * res);
145 : static TDS_INT string_to_int8(const char *buf, const char *pend, TDS_INT8 * res);
146 : static TDS_INT string_to_uint8(const char *buf, const char *pend, TDS_UINT8 * res);
147 : static TDS_INT string_to_float(const TDS_CHAR * src, TDS_UINT srclen, int desttype, CONV_RESULT * cr);
148 :
149 : static int store_hour(const char *, const char *, struct tds_time *);
150 : static int store_time(const char *, struct tds_time *);
151 : static int store_yymmdd_date(const char *, struct tds_time *);
152 : static int store_monthname(const char *, struct tds_time *);
153 : static int store_numeric_date(const char *, struct tds_time *);
154 : static int store_mday(const char *, struct tds_time *);
155 : static int store_year(int, struct tds_time *);
156 :
157 : /* static int days_this_year (int years); */
158 : static bool is_timeformat(const char *);
159 : static bool is_numeric(const char *);
160 : static bool is_alphabetic(const char *);
161 : static bool is_ampm(const char *);
162 : #define is_monthname(s) (store_monthname(s, NULL) >= 0)
163 : static bool is_numeric_dateformat(const char *);
164 :
165 : #if 0
166 : static TDS_UINT utf16len(const utf16_t * s);
167 : static const char *tds_prtype(int token);
168 : #endif
169 :
170 : const char tds_hex_digits[] = "0123456789abcdef";
171 :
172 : /**
173 : * Copy a terminated string to result and return len or TDS_CONVERT_NOMEM
174 : */
175 : static TDS_INT
176 23670 : string_to_result(int desttype, const char *s, CONV_RESULT * cr)
177 : {
178 23670 : size_t len = strlen(s);
179 :
180 23670 : if (desttype != TDS_CONVERT_CHAR) {
181 4572 : cr->c = tds_new(TDS_CHAR, len + 1);
182 4572 : test_alloc(cr->c);
183 4572 : memcpy(cr->c, s, len + 1);
184 : } else {
185 19098 : memcpy(cr->cc.c, s, TDS_MIN(len, cr->cc.len));
186 : }
187 23670 : return (TDS_INT)len;
188 : }
189 :
190 : /**
191 : * Copy binary data to to result and return len or TDS_CONVERT_NOMEM
192 : */
193 : static TDS_INT
194 2628 : binary_to_result(int desttype, const void *data, size_t len, CONV_RESULT * cr)
195 : {
196 2628 : if (desttype != TDS_CONVERT_BINARY) {
197 2416 : cr->ib = tds_new(TDS_CHAR, len);
198 2416 : test_alloc(cr->ib);
199 2416 : memcpy(cr->ib, data, len);
200 : } else {
201 212 : memcpy(cr->cb.ib, data, TDS_MIN(len, cr->cb.len));
202 : }
203 2628 : return (TDS_INT) len;
204 : }
205 :
206 : static inline TDS_INT
207 : set_money(TDS_INT8 value, CONV_RESULT *cr)
208 : {
209 111640 : cr->m.tdsoldmoney.mnyhigh = (TDS_INT) (value >> 32);
210 111640 : cr->m.tdsoldmoney.mnylow = (TDS_UINT) value;
211 : return sizeof(TDS_MONEY);
212 : }
213 :
214 : #define CASE_ALL_CHAR \
215 : SYBCHAR: case SYBVARCHAR: case SYBTEXT: case XSYBCHAR: case XSYBVARCHAR
216 : #define CASE_ALL_BINARY \
217 : SYBBINARY: case SYBVARBINARY: case SYBIMAGE: case XSYBBINARY: case XSYBVARBINARY: \
218 : case SYBLONGBINARY: case TDS_CONVERT_BINARY
219 :
220 : /* TODO implement me */
221 : /*
222 : static TDS_INT
223 : tds_convert_ntext(int srctype,TDS_CHAR *src,TDS_UINT srclen,
224 : int desttype, CONV_RESULT *cr)
225 : {
226 : return TDS_CONVERT_NOAVAIL;
227 : }
228 : */
229 :
230 : static TDS_INT
231 18502 : tds_convert_binary(const TDS_UCHAR * src, TDS_INT srclen, int desttype, CONV_RESULT * cr)
232 : {
233 : int cplen;
234 : int s;
235 : char *c;
236 :
237 18502 : switch (desttype) {
238 1082 : case TDS_CONVERT_CHAR:
239 1082 : cplen = srclen * 2;
240 1082 : if ((TDS_UINT)cplen > cr->cc.len)
241 490 : cplen = cr->cc.len;
242 :
243 1082 : c = cr->cc.c;
244 804222 : for (s = 0; cplen >= 2; ++s, cplen -= 2) {
245 803140 : *c++ = tds_hex_digits[src[s]>>4];
246 803140 : *c++ = tds_hex_digits[src[s]&0xF];
247 : }
248 1082 : if (cplen)
249 240 : *c = tds_hex_digits[src[s]>>4];
250 : return srclen * 2;
251 :
252 520 : case CASE_ALL_CHAR:
253 :
254 : /*
255 : * NOTE: Do not prepend 0x to string.
256 : * The libraries all expect a bare string, without a 0x prefix.
257 : * Applications such as isql and query analyzer provide the "0x" prefix.
258 : */
259 :
260 : /* 2 * source length + 1 for terminator */
261 :
262 520 : cr->c = tds_new(TDS_CHAR, (srclen * 2) + 1);
263 520 : test_alloc(cr->c);
264 :
265 : c = cr->c;
266 :
267 112412 : for (s = 0; s < srclen; s++) {
268 112412 : *c++ = tds_hex_digits[src[s]>>4];
269 112412 : *c++ = tds_hex_digits[src[s]&0xF];
270 : }
271 :
272 520 : *c = '\0';
273 520 : return (srclen * 2);
274 : break;
275 2080 : case SYBINT1:
276 : case SYBSINT1:
277 : case SYBUINT1:
278 : case SYBINT2:
279 : case SYBUINT2:
280 : case SYBINT4:
281 : case SYBUINT4:
282 : case SYBINT8:
283 : case SYBUINT8:
284 : case SYBMONEY4:
285 : case SYBMONEY:
286 : case SYBREAL:
287 : case SYBFLT8:
288 2080 : cplen = tds_get_size_by_type(desttype);
289 2080 : if (srclen >= cplen)
290 680 : srclen = cplen;
291 2080 : memcpy(cr, src, srclen);
292 2080 : memset(((char*) cr) + srclen, 0, cplen - srclen);
293 2080 : return cplen;
294 : break;
295 :
296 : /* conversions not allowed */
297 : case SYBDATETIME4:
298 : case SYBDATETIME:
299 : case SYBDATETIMN:
300 :
301 : /* TODO should we do some test for these types or work as ints ?? */
302 : case SYBDECIMAL:
303 : case SYBNUMERIC:
304 : case SYBBIT:
305 : case SYBBITN:
306 :
307 : default:
308 : break;
309 : }
310 : return TDS_CONVERT_NOAVAIL;
311 : }
312 :
313 : size_t
314 1410 : tds_hex_trim(const TDS_CHAR **p_src, size_t srclen)
315 : {
316 1410 : const TDS_CHAR *src = *p_src;
317 :
318 : /* skip leading spaces and tabs */
319 2950 : while (srclen > 0 && (src[0] == ' ' || src[0] == '\t')) {
320 130 : src++;
321 130 : srclen--;
322 : }
323 :
324 : /* skip leading "0x" or "0X" */
325 1410 : if (srclen >= 2 && src[0] == '0' && (src[1] == 'x' || src[1] == 'X')) {
326 538 : src += 2;
327 538 : srclen -= 2;
328 : }
329 :
330 : /* ignore trailing spaces and tabs */
331 1510 : while (srclen > 0 && (src[srclen - 1] == ' ' || src[srclen - 1] == '\t'))
332 : --srclen;
333 :
334 1410 : *p_src = src;
335 1410 : return srclen;
336 : }
337 :
338 : ptrdiff_t
339 1450 : tds_char2hex(TDS_CHAR *dest, size_t destlen, const TDS_CHAR *src, size_t srclen)
340 : {
341 : size_t i;
342 1450 : unsigned char hex1, c = 0;
343 :
344 : /* if srclen if odd we must add a "0" before ... */
345 1450 : i = 0; /* number where to start converting */
346 1450 : if (srclen & 1) {
347 420 : ++srclen;
348 420 : i = 1;
349 420 : --src;
350 : }
351 624130 : for (; i < srclen; ++i) {
352 624170 : hex1 = (unsigned char) src[i];
353 :
354 624170 : if ('0' <= hex1 && hex1 <= '9')
355 521372 : hex1 &= 0x0f;
356 : else {
357 102798 : hex1 &= 0x20 ^ 0xff; /* mask off 0x20 to ensure upper case */
358 102798 : if ('A' <= hex1 && hex1 <= 'F') {
359 102758 : hex1 -= ('A' - 10);
360 : } else {
361 40 : tdsdump_log(TDS_DBG_ERROR,
362 : "error_handler: attempt to convert data stopped by syntax error in source field\n");
363 : return TDS_CONVERT_SYNTAX;
364 : }
365 : }
366 624130 : tds_extra_assert(hex1 < 0x10);
367 :
368 624130 : if ((i/2u) >= destlen)
369 0 : continue;
370 :
371 624130 : if (i & 1)
372 312260 : dest[i / 2u] = (char) (c | hex1);
373 : else
374 311870 : c = hex1 << 4;
375 : }
376 1410 : return (ptrdiff_t) (srclen / 2u);
377 : }
378 :
379 : static TDS_INT
380 1489244 : tds_convert_char(const TDS_CHAR * src, TDS_UINT srclen, int desttype, CONV_RESULT * cr)
381 : {
382 : unsigned int i;
383 :
384 : TDS_INT8 mymoney;
385 : char mynumber[28];
386 :
387 : TDS_INT tds_i;
388 : TDS_INT8 tds_i8;
389 : TDS_UINT8 tds_ui8;
390 : TDS_INT rc;
391 :
392 : bool negative;
393 : size_t digits, decimals;
394 :
395 1489244 : switch (desttype) {
396 2788 : case TDS_CONVERT_CHAR:
397 2788 : memcpy(cr->cc.c, src, TDS_MIN(srclen, cr->cc.len));
398 2788 : return srclen;
399 :
400 63482 : case CASE_ALL_CHAR:
401 63482 : cr->c = tds_new(TDS_CHAR, srclen + 1);
402 63482 : test_alloc(cr->c);
403 63482 : memcpy(cr->c, src, srclen);
404 63482 : cr->c[srclen] = 0;
405 63482 : return srclen;
406 : break;
407 :
408 94030 : case SYBSINT1:
409 94030 : if ((rc = string_to_int(src, src + srclen, &tds_i)) < 0)
410 : return rc;
411 58660 : if (!IS_SINT1(tds_i))
412 : return TDS_CONVERT_OVERFLOW;
413 10970 : cr->ti = (TDS_TINYINT) tds_i;
414 10970 : return sizeof(TDS_TINYINT);
415 : break;
416 202870 : case SYBINT1:
417 : case SYBUINT1:
418 202870 : if ((rc = string_to_int(src, src + srclen, &tds_i)) < 0)
419 : return rc;
420 126060 : if (!IS_TINYINT(tds_i))
421 : return TDS_CONVERT_OVERFLOW;
422 25520 : cr->ti = (TDS_TINYINT) tds_i;
423 25520 : return sizeof(TDS_TINYINT);
424 : break;
425 101580 : case SYBINT2:
426 101580 : if ((rc = string_to_int(src, src + srclen, &tds_i)) < 0)
427 : return rc;
428 63110 : if (!IS_SMALLINT(tds_i))
429 : return TDS_CONVERT_OVERFLOW;
430 33350 : cr->si = (TDS_SMALLINT) tds_i;
431 33350 : return sizeof(TDS_SMALLINT);
432 : break;
433 101410 : case SYBUINT2:
434 101410 : if ((rc = string_to_int(src, src + srclen, &tds_i)) < 0)
435 : return rc;
436 62960 : if (!IS_USMALLINT(tds_i))
437 : return TDS_CONVERT_OVERFLOW;
438 23870 : cr->usi = (TDS_USMALLINT) tds_i;
439 23870 : return sizeof(TDS_USMALLINT);
440 : break;
441 102632 : case SYBINT4:
442 102632 : if ((rc = string_to_int(src, src + srclen, &tds_i)) < 0)
443 : return rc;
444 63992 : cr->i = tds_i;
445 63992 : return sizeof(TDS_INT);
446 : break;
447 101462 : case SYBUINT4:
448 101462 : if ((rc = string_to_int8(src, src + srclen, &tds_i8)) < 0)
449 : return rc;
450 89592 : if (!INT_IS_UINT(tds_i8))
451 : return TDS_CONVERT_OVERFLOW;
452 39102 : cr->ui = (TDS_UINT) tds_i8;
453 39102 : return sizeof(TDS_UINT);
454 : break;
455 101720 : case SYBINT8:
456 101720 : if ((rc = string_to_int8(src, src + srclen, &tds_i8)) < 0)
457 : return rc;
458 89690 : cr->bi = tds_i8;
459 89690 : return sizeof(TDS_INT8);
460 : break;
461 101590 : case SYBUINT8:
462 101590 : if ((rc = string_to_uint8(src, src + srclen, &tds_ui8)) < 0)
463 : return rc;
464 52470 : cr->ubi = tds_ui8;
465 52470 : return sizeof(TDS_UINT8);
466 : break;
467 189290 : case SYBFLT8:
468 : case SYBREAL:
469 189290 : return string_to_float(src, srclen, desttype, cr);
470 : break;
471 590 : case SYBBIT:
472 : case SYBBITN:
473 590 : if ((rc = string_to_int(src, src + srclen, &tds_i)) < 0)
474 : return rc;
475 590 : cr->ti = tds_i ? 1 : 0;
476 590 : return sizeof(TDS_TINYINT);
477 : break;
478 203790 : case SYBMONEY:
479 : case SYBMONEY4:
480 :
481 203790 : src = parse_numeric(src, src + srclen, &negative, &digits, &decimals);
482 203790 : if (!src)
483 : return TDS_CONVERT_SYNTAX;
484 203760 : if (digits > 18)
485 : return TDS_CONVERT_OVERFLOW;
486 :
487 171520 : i = 0;
488 171520 : if (negative)
489 78360 : mynumber[i++] = '-';
490 1099080 : for (; digits; --digits)
491 1099080 : mynumber[i++] = *src++;
492 171520 : src++;
493 174400 : for (digits = 0; digits < 4 && digits < decimals; ++digits)
494 2880 : mynumber[i++] = *src++;
495 683200 : for (; digits < 4; ++digits)
496 683200 : mynumber[i++] = '0';
497 :
498 : /* convert number and check for overflow */
499 171520 : if ((rc = string_to_int8(mynumber, mynumber + i, &mymoney)) < 0)
500 : return rc;
501 :
502 163240 : if (desttype == SYBMONEY)
503 163220 : return set_money(mymoney, cr);
504 :
505 81630 : if (!INT_IS_INT(mymoney))
506 : return TDS_CONVERT_OVERFLOW;
507 54040 : cr->m4.mny4 = (TDS_INT) mymoney;
508 54040 : return sizeof(TDS_MONEY4);
509 : break;
510 3148 : case SYBDATETIME:
511 : case SYBDATETIME4:
512 : case SYBMSTIME:
513 : case SYBMSDATE:
514 : case SYBMSDATETIME2:
515 : case SYBMSDATETIMEOFFSET:
516 : case SYBTIME:
517 : case SYBDATE:
518 : case SYB5BIGTIME:
519 : case SYB5BIGDATETIME:
520 3148 : return string_to_datetime(src, srclen, desttype, cr);
521 : break;
522 107730 : case SYBNUMERIC:
523 : case SYBDECIMAL:
524 107730 : return string_to_numeric(src, src + srclen, cr);
525 : break;
526 282 : case SYBUNIQUE:{
527 282 : unsigned n = 0;
528 : uint8_t c;
529 :
530 : /*
531 : * format: XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX
532 : * or {XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX}
533 : * or XXXXXXXX-XXXX-XXXX-XXXXXXXXXXXXXXXX
534 : * or {XXXXXXXX-XXXX-XXXX-XXXXXXXXXXXXXXXX}
535 : * SQL seem to ignore the additional braces.
536 : */
537 282 : if (srclen < (32 + 3))
538 : return TDS_CONVERT_SYNTAX;
539 :
540 192 : if (src[0] == '{') {
541 10 : TDS_UINT last = (src[8+1 + 4+1 + 4+1 + 4 + 1] == '-') ? 32+4+1 : 32+3+1;
542 10 : if (srclen <= last || src[last] != '}')
543 : return TDS_CONVERT_SYNTAX;
544 10 : ++src;
545 : }
546 :
547 : /*
548 : * Test each character and get value.
549 : * sscanf works if the number terminates with less digits.
550 : */
551 5380 : for (i = 0; i < 32 + 3; ++i) {
552 5430 : c = (uint8_t) src[i];
553 5430 : switch (i) {
554 162 : case 8:
555 162 : if (c != '-')
556 : return TDS_CONVERT_SYNTAX;
557 162 : cr->u.Data1 = n;
558 162 : n = 0;
559 162 : break;
560 162 : case 8+1 + 4:
561 162 : if (c != '-')
562 : return TDS_CONVERT_SYNTAX;
563 162 : cr->u.Data2 = (uint16_t) n;
564 162 : n = 0;
565 162 : break;
566 152 : case 8+1 + 4+1 + 4:
567 152 : if (c != '-')
568 : return TDS_CONVERT_SYNTAX;
569 152 : cr->u.Data3 = (uint16_t) n;
570 152 : n = 0;
571 152 : break;
572 152 : case 8+1 + 4+1 + 4+1 + 4:
573 : /* skip last (optional) dash */
574 152 : if (c == '-') {
575 112 : if (--srclen < 32 + 3)
576 : return TDS_CONVERT_SYNTAX;
577 112 : c = (uint8_t) (++src)[i];
578 : }
579 : /* fall through */
580 : default:
581 4954 : n = n << 4;
582 4954 : if (c >= '0' && c <= '9')
583 3396 : n += c - '0';
584 : else {
585 1558 : c &= 0x20 ^ 0xff;
586 1558 : if (c >= 'A' && c <= 'F')
587 1508 : n += c - ('A' - 10);
588 : else
589 : return TDS_CONVERT_SYNTAX;
590 : }
591 4904 : if (i > (16 + 2) && !(i & 1)) {
592 1156 : cr->u.Data4[(i >> 1) - 10] = (uint8_t) n;
593 1156 : n = 0;
594 : }
595 : }
596 : }
597 : }
598 : return sizeof(TDS_UNIQUE);
599 : default:
600 : return TDS_CONVERT_NOAVAIL;
601 : break;
602 : } /* end switch */
603 : } /* tds_convert_char */
604 :
605 : static TDS_INT
606 : tds_convert_bit(const TDS_CHAR * src, int desttype, CONV_RESULT * cr)
607 : {
608 6618 : return tds_convert_int(src[0] ? 1 : 0, desttype, cr);
609 : }
610 :
611 : static TDS_INT
612 : tds_convert_int1(const int8_t * src, int desttype, CONV_RESULT * cr)
613 : {
614 8424 : return tds_convert_int(*src, desttype, cr);
615 : }
616 :
617 : static TDS_INT
618 : tds_convert_uint1(const TDS_TINYINT * src, int desttype, CONV_RESULT * cr)
619 : {
620 23056 : return tds_convert_int(*src, desttype, cr);
621 : }
622 :
623 : static TDS_INT
624 : tds_convert_int2(const TDS_SMALLINT * src, int desttype, CONV_RESULT * cr)
625 : {
626 28138 : return tds_convert_int(*src, desttype, cr);
627 : }
628 :
629 : static TDS_INT
630 : tds_convert_uint2(const TDS_USMALLINT * src, int desttype, CONV_RESULT * cr)
631 : {
632 16562 : return tds_convert_int(*src, desttype, cr);
633 : }
634 :
635 : static TDS_INT
636 : tds_convert_int4(const TDS_INT * src, int desttype, CONV_RESULT * cr)
637 : {
638 113788 : return tds_convert_int(*src, desttype, cr);
639 : }
640 :
641 : static TDS_INT
642 : tds_convert_uint4(const TDS_UINT * src, int desttype, CONV_RESULT * cr)
643 : {
644 : TDS_UINT8 num;
645 :
646 27378 : num = *src;
647 27378 : return tds_convert_uint8(&num, desttype, cr);
648 : }
649 :
650 : static TDS_INT
651 : tds_convert_int_numeric(unsigned char scale,
652 : unsigned char sign, TDS_UINT num, CONV_RESULT * cr)
653 : {
654 14700 : unsigned char orig_prec = cr->n.precision, orig_scale = cr->n.scale;
655 14700 : cr->n.precision = 10;
656 14700 : cr->n.scale = scale;
657 14700 : cr->n.array[0] = sign;
658 14700 : cr->n.array[1] = 0;
659 14700 : TDS_PUT_UA4BE(&(cr->n.array[2]), num);
660 14700 : return tds_numeric_change_prec_scale(&(cr->n), orig_prec, orig_scale);
661 : }
662 :
663 : static TDS_INT
664 : tds_convert_int8_numeric(unsigned char scale,
665 : unsigned char sign, TDS_UINT8 num, CONV_RESULT * cr)
666 : {
667 6320 : unsigned char orig_prec = cr->n.precision, orig_scale = cr->n.scale;
668 6320 : cr->n.precision = 20;
669 6320 : cr->n.scale = scale;
670 6320 : cr->n.array[0] = sign;
671 6320 : cr->n.array[1] = 0;
672 6320 : TDS_PUT_UA4BE(&(cr->n.array[2]), (TDS_UINT) (num >> 32));
673 6320 : TDS_PUT_UA4BE(&(cr->n.array[6]), (TDS_UINT) num);
674 6320 : return tds_numeric_change_prec_scale(&(cr->n), orig_prec, orig_scale);
675 : }
676 :
677 : static const char digits2[200] =
678 : "0001020304050607080910111213141516171819202122232425262728293031323334353637383940414243444546474849"
679 : "5051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899";
680 :
681 : static inline void
682 : tds02dfast(char out[2], int v)
683 : {
684 23656 : out[0] = digits2[v * 2];
685 23656 : out[1] = digits2[v * 2 + 1];
686 : }
687 :
688 : void
689 400 : tds_02d_fast(char out[2], int v)
690 : {
691 400 : tds02dfast(out, v);
692 400 : }
693 :
694 : /**
695 : * Format an unsigned int32 right-justified on a char[10] buffer.
696 : * Returns the amount of leading padding.
697 : */
698 : size_t
699 11728 : tds_u32toa_fast_right(char out[10], uint32_t v)
700 : {
701 11728 : char *p = out + 10;
702 :
703 : /* Fill buffer from the end so it comes out in the right order */
704 43006 : while (v >= 100u) {
705 19550 : uint32_t q = v / 100u;
706 19550 : uint32_t r = v % 100u;
707 :
708 19550 : p -= 2;
709 39100 : tds02dfast(p, r);
710 19550 : v = q;
711 : }
712 :
713 11728 : if (v >= 10u) {
714 1360 : p -= 2;
715 1360 : tds02dfast(p, v);
716 10368 : } else if (v > 0u)
717 9526 : *--p = (char) ('0' + v);
718 :
719 11728 : return p - out;
720 : }
721 :
722 : /* Returns number of digits written */
723 : size_t
724 13260 : tds_u32toa_fast(char out[10], uint32_t v)
725 : {
726 : char buf[10];
727 : size_t pad;
728 :
729 : /* Small case optimizations */
730 13260 : if (v < 10u) {
731 4064 : *out = (char) ('0' + v);
732 4064 : return 1;
733 : }
734 9196 : if (v < 100u) {
735 1384 : tds02dfast(out, v);
736 692 : return 2;
737 : }
738 :
739 8504 : pad = tds_u32toa_fast_right(buf, v);
740 :
741 8504 : memcpy(out, buf + pad, 10 - pad);
742 8504 : return 10 - pad;
743 : }
744 :
745 : size_t
746 0 : tds_i32toa_fast(char out[11], int32_t v)
747 : {
748 13180 : size_t sign_length = 0;
749 :
750 13180 : if (v < 0) {
751 952 : *out++ = '-';
752 952 : sign_length = 1;
753 952 : if (TDS_LIKELY(v != (-2147483647 - 1)))
754 872 : v = -v;
755 : }
756 13180 : return tds_u32toa_fast(out, v) + sign_length;
757 : }
758 :
759 : static TDS_INT
760 283636 : tds_convert_int(TDS_INT num, int desttype, CONV_RESULT * cr)
761 : {
762 : TDS_CHAR tmp_str[16];
763 :
764 283636 : switch (desttype) {
765 13180 : case TDS_CONVERT_CHAR:
766 : case CASE_ALL_CHAR:
767 13180 : tmp_str[tds_i32toa_fast(tmp_str, num)] = 0;
768 13180 : return string_to_result(desttype, tmp_str, cr);
769 : break;
770 11354 : case SYBSINT1:
771 11354 : if (!IS_SINT1(num))
772 : return TDS_CONVERT_OVERFLOW;
773 2914 : cr->ti = (TDS_TINYINT) num;
774 2914 : return sizeof(TDS_TINYINT);
775 : break;
776 23908 : case SYBINT1:
777 : case SYBUINT1:
778 23908 : if (!IS_TINYINT(num))
779 : return TDS_CONVERT_OVERFLOW;
780 9178 : cr->ti = (TDS_TINYINT) num;
781 9178 : return sizeof(TDS_TINYINT);
782 : break;
783 14356 : case SYBINT2:
784 14356 : if (!IS_SMALLINT(num))
785 : return TDS_CONVERT_OVERFLOW;
786 10336 : cr->si = (TDS_SMALLINT) num;
787 10336 : return sizeof(TDS_SMALLINT);
788 : break;
789 11840 : case SYBUINT2:
790 11840 : if (!IS_USMALLINT(num))
791 : return TDS_CONVERT_OVERFLOW;
792 6800 : cr->usi = (TDS_USMALLINT) num;
793 6800 : return sizeof(TDS_USMALLINT);
794 : break;
795 84734 : case SYBINT4:
796 84734 : cr->i = num;
797 84734 : return sizeof(TDS_INT);
798 : break;
799 13068 : case SYBUINT4:
800 13068 : if (num < 0)
801 : return TDS_CONVERT_OVERFLOW;
802 9708 : cr->ui = (TDS_UINT) num;
803 9708 : return sizeof(TDS_UINT);
804 : break;
805 12170 : case SYBINT8:
806 12170 : cr->bi = num;
807 12170 : return sizeof(TDS_INT8);
808 : break;
809 12000 : case SYBUINT8:
810 12000 : if (num < 0)
811 : return TDS_CONVERT_OVERFLOW;
812 8640 : cr->ubi = (TDS_UINT8) num;
813 8640 : return sizeof(TDS_UINT8);
814 : break;
815 1206 : case SYBBIT:
816 : case SYBBITN:
817 1206 : cr->ti = num ? 1 : 0;
818 1206 : return sizeof(TDS_TINYINT);
819 : break;
820 11330 : case SYBFLT8:
821 11330 : cr->f = num;
822 11330 : return sizeof(TDS_FLOAT);
823 : break;
824 11330 : case SYBREAL:
825 11330 : cr->r = (TDS_REAL) num;
826 11330 : return sizeof(TDS_REAL);
827 : break;
828 11800 : case SYBMONEY4:
829 11800 : if (num > 214748 || num < -214748)
830 : return TDS_CONVERT_OVERFLOW;
831 10570 : cr->m4.mny4 = num * 10000;
832 10570 : return sizeof(TDS_MONEY4);
833 : break;
834 11920 : case SYBMONEY:
835 23840 : return set_money((TDS_INT8) num * 10000, cr);
836 : break;
837 12370 : case SYBNUMERIC:
838 : case SYBDECIMAL:
839 12370 : if (num < 0)
840 7060 : return tds_convert_int_numeric(0, 1, (TDS_UINT) -num, cr);
841 17680 : return tds_convert_int_numeric(0, 0, (TDS_UINT) num, cr);
842 : break;
843 : /* handled by upper layer */
844 : case CASE_ALL_BINARY:
845 : /* conversions not allowed */
846 : case SYBUNIQUE:
847 : case SYBDATETIME4:
848 : case SYBDATETIME:
849 : case SYBDATETIMN:
850 : default:
851 : break;
852 : }
853 : return TDS_CONVERT_NOAVAIL;
854 : }
855 :
856 : static TDS_INT
857 61284 : tds_convert_int8(const TDS_INT8 *src, int desttype, CONV_RESULT * cr)
858 : {
859 : TDS_INT8 buf;
860 : TDS_CHAR tmp_str[24];
861 :
862 61284 : memcpy(&buf, src, sizeof(buf));
863 61284 : if (INT_IS_INT(buf))
864 40594 : return tds_convert_int((TDS_INT) buf, desttype, cr);
865 :
866 20690 : switch (desttype) {
867 622 : case TDS_CONVERT_CHAR:
868 : case CASE_ALL_CHAR:
869 622 : sprintf(tmp_str, "%" PRId64, buf);
870 622 : return string_to_result(desttype, tmp_str, cr);
871 : break;
872 : case SYBINT1:
873 : case SYBSINT1:
874 : case SYBUINT1:
875 : case SYBINT2:
876 : case SYBUINT2:
877 : case SYBINT4:
878 : case SYBMONEY4:
879 : return TDS_CONVERT_OVERFLOW;
880 : break;
881 1370 : case SYBUINT4:
882 1370 : if (!INT_IS_UINT(buf))
883 : return TDS_CONVERT_OVERFLOW;
884 230 : cr->ui = (TDS_UINT) buf;
885 230 : return sizeof(TDS_UINT);
886 : break;
887 1558 : case SYBINT8:
888 1558 : cr->bi = buf;
889 1558 : return sizeof(TDS_INT8);
890 : break;
891 1410 : case SYBUINT8:
892 1410 : if (buf < 0)
893 : return TDS_CONVERT_OVERFLOW;
894 780 : cr->ubi = (TDS_UINT8) buf;
895 780 : return sizeof(TDS_UINT8);
896 : break;
897 90 : case SYBBIT:
898 : case SYBBITN:
899 : /* this cannot be 0 as already tested above */
900 90 : cr->ti = 1;
901 90 : return sizeof(TDS_TINYINT);
902 : break;
903 1350 : case SYBFLT8:
904 1350 : cr->f = (TDS_FLOAT) buf;
905 1350 : return sizeof(TDS_FLOAT);
906 : break;
907 1350 : case SYBREAL:
908 1350 : cr->r = (TDS_REAL) buf;
909 1350 : return sizeof(TDS_REAL);
910 : break;
911 1320 : case SYBMONEY:
912 1320 : if (buf > (TDS_INT8_MAX / 10000) || buf < (TDS_INT8_MIN / 10000))
913 : return TDS_CONVERT_OVERFLOW;
914 1820 : return set_money(buf * 10000, cr);
915 : break;
916 1450 : case SYBNUMERIC:
917 : case SYBDECIMAL:
918 1450 : if (buf < 0)
919 1340 : return tds_convert_int8_numeric(0, 1, (TDS_UINT8) -buf, cr);
920 1560 : return tds_convert_int8_numeric(0, 0, (TDS_UINT8) buf, cr);
921 : break;
922 : /* conversions not allowed */
923 : case SYBUNIQUE:
924 : case SYBDATETIME4:
925 : case SYBDATETIME:
926 : case SYBDATETIMN:
927 : default:
928 : break;
929 : }
930 630 : return TDS_CONVERT_NOAVAIL;
931 : }
932 :
933 : static TDS_INT
934 62670 : tds_convert_uint8(const TDS_UINT8 *src, int desttype, CONV_RESULT * cr)
935 : {
936 : TDS_UINT8 buf;
937 : TDS_CHAR tmp_str[24];
938 :
939 62670 : memcpy(&buf, src, sizeof(buf));
940 : /* INT_IS_INT does not work here due to unsigned/signed conversions */
941 62670 : if (buf <= TDS_INT_MAX)
942 46456 : return tds_convert_int((TDS_INT) buf, desttype, cr);
943 :
944 16214 : switch (desttype) {
945 474 : case TDS_CONVERT_CHAR:
946 : case CASE_ALL_CHAR:
947 474 : sprintf(tmp_str, "%" PRIu64, buf);
948 474 : return string_to_result(desttype, tmp_str, cr);
949 : break;
950 : case SYBINT1:
951 : case SYBSINT1:
952 : case SYBUINT1:
953 : case SYBINT2:
954 : case SYBUINT2:
955 : case SYBINT4:
956 : case SYBMONEY4:
957 : return TDS_CONVERT_OVERFLOW;
958 : break;
959 1120 : case SYBUINT4:
960 1120 : if (!INT_IS_UINT(buf))
961 : return TDS_CONVERT_OVERFLOW;
962 460 : cr->ui = (TDS_UINT) buf;
963 : return sizeof(TDS_UINT);
964 : break;
965 1160 : case SYBINT8:
966 1160 : if (buf > TDS_INT8_MAX)
967 : return TDS_CONVERT_OVERFLOW;
968 950 : cr->bi = (TDS_INT8) buf;
969 : return sizeof(TDS_INT8);
970 : break;
971 1180 : case SYBUINT8:
972 1180 : cr->ubi = buf;
973 : return sizeof(TDS_UINT8);
974 : break;
975 30 : case SYBBIT:
976 : case SYBBITN:
977 : /* this cannot be 0 as already tested above */
978 30 : cr->ti = 1;
979 : return sizeof(TDS_TINYINT);
980 : break;
981 1080 : case SYBFLT8:
982 1080 : cr->f = (TDS_FLOAT) buf;
983 : return sizeof(TDS_FLOAT);
984 : break;
985 1080 : case SYBREAL:
986 1080 : cr->r = (TDS_REAL) buf;
987 : return sizeof(TDS_REAL);
988 : break;
989 1110 : case SYBMONEY:
990 1110 : if (buf > (TDS_INT8_MAX / 10000))
991 : return TDS_CONVERT_OVERFLOW;
992 1400 : return set_money((TDS_INT8) (buf * 10000), cr);
993 : break;
994 1180 : case SYBNUMERIC:
995 : case SYBDECIMAL:
996 2360 : return tds_convert_int8_numeric(0, 0, buf, cr);
997 : break;
998 : /* conversions not allowed */
999 : case SYBUNIQUE:
1000 : case SYBDATETIME4:
1001 : case SYBDATETIME:
1002 : case SYBDATETIMN:
1003 : default:
1004 : break;
1005 : }
1006 : return TDS_CONVERT_NOAVAIL;
1007 : }
1008 :
1009 : static TDS_INT
1010 75248 : tds_convert_numeric(const TDS_NUMERIC *src, int desttype, CONV_RESULT *cr)
1011 : {
1012 : union
1013 : {
1014 : /* if the number has precision == scale == MAXPRECISION and it's negative a "-0." is prefixed
1015 : * to the digits. Also account for terminator and possible invalid out of range number. */
1016 : char tmpstr[MAXPRECISION + 5];
1017 : TDS_NUMERIC num;
1018 : } u;
1019 : TDS_INT i, ret;
1020 : TDS_UINT ui;
1021 : TDS_INT8 bi;
1022 :
1023 75248 : switch (desttype) {
1024 2326 : case TDS_CONVERT_CHAR:
1025 : case CASE_ALL_CHAR:
1026 2326 : if (tds_numeric_to_string(src, u.tmpstr) < 0)
1027 : return TDS_CONVERT_FAIL;
1028 2326 : return string_to_result(desttype, u.tmpstr, cr);
1029 : break;
1030 4680 : case SYBSINT1:
1031 4680 : u.num = *src;
1032 4680 : ret = tds_numeric_change_prec_scale(&u.num, 3, 0);
1033 4680 : if (ret < 0)
1034 : return ret;
1035 1280 : if (u.num.array[1])
1036 : return TDS_CONVERT_OVERFLOW;
1037 1060 : i = u.num.array[2];
1038 1060 : if (u.num.array[0])
1039 520 : i = -i;
1040 1060 : if (i != 0 && ((i >> 7) ^ u.num.array[0]) & 1)
1041 : return TDS_CONVERT_OVERFLOW;
1042 650 : cr->ti = (TDS_TINYINT) i;
1043 650 : return sizeof(TDS_TINYINT);
1044 : break;
1045 9440 : case SYBINT1:
1046 : case SYBUINT1:
1047 9440 : u.num = *src;
1048 9440 : ret = tds_numeric_change_prec_scale(&(u.num), 3, 0);
1049 9440 : if (ret < 0)
1050 : return ret;
1051 2640 : if (u.num.array[1] || (u.num.array[0] && u.num.array[2]))
1052 : return TDS_CONVERT_OVERFLOW;
1053 1180 : cr->ti = u.num.array[2];
1054 1180 : return sizeof(TDS_TINYINT);
1055 : break;
1056 4810 : case SYBINT2:
1057 4810 : u.num = *src;
1058 4810 : ret = tds_numeric_change_prec_scale(&(u.num), 5, 0);
1059 4810 : if (ret < 0)
1060 : return ret;
1061 2210 : if (u.num.array[1])
1062 : return TDS_CONVERT_OVERFLOW;
1063 1990 : i = TDS_GET_UA2BE(&(u.num.array[2]));
1064 1990 : if (u.num.array[0])
1065 970 : i = -i;
1066 1990 : if (i != 0 && ((i >> 15) ^ u.num.array[0]) & 1)
1067 : return TDS_CONVERT_OVERFLOW;
1068 1580 : cr->si = (TDS_SMALLINT) i;
1069 1580 : return sizeof(TDS_SMALLINT);
1070 : break;
1071 4760 : case SYBUINT2:
1072 4760 : u.num = *src;
1073 4760 : ret = tds_numeric_change_prec_scale(&(u.num), 5, 0);
1074 4760 : if (ret < 0)
1075 : return ret;
1076 2200 : i = TDS_GET_UA2BE(&(u.num.array[2]));
1077 2200 : if ((i != 0 && u.num.array[0]) || u.num.array[1])
1078 : return TDS_CONVERT_OVERFLOW;
1079 1050 : cr->usi = (TDS_USMALLINT) i;
1080 1050 : return sizeof(TDS_USMALLINT);
1081 : break;
1082 4910 : case SYBINT4:
1083 4910 : u.num = *src;
1084 4910 : ret = tds_numeric_change_prec_scale(&(u.num), 10, 0);
1085 4910 : if (ret < 0)
1086 : return ret;
1087 3650 : if (u.num.array[1])
1088 : return TDS_CONVERT_OVERFLOW;
1089 3430 : i = (TDS_INT) TDS_GET_UA4BE(&(u.num.array[2]));
1090 3430 : if (u.num.array[0])
1091 1640 : i = -i;
1092 3430 : if (i != 0 && ((i >> 31) ^ u.num.array[0]) & 1)
1093 : return TDS_CONVERT_OVERFLOW;
1094 3020 : cr->i = i;
1095 3020 : return sizeof(TDS_INT);
1096 : break;
1097 4820 : case SYBUINT4:
1098 4820 : u.num = *src;
1099 4820 : ret = tds_numeric_change_prec_scale(&(u.num), 10, 0);
1100 4820 : if (ret < 0)
1101 : return ret;
1102 3560 : ui = TDS_GET_UA4BE(&(u.num.array[2]));
1103 3560 : if ((ui != 0 && u.num.array[0]) || u.num.array[1])
1104 : return TDS_CONVERT_OVERFLOW;
1105 1780 : cr->ui = ui;
1106 1780 : return sizeof(TDS_UINT);
1107 : break;
1108 4970 : case SYBINT8:
1109 4970 : u.num = *src;
1110 4970 : ret = tds_numeric_change_prec_scale(&(u.num), 20, 0);
1111 4970 : if (ret < 0)
1112 : return ret;
1113 4970 : if (u.num.array[1])
1114 : return TDS_CONVERT_OVERFLOW;
1115 4750 : bi = TDS_GET_UA4BE(&(u.num.array[2]));
1116 4750 : bi = (bi << 32) + TDS_GET_UA4BE(&(u.num.array[6]));
1117 4750 : if (u.num.array[0])
1118 2310 : bi = -bi;
1119 4750 : if (bi != 0 && ((bi >> 63) ^ u.num.array[0]) & 1)
1120 : return TDS_CONVERT_OVERFLOW;
1121 4340 : cr->bi = bi;
1122 4340 : return sizeof(TDS_INT8);
1123 : break;
1124 4880 : case SYBUINT8:
1125 4880 : u.num = *src;
1126 4880 : ret = tds_numeric_change_prec_scale(&(u.num), 20, 0);
1127 4880 : if (ret < 0)
1128 : return ret;
1129 4880 : bi = TDS_GET_UA4BE(&(u.num.array[2]));
1130 4880 : bi = (bi << 32) + TDS_GET_UA4BE(&(u.num.array[6]));
1131 4880 : if ((bi != 0 && u.num.array[0]) || u.num.array[1])
1132 : return TDS_CONVERT_OVERFLOW;
1133 2470 : cr->ubi = bi;
1134 2470 : return sizeof(TDS_UINT8);
1135 : break;
1136 80 : case SYBBIT:
1137 : case SYBBITN:
1138 80 : cr->ti = 0;
1139 160 : for (i = tds_numeric_bytes_per_prec[src->precision]; --i > 0;)
1140 80 : if (src->array[i] != 0) {
1141 80 : cr->ti = 1;
1142 80 : break;
1143 : }
1144 : return sizeof(TDS_TINYINT);
1145 : break;
1146 4790 : case SYBMONEY4:
1147 4790 : u.num = *src;
1148 4790 : ret = tds_numeric_change_prec_scale(&(u.num), 10, 4);
1149 4790 : if (ret < 0)
1150 : return ret;
1151 2690 : if (u.num.array[1])
1152 : return TDS_CONVERT_OVERFLOW;
1153 2690 : i = (TDS_INT) TDS_GET_UA4BE(&(u.num.array[2]));
1154 2690 : if (u.num.array[0])
1155 1310 : i = -i;
1156 2690 : if (i != 0 && ((i >> 31) ^ u.num.array[0]) & 1)
1157 : return TDS_CONVERT_OVERFLOW;
1158 2490 : cr->m4.mny4 = i;
1159 2490 : return sizeof(TDS_MONEY4);
1160 : break;
1161 4890 : case SYBMONEY:
1162 4890 : u.num = *src;
1163 4890 : ret = tds_numeric_change_prec_scale(&(u.num), 20, 4);
1164 4890 : if (ret < 0)
1165 : return ret;
1166 4050 : if (u.num.array[1])
1167 : return TDS_CONVERT_OVERFLOW;
1168 4050 : bi = TDS_GET_UA4BE(&(u.num.array[2]));
1169 4050 : bi = (bi << 32) + TDS_GET_UA4BE(&(u.num.array[6]));
1170 4050 : if (u.num.array[0])
1171 1980 : bi = -bi;
1172 4050 : if (bi != 0 && ((bi >> 63) ^ u.num.array[0]) & 1)
1173 : return TDS_CONVERT_OVERFLOW;
1174 7700 : return set_money(bi, cr);
1175 : break;
1176 5692 : case SYBNUMERIC:
1177 : case SYBDECIMAL:
1178 : {
1179 5692 : unsigned char prec = cr->n.precision, scale = cr->n.scale;
1180 :
1181 5692 : cr->n = *src;
1182 5692 : return tds_numeric_change_prec_scale(&(cr->n), prec, scale);
1183 : }
1184 : break;
1185 4680 : case SYBFLT8:
1186 4680 : if (tds_numeric_to_string(src, u.tmpstr) < 0)
1187 : return TDS_CONVERT_FAIL;
1188 4680 : cr->f = atof(u.tmpstr);
1189 4680 : return 8;
1190 : break;
1191 4680 : case SYBREAL:
1192 4680 : if (tds_numeric_to_string(src, u.tmpstr) < 0)
1193 : return TDS_CONVERT_FAIL;
1194 4680 : cr->r = (TDS_REAL) atof(u.tmpstr);
1195 4680 : return 4;
1196 : break;
1197 : /* conversions not allowed */
1198 : case SYBUNIQUE:
1199 : case SYBDATETIME4:
1200 : case SYBDATETIME:
1201 : case SYBDATETIMN:
1202 : default:
1203 : break;
1204 : }
1205 : return TDS_CONVERT_NOAVAIL;
1206 : }
1207 :
1208 : static TDS_INT
1209 35772 : tds_convert_money4(const TDSCONTEXT * tds_ctx, const TDS_MONEY4 * src, int desttype, CONV_RESULT * cr)
1210 : {
1211 : TDS_MONEY4 mny;
1212 : long dollars;
1213 :
1214 35772 : mny = *src;
1215 35772 : switch (desttype) {
1216 1492 : case TDS_CONVERT_CHAR:
1217 : case CASE_ALL_CHAR: {
1218 : char tmp_str[33];
1219 : char *p;
1220 : unsigned dollars;
1221 : /*
1222 : * round to 2 decimal digits
1223 : * rounding with dollars = (mny.mny4 + 5000) /10000
1224 : * can give arithmetic overflow so I use
1225 : * dollars = (mny.mny4/50 + 1)/2
1226 : */
1227 : /* TODO round also all conversions to int and from money ?? */
1228 1492 : p = tmp_str;
1229 1492 : if (mny.mny4 < 0) {
1230 310 : *p++ = '-';
1231 : /* we use unsigned cause this cause arithmetic problem for -2^31*/
1232 310 : dollars = (unsigned) -mny.mny4;
1233 : } else {
1234 1182 : dollars = (unsigned) mny.mny4;
1235 : }
1236 1492 : if (tds_ctx->money_use_2_digits) {
1237 : /* print only 2 decimal digits as server does */
1238 0 : dollars = (dollars + 50) / 100;
1239 0 : sprintf(p, "%u.%02u", dollars / 100u, dollars % 100u);
1240 : } else {
1241 1492 : sprintf(p, "%u.%04u", dollars / 10000u, dollars % 10000u);
1242 : }
1243 1492 : return string_to_result(desttype, tmp_str, cr);
1244 : } break;
1245 2170 : case SYBSINT1:
1246 2170 : dollars = mny.mny4 / 10000;
1247 2170 : if (!IS_SINT1(dollars))
1248 : return TDS_CONVERT_OVERFLOW;
1249 430 : cr->ti = (TDS_TINYINT) dollars;
1250 : return sizeof(TDS_TINYINT);
1251 : break;
1252 4420 : case SYBINT1:
1253 : case SYBUINT1:
1254 4420 : dollars = mny.mny4 / 10000;
1255 4420 : if (!IS_TINYINT(dollars))
1256 : return TDS_CONVERT_OVERFLOW;
1257 940 : cr->ti = (TDS_TINYINT) dollars;
1258 : return sizeof(TDS_TINYINT);
1259 : break;
1260 2310 : case SYBINT2:
1261 2310 : dollars = mny.mny4 / 10000;
1262 2310 : if (!IS_SMALLINT(dollars))
1263 : return TDS_CONVERT_OVERFLOW;
1264 1460 : cr->si = (TDS_SMALLINT) dollars;
1265 : return sizeof(TDS_SMALLINT);
1266 : break;
1267 2250 : case SYBUINT2:
1268 2250 : dollars = mny.mny4 / 10000;
1269 2250 : if (!IS_USMALLINT(dollars))
1270 : return TDS_CONVERT_OVERFLOW;
1271 980 : cr->usi = (TDS_USMALLINT) dollars;
1272 : return sizeof(TDS_USMALLINT);
1273 : break;
1274 2370 : case SYBINT4:
1275 2370 : cr->i = mny.mny4 / 10000;
1276 : return sizeof(TDS_INT);
1277 : break;
1278 2270 : case SYBUINT4:
1279 2270 : dollars = mny.mny4 / 10000;
1280 2270 : if (!INT_IS_UINT(dollars))
1281 : return TDS_CONVERT_OVERFLOW;
1282 1220 : cr->ui = (TDS_UINT) dollars;
1283 : return sizeof(TDS_UINT);
1284 : break;
1285 2320 : case SYBINT8:
1286 2320 : cr->bi = mny.mny4 / 10000;
1287 : return sizeof(TDS_INT8);
1288 : break;
1289 2270 : case SYBUINT8:
1290 2270 : dollars = mny.mny4 / 10000;
1291 2270 : if (dollars < 0)
1292 : return TDS_CONVERT_OVERFLOW;
1293 1220 : cr->ubi = (TDS_UINT8) dollars;
1294 : return sizeof(TDS_UINT8);
1295 : break;
1296 70 : case SYBBIT:
1297 : case SYBBITN:
1298 70 : cr->ti = mny.mny4 ? 1 : 0;
1299 : return sizeof(TDS_TINYINT);
1300 : break;
1301 2170 : case SYBFLT8:
1302 2170 : cr->f = ((TDS_FLOAT) mny.mny4) / 10000.0;
1303 : return sizeof(TDS_FLOAT);
1304 : break;
1305 2170 : case SYBREAL:
1306 2170 : cr->r = (TDS_REAL) (mny.mny4 / 10000.0);
1307 : return sizeof(TDS_REAL);
1308 : break;
1309 2270 : case SYBMONEY:
1310 4540 : return set_money(mny.mny4, cr);
1311 : break;
1312 2260 : case SYBMONEY4:
1313 2260 : cr->m4 = mny;
1314 : return sizeof(TDS_MONEY4);
1315 : break;
1316 2330 : case SYBDECIMAL:
1317 : case SYBNUMERIC:
1318 2330 : if (mny.mny4 < 0)
1319 2200 : return tds_convert_int_numeric(4, 1, (TDS_UINT) -mny.mny4, cr);
1320 2460 : return tds_convert_int_numeric(4, 0, (TDS_UINT) mny.mny4, cr);
1321 : /* conversions not allowed */
1322 : case SYBUNIQUE:
1323 : case SYBDATETIME4:
1324 : case SYBDATETIME:
1325 : case SYBDATETIMN:
1326 : default:
1327 : return TDS_CONVERT_NOAVAIL;
1328 : break;
1329 : }
1330 : return TDS_CONVERT_FAIL;
1331 : }
1332 :
1333 : static TDS_INT
1334 54420 : tds_convert_money(const TDSCONTEXT * tds_ctx, const TDS_MONEY * src, int desttype, CONV_RESULT * cr)
1335 : {
1336 : char *s;
1337 :
1338 : TDS_INT8 mymoney, dollars;
1339 : char tmpstr[64];
1340 :
1341 54420 : tdsdump_log(TDS_DBG_FUNC, "tds_convert_money()\n");
1342 :
1343 : /* sometimes money it's only 4-byte aligned so always compute 64-bit */
1344 54420 : mymoney = ((TDS_INT8) src->tdsoldmoney.mnyhigh << 32) | src->tdsoldmoney.mnylow;
1345 :
1346 54420 : switch (desttype) {
1347 2006 : case TDS_CONVERT_CHAR:
1348 : case CASE_ALL_CHAR:
1349 2006 : s = tds_money_to_string(mymoney, tmpstr, tds_ctx->money_use_2_digits);
1350 2006 : return string_to_result(desttype, s, cr);
1351 : break;
1352 3430 : case SYBSINT1:
1353 3430 : if (mymoney <= -129 * 10000 || mymoney >= 128 * 10000)
1354 : return TDS_CONVERT_OVERFLOW;
1355 430 : cr->ti = (uint8_t) (((TDS_INT) mymoney) / 10000);
1356 : return sizeof(TDS_TINYINT);
1357 : break;
1358 6940 : case SYBINT1:
1359 : case SYBUINT1:
1360 6940 : if (mymoney <= -10000 || mymoney >= 256 * 10000)
1361 : return TDS_CONVERT_OVERFLOW;
1362 : /* TODO: round ?? */
1363 940 : cr->ti = (TDS_TINYINT) (((TDS_INT) mymoney) / 10000);
1364 : return sizeof(TDS_TINYINT);
1365 : break;
1366 3570 : case SYBINT2:
1367 3570 : if (mymoney <= -32769 * 10000 || mymoney >= 32768 * 10000)
1368 : return TDS_CONVERT_OVERFLOW;
1369 1460 : cr->si = (TDS_SMALLINT) (((TDS_INT) mymoney) / 10000);
1370 : return sizeof(TDS_SMALLINT);
1371 : break;
1372 3510 : case SYBUINT2:
1373 3510 : if (mymoney <= -1 * 10000 || mymoney >= 65536 * 10000)
1374 : return TDS_CONVERT_OVERFLOW;
1375 980 : cr->usi = (TDS_USMALLINT) (((TDS_INT) mymoney) / 10000);
1376 : return sizeof(TDS_USMALLINT);
1377 : break;
1378 3670 : case SYBINT4:
1379 3670 : dollars = mymoney / 10000;
1380 3670 : if (!INT_IS_INT(dollars))
1381 : return TDS_CONVERT_OVERFLOW;
1382 2820 : cr->i = (TDS_INT) dollars;
1383 : return sizeof(TDS_INT);
1384 : break;
1385 3570 : case SYBUINT4:
1386 3570 : dollars = mymoney / 10000;
1387 3570 : if (!INT_IS_UINT(dollars))
1388 : return TDS_CONVERT_OVERFLOW;
1389 1670 : cr->ui = (TDS_UINT) dollars;
1390 : return sizeof(TDS_UINT);
1391 : break;
1392 3680 : case SYBINT8:
1393 3680 : cr->bi = mymoney / 10000;
1394 : return sizeof(TDS_INT8);
1395 : break;
1396 3590 : case SYBUINT8:
1397 3590 : dollars = mymoney / 10000;
1398 3590 : if (dollars < 0)
1399 : return TDS_CONVERT_OVERFLOW;
1400 1910 : cr->ubi = (TDS_UINT8) dollars;
1401 : return sizeof(TDS_UINT8);
1402 : break;
1403 70 : case SYBBIT:
1404 : case SYBBITN:
1405 70 : cr->ti = mymoney ? 1 : 0;
1406 : return sizeof(TDS_TINYINT);
1407 : break;
1408 3484 : case SYBFLT8:
1409 3484 : cr->f = ((TDS_FLOAT) mymoney) / 10000.0;
1410 : return sizeof(TDS_FLOAT);
1411 : break;
1412 3430 : case SYBREAL:
1413 3430 : cr->r = (TDS_REAL) (mymoney / 10000.0);
1414 : return sizeof(TDS_REAL);
1415 : break;
1416 3530 : case SYBMONEY4:
1417 3530 : if (!INT_IS_INT(mymoney))
1418 : return TDS_CONVERT_OVERFLOW;
1419 2270 : cr->m4.mny4 = (TDS_INT) mymoney;
1420 : return sizeof(TDS_MONEY4);
1421 : break;
1422 3620 : case SYBMONEY:
1423 7240 : return set_money(mymoney, cr);
1424 : break;
1425 3690 : case SYBDECIMAL:
1426 : case SYBNUMERIC:
1427 3690 : if (mymoney < 0)
1428 3540 : return tds_convert_int8_numeric(4, 1, (TDS_UINT8) -mymoney, cr);
1429 3840 : return tds_convert_int8_numeric(4, 0, (TDS_UINT8) mymoney, cr);
1430 : break;
1431 : /* conversions not allowed */
1432 : case SYBUNIQUE:
1433 : case SYBDATETIME4:
1434 : case SYBDATETIME:
1435 : case SYBDATETIMN:
1436 : default:
1437 : break;
1438 : }
1439 : return TDS_CONVERT_NOAVAIL;
1440 : }
1441 :
1442 : static TDS_INT
1443 25526 : tds_convert_datetimeall(const TDSCONTEXT * tds_ctx, int srctype, const TDS_DATETIMEALL * dta, int desttype, CONV_RESULT * cr)
1444 : {
1445 : char whole_date_string[64];
1446 : const char *datetime_fmt;
1447 : TDSDATEREC when;
1448 :
1449 25526 : switch (desttype) {
1450 1724 : case TDS_CONVERT_CHAR:
1451 : case CASE_ALL_CHAR:
1452 1724 : tds_datecrack(srctype, dta, &when);
1453 1724 : datetime_fmt = tds_ctx->locale->datetime_fmt;
1454 1724 : if (srctype == SYBMSDATE && tds_ctx->locale->date_fmt)
1455 660 : datetime_fmt = tds_ctx->locale->date_fmt;
1456 1724 : if (srctype == SYBMSTIME && tds_ctx->locale->time_fmt)
1457 790 : datetime_fmt = tds_ctx->locale->time_fmt;
1458 1724 : tds_strftime(whole_date_string, sizeof(whole_date_string), datetime_fmt, &when,
1459 1724 : dta->time_prec);
1460 :
1461 1724 : return string_to_result(desttype, whole_date_string, cr);
1462 370 : case SYBDATETIME:
1463 370 : cr->dt.dtdays = dta->date;
1464 370 : cr->dt.dttime = (TDS_INT) ((dta->time * 3u + 50000u) / 100000u);
1465 : return sizeof(TDS_DATETIME);
1466 80 : case SYBDATETIME4:
1467 80 : if (!IS_USMALLINT(dta->date))
1468 : return TDS_CONVERT_OVERFLOW;
1469 80 : cr->dt4.days = (TDS_USMALLINT) dta->date;
1470 80 : cr->dt4.minutes = (TDS_USMALLINT) ((dta->time + 30u * 10000000u) / (60u * 10000000u));
1471 : return sizeof(TDS_DATETIME4);
1472 1612 : case SYBMSDATETIMEOFFSET:
1473 : case SYBMSDATE:
1474 : case SYBMSTIME:
1475 : case SYBMSDATETIME2:
1476 1612 : cr->dta = *dta;
1477 : return sizeof(TDS_DATETIMEALL);
1478 100 : case SYBDATE:
1479 100 : cr->date = dta->date;
1480 : return sizeof(TDS_DATE);
1481 80 : case SYBTIME:
1482 80 : cr->time = (TDS_INT) ((dta->time * 3u + 50000u) / 100000u);
1483 : return sizeof(TDS_TIME);
1484 90 : case SYB5BIGTIME:
1485 90 : cr->bigtime = dta->time / 10u;
1486 : return sizeof(TDS_UINT8);
1487 110 : case SYB5BIGDATETIME:
1488 220 : cr->bigtime = dta->time / 10u
1489 110 : + (dta->date + BIGDATETIME_BIAS) * (UINT64_C(86400) * 1000000u);
1490 : return sizeof(TDS_UINT8);
1491 : /* conversions not allowed */
1492 : case SYBUNIQUE:
1493 : case SYBBIT:
1494 : case SYBBITN:
1495 : case SYBINT1:
1496 : case SYBSINT1:
1497 : case SYBUINT1:
1498 : case SYBINT2:
1499 : case SYBUINT2:
1500 : case SYBINT4:
1501 : case SYBUINT4:
1502 : case SYBINT8:
1503 : case SYBUINT8:
1504 : case SYBMONEY4:
1505 : case SYBMONEY:
1506 : case SYBNUMERIC:
1507 : case SYBDECIMAL:
1508 : default:
1509 : break;
1510 : }
1511 : return TDS_CONVERT_NOAVAIL;
1512 : }
1513 :
1514 : static TDS_INT
1515 8738 : tds_convert_datetime(const TDSCONTEXT * tds_ctx, const TDS_DATETIME * dt, int desttype, unsigned precision, CONV_RESULT * cr)
1516 : {
1517 : char whole_date_string[64];
1518 : TDSDATEREC when;
1519 :
1520 8738 : switch (desttype) {
1521 1072 : case TDS_CONVERT_CHAR:
1522 : case CASE_ALL_CHAR:
1523 1072 : tds_datecrack(SYBDATETIME, dt, &when);
1524 1072 : tds_strftime(whole_date_string, sizeof(whole_date_string), tds_ctx->locale->datetime_fmt, &when, 3);
1525 :
1526 1072 : return string_to_result(desttype, whole_date_string, cr);
1527 10 : case SYBDATETIME:
1528 10 : cr->dt = *dt;
1529 : return sizeof(TDS_DATETIME);
1530 10 : case SYBDATETIME4:
1531 10 : if (!IS_USMALLINT(dt->dtdays))
1532 : return TDS_CONVERT_OVERFLOW;
1533 10 : cr->dt4.days = (TDS_USMALLINT) dt->dtdays;
1534 10 : cr->dt4.minutes = (dt->dttime / 300) / 60;
1535 : return sizeof(TDS_DATETIME4);
1536 30 : case SYBDATE:
1537 30 : cr->date = dt->dtdays;
1538 : return sizeof(TDS_DATE);
1539 30 : case SYBTIME:
1540 30 : cr->time = dt->dttime;
1541 : return sizeof(TDS_TIME);
1542 1246 : case SYBMSDATETIMEOFFSET:
1543 : case SYBMSDATE:
1544 : case SYBMSTIME:
1545 : case SYBMSDATETIME2:
1546 1246 : memset(&cr->dta, 0, sizeof(cr->dta));
1547 1246 : cr->dta.time_prec = precision;
1548 1246 : if (desttype == SYBMSDATETIMEOFFSET)
1549 28 : cr->dta.has_offset = 1;
1550 1246 : if (desttype != SYBMSDATE) {
1551 1218 : cr->dta.has_time = 1;
1552 1218 : cr->dta.time_prec = 3;
1553 1218 : cr->dta.time = (dt->dttime * UINT64_C(20) + 3) / 6 * 10000u;
1554 : }
1555 1246 : if (desttype != SYBMSTIME) {
1556 1218 : cr->dta.has_date = 1;
1557 1218 : cr->dta.date = dt->dtdays;
1558 : }
1559 : return sizeof(TDS_DATETIMEALL);
1560 20 : case SYB5BIGTIME:
1561 20 : cr->bigtime = (dt->dttime * UINT64_C(20) + 3u) / 6u * 1000u;
1562 : return sizeof(TDS_BIGTIME);
1563 20 : case SYB5BIGDATETIME:
1564 40 : cr->bigdatetime = (dt->dttime * UINT64_C(20) + 3u) / 6u * 1000u
1565 20 : + (dt->dtdays + BIGDATETIME_BIAS) * (UINT64_C(86400) * 1000000u);
1566 : return sizeof(TDS_BIGDATETIME);
1567 : /* conversions not allowed */
1568 : case SYBUNIQUE:
1569 : case SYBBIT:
1570 : case SYBBITN:
1571 : case SYBINT1:
1572 : case SYBSINT1:
1573 : case SYBUINT1:
1574 : case SYBINT2:
1575 : case SYBUINT2:
1576 : case SYBINT4:
1577 : case SYBUINT4:
1578 : case SYBINT8:
1579 : case SYBUINT8:
1580 : case SYBMONEY4:
1581 : case SYBMONEY:
1582 : case SYBNUMERIC:
1583 : case SYBDECIMAL:
1584 : default:
1585 : break;
1586 : }
1587 : return TDS_CONVERT_NOAVAIL;
1588 : }
1589 :
1590 : static TDS_INT
1591 3716 : tds_convert_datetime4(const TDSCONTEXT * tds_ctx, const TDS_DATETIME4 * dt4, int desttype, CONV_RESULT * cr)
1592 : {
1593 : TDS_DATETIME dt;
1594 :
1595 3716 : if (desttype == SYBDATETIME4) {
1596 0 : cr->dt4 = *dt4;
1597 0 : return sizeof(TDS_DATETIME4);
1598 : }
1599 :
1600 : /* convert to DATETIME and use tds_convert_datetime */
1601 3716 : dt.dtdays = dt4->days;
1602 3716 : dt.dttime = dt4->minutes * (60u * 300u);
1603 3716 : return tds_convert_datetime(tds_ctx, &dt, desttype, 0, cr);
1604 : }
1605 :
1606 : static TDS_INT
1607 3768 : tds_convert_time(const TDSCONTEXT * tds_ctx, const TDS_TIME * time, int desttype, CONV_RESULT * cr)
1608 : {
1609 : TDS_DATETIMEALL dta;
1610 :
1611 3768 : if (desttype == SYBTIME) {
1612 10 : cr->time = *time;
1613 10 : return sizeof(TDS_TIME);
1614 : }
1615 :
1616 : /* convert to DATETIMEALL and use tds_convert_datetimeall */
1617 3758 : memset(&dta, 0, sizeof(dta));
1618 3758 : dta.has_time = 1;
1619 3758 : dta.time_prec = 3;
1620 3758 : dta.time = (*time * UINT64_C(100000) + 2) / 3;
1621 3758 : dta.time = (*time * UINT64_C(20) + 3) / 6 * 10000;
1622 3758 : return tds_convert_datetimeall(tds_ctx, SYBMSTIME, &dta, desttype, cr);
1623 : }
1624 :
1625 : static TDS_INT
1626 3788 : tds_convert_date(const TDSCONTEXT * tds_ctx, const TDS_DATE * date, int desttype, CONV_RESULT * cr)
1627 : {
1628 : TDS_DATETIMEALL dta;
1629 :
1630 3788 : if (desttype == SYBDATE) {
1631 10 : cr->date = *date;
1632 10 : return sizeof(TDS_DATE);
1633 : }
1634 :
1635 : /* convert to DATETIMEALL and use tds_convert_datetimeall */
1636 3778 : memset(&dta, 0, sizeof(dta));
1637 3778 : dta.has_date = 1;
1638 3778 : dta.date = *date;
1639 3778 : return tds_convert_datetimeall(tds_ctx, SYBMSDATE, &dta, desttype, cr);
1640 : }
1641 :
1642 : static TDS_INT
1643 2758 : tds_convert_bigtime(const TDSCONTEXT * tds_ctx, const TDS_BIGTIME * bigtime, int desttype, CONV_RESULT * cr)
1644 : {
1645 : TDS_DATETIMEALL dta;
1646 :
1647 2758 : if (desttype == SYB5BIGTIME) {
1648 0 : cr->bigtime = *bigtime;
1649 0 : return sizeof(TDS_BIGTIME);
1650 : }
1651 :
1652 : /* convert to DATETIMEALL and use tds_convert_datetimeall */
1653 2758 : memset(&dta, 0, sizeof(dta));
1654 2758 : dta.time_prec = 6;
1655 2758 : dta.has_time = 1;
1656 2758 : dta.time = *bigtime % (UINT64_C(86400) * 1000000u) * 10u;
1657 2758 : return tds_convert_datetimeall(tds_ctx, SYBMSTIME, &dta, desttype, cr);
1658 : }
1659 :
1660 : static TDS_INT
1661 2816 : tds_convert_bigdatetime(const TDSCONTEXT * tds_ctx, const TDS_BIGDATETIME * bigdatetime, int desttype, CONV_RESULT * cr)
1662 : {
1663 : TDS_DATETIMEALL dta;
1664 : TDS_UINT8 bdt;
1665 :
1666 2816 : if (desttype == SYB5BIGDATETIME) {
1667 0 : cr->bigdatetime = *bigdatetime;
1668 : return sizeof(TDS_BIGDATETIME);
1669 : }
1670 :
1671 : /* convert to DATETIMEALL and use tds_convert_datetimeall */
1672 2816 : bdt = *bigdatetime;
1673 2816 : memset(&dta, 0, sizeof(dta));
1674 2816 : dta.time_prec = 6;
1675 2816 : dta.has_time = 1;
1676 2816 : dta.time = bdt % (UINT64_C(86400) * 1000000u) * 10u;
1677 2816 : bdt /= UINT64_C(86400) * 1000000u;
1678 2816 : dta.has_date = 1;
1679 2816 : dta.date = (TDS_INT) (bdt - BIGDATETIME_BIAS);
1680 2816 : return tds_convert_datetimeall(tds_ctx, SYBMSDATETIME2, &dta, desttype, cr);
1681 : }
1682 :
1683 :
1684 : static TDS_INT
1685 65972 : tds_convert_real(const TDS_REAL* src, int desttype, CONV_RESULT * cr)
1686 : {
1687 : TDS_REAL the_value;
1688 :
1689 : /* FIXME how big should be this buffer ?? */
1690 : char tmp_str[128];
1691 : TDS_INT mymoney4;
1692 :
1693 65972 : the_value = *src;
1694 :
1695 65972 : switch (desttype) {
1696 260 : case TDS_CONVERT_CHAR:
1697 : case CASE_ALL_CHAR:
1698 260 : sprintf(tmp_str, "%.9g", the_value);
1699 260 : return string_to_result(desttype, tmp_str, cr);
1700 : break;
1701 4470 : case SYBSINT1:
1702 4470 : if (!IS_SINT1(the_value))
1703 : return TDS_CONVERT_OVERFLOW;
1704 430 : cr->ti = (TDS_TINYINT) the_value;
1705 : return sizeof(TDS_TINYINT);
1706 : break;
1707 8940 : case SYBINT1:
1708 : case SYBUINT1:
1709 8940 : if (!IS_TINYINT(the_value))
1710 : return TDS_CONVERT_OVERFLOW;
1711 860 : cr->ti = (TDS_TINYINT) the_value;
1712 : return sizeof(TDS_TINYINT);
1713 : break;
1714 4520 : case SYBINT2:
1715 4520 : if (!IS_SMALLINT(the_value))
1716 : return TDS_CONVERT_OVERFLOW;
1717 1370 : cr->si = (TDS_SMALLINT) the_value;
1718 : return sizeof(TDS_SMALLINT);
1719 : break;
1720 4470 : case SYBUINT2:
1721 4470 : if (!IS_USMALLINT(the_value))
1722 : return TDS_CONVERT_OVERFLOW;
1723 900 : cr->usi = (TDS_USMALLINT) the_value;
1724 : return sizeof(TDS_USMALLINT);
1725 : break;
1726 4520 : case SYBINT4:
1727 4520 : if (!FLOAT_IS_INT(the_value))
1728 : return TDS_CONVERT_OVERFLOW;
1729 2640 : cr->i = (TDS_INT) the_value;
1730 : return sizeof(TDS_INT);
1731 : break;
1732 4470 : case SYBUINT4:
1733 4470 : if (!FLOAT_IS_UINT(the_value))
1734 : return TDS_CONVERT_OVERFLOW;
1735 1530 : cr->ui = (TDS_UINT) the_value;
1736 : return sizeof(TDS_UINT);
1737 : break;
1738 4470 : case SYBINT8:
1739 4470 : if (!FLOAT_IS_INT8(the_value))
1740 : return TDS_CONVERT_OVERFLOW;
1741 3850 : cr->bi = (TDS_INT8) the_value;
1742 : return sizeof(TDS_INT8);
1743 : break;
1744 4470 : case SYBUINT8:
1745 4470 : if (!FLOAT_IS_UINT8(the_value))
1746 : return TDS_CONVERT_OVERFLOW;
1747 2160 : cr->ubi = (TDS_UINT8) the_value;
1748 : return sizeof(TDS_UINT8);
1749 : break;
1750 70 : case SYBBIT:
1751 : case SYBBITN:
1752 70 : cr->ti = the_value ? 1 : 0;
1753 : return sizeof(TDS_TINYINT);
1754 : break;
1755 :
1756 4740 : case SYBFLT8:
1757 4740 : cr->f = the_value;
1758 : return sizeof(TDS_FLOAT);
1759 : break;
1760 :
1761 4622 : case SYBREAL:
1762 4622 : cr->r = the_value;
1763 : return sizeof(TDS_REAL);
1764 : break;
1765 :
1766 4420 : case SYBMONEY:
1767 4420 : if (the_value > (TDS_REAL) (TDS_INT8_MAX / 10000) || the_value < (TDS_REAL) (TDS_INT8_MIN / 10000))
1768 : return TDS_CONVERT_OVERFLOW;
1769 6760 : return set_money((TDS_INT8) (the_value * 10000), cr);
1770 : break;
1771 :
1772 4420 : case SYBMONEY4:
1773 4420 : if (the_value > (TDS_REAL) (TDS_INT_MAX / 10000) || the_value < (TDS_REAL) (TDS_INT_MIN / 10000))
1774 : return TDS_CONVERT_OVERFLOW;
1775 2120 : mymoney4 = (TDS_INT) (the_value * 10000);
1776 2120 : cr->m4.mny4 = mymoney4;
1777 : return sizeof(TDS_MONEY4);
1778 : break;
1779 4480 : case SYBNUMERIC:
1780 : case SYBDECIMAL:
1781 4480 : sprintf(tmp_str, "%.*f", cr->n.scale, the_value);
1782 4480 : return stringz_to_numeric(tmp_str, cr);
1783 : break;
1784 : /* not allowed */
1785 : case SYBUNIQUE:
1786 : case SYBDATETIME4:
1787 : case SYBDATETIME:
1788 : case SYBDATETIMN:
1789 : default:
1790 : break;
1791 : }
1792 : return TDS_CONVERT_NOAVAIL;
1793 : }
1794 :
1795 : /*
1796 : * TODO: emit SYBECLPR errors: "Data conversion resulted in loss of precision".
1797 : * There are many places where this would be correct to do, but the test is tedious
1798 : * (convert e.g. 1.5 -> SYBINT and test if output == input) and we don't have a good,
1799 : * API-independent alternative to tds_client_msg(). Postponed until then.
1800 : */
1801 : static TDS_INT
1802 66084 : tds_convert_flt8(const TDS_FLOAT* src, int desttype, CONV_RESULT * cr)
1803 : {
1804 : TDS_FLOAT the_value;
1805 : char tmp_str[25];
1806 :
1807 66084 : memcpy(&the_value, src, 8);
1808 66084 : switch (desttype) {
1809 308 : case TDS_CONVERT_CHAR:
1810 : case CASE_ALL_CHAR:
1811 308 : sprintf(tmp_str, "%.17g", the_value);
1812 308 : return string_to_result(desttype, tmp_str, cr);
1813 : break;
1814 4470 : case SYBSINT1:
1815 4470 : if (!IS_SINT1(the_value))
1816 : return TDS_CONVERT_OVERFLOW;
1817 430 : cr->ti = (TDS_TINYINT) the_value;
1818 430 : return sizeof(TDS_TINYINT);
1819 : break;
1820 8940 : case SYBINT1:
1821 : case SYBUINT1:
1822 8940 : if (!IS_TINYINT(the_value))
1823 : return TDS_CONVERT_OVERFLOW;
1824 860 : cr->ti = (TDS_TINYINT) the_value;
1825 860 : return sizeof(TDS_TINYINT);
1826 : break;
1827 4520 : case SYBINT2:
1828 4520 : if (!IS_SMALLINT(the_value))
1829 : return TDS_CONVERT_OVERFLOW;
1830 1370 : cr->si = (TDS_SMALLINT) the_value;
1831 1370 : return sizeof(TDS_SMALLINT);
1832 : break;
1833 4470 : case SYBUINT2:
1834 4470 : if (!IS_USMALLINT(the_value))
1835 : return TDS_CONVERT_OVERFLOW;
1836 900 : cr->usi = (TDS_USMALLINT) the_value;
1837 900 : return sizeof(TDS_USMALLINT);
1838 : break;
1839 4520 : case SYBINT4:
1840 4520 : if (!FLOAT_IS_INT(the_value))
1841 : return TDS_CONVERT_OVERFLOW;
1842 2630 : cr->i = (TDS_INT) the_value;
1843 2630 : return sizeof(TDS_INT);
1844 : break;
1845 4470 : case SYBUINT4:
1846 4470 : if (!FLOAT_IS_UINT(the_value))
1847 : return TDS_CONVERT_OVERFLOW;
1848 1530 : cr->ui = (TDS_UINT) the_value;
1849 1530 : return sizeof(TDS_UINT);
1850 : break;
1851 4470 : case SYBINT8:
1852 4470 : if (!FLOAT_IS_INT8(the_value))
1853 : return TDS_CONVERT_OVERFLOW;
1854 3850 : cr->bi = (TDS_INT8) the_value;
1855 3850 : return sizeof(TDS_INT8);
1856 : break;
1857 4470 : case SYBUINT8:
1858 4470 : if (!FLOAT_IS_UINT8(the_value))
1859 : return TDS_CONVERT_OVERFLOW;
1860 2160 : cr->ubi = (TDS_UINT8) the_value;
1861 2160 : return sizeof(TDS_UINT8);
1862 : break;
1863 70 : case SYBBIT:
1864 : case SYBBITN:
1865 70 : cr->ti = the_value ? 1 : 0;
1866 70 : return sizeof(TDS_TINYINT);
1867 : break;
1868 :
1869 4420 : case SYBMONEY:
1870 4420 : if (the_value > (TDS_FLOAT) (TDS_INT8_MAX / 10000) || the_value < (TDS_FLOAT) (TDS_INT8_MIN / 10000))
1871 : return TDS_CONVERT_OVERFLOW;
1872 6760 : return set_money((TDS_INT8) (the_value * 10000), cr);
1873 : break;
1874 4420 : case SYBMONEY4:
1875 4420 : if (the_value > (TDS_FLOAT) (TDS_INT_MAX / 10000) || the_value < (TDS_FLOAT) (TDS_INT_MIN / 10000))
1876 : return TDS_CONVERT_OVERFLOW;
1877 2120 : cr->m4.mny4 = (TDS_INT) (the_value * 10000);
1878 2120 : return sizeof(TDS_MONEY4);
1879 : break;
1880 4740 : case SYBREAL:
1881 : /* TODO check overflow */
1882 4740 : cr->r = (TDS_REAL)the_value;
1883 4740 : return sizeof(TDS_REAL);
1884 : break;
1885 4676 : case SYBFLT8:
1886 4676 : cr->f = the_value;
1887 4676 : return sizeof(TDS_FLOAT);
1888 : break;
1889 4490 : case SYBNUMERIC:
1890 : case SYBDECIMAL:
1891 4490 : sprintf(tmp_str, "%.*f", cr->n.scale, the_value);
1892 4490 : return stringz_to_numeric(tmp_str, cr);
1893 : break;
1894 : /* not allowed */
1895 : case SYBUNIQUE:
1896 : case SYBDATETIME4:
1897 : case SYBDATETIME:
1898 : case SYBDATETIMN:
1899 : default:
1900 : break;
1901 : }
1902 : return TDS_CONVERT_NOAVAIL;
1903 : }
1904 :
1905 : static TDS_INT
1906 3134 : tds_convert_unique(const TDS_CHAR * src, int desttype, CONV_RESULT * cr)
1907 : {
1908 : /*
1909 : * raw data is equivalent to structure and always aligned,
1910 : * so this cast is portable
1911 : */
1912 3134 : const TDS_UNIQUE *u = (const TDS_UNIQUE *) src;
1913 : char buf[37];
1914 :
1915 3134 : switch (desttype) {
1916 206 : case TDS_CONVERT_CHAR:
1917 : case CASE_ALL_CHAR:
1918 2266 : sprintf(buf, "%08X-%04X-%04X-%02X%02X-%02X%02X%02X%02X%02X%02X",
1919 618 : (int) u->Data1, (int) u->Data2, (int) u->Data3,
1920 1648 : u->Data4[0], u->Data4[1], u->Data4[2], u->Data4[3], u->Data4[4], u->Data4[5], u->Data4[6], u->Data4[7]);
1921 206 : return string_to_result(desttype, buf, cr);
1922 : break;
1923 68 : case SYBUNIQUE:
1924 : /*
1925 : * Here we can copy raw to structure because we adjust
1926 : * byte order in tds_swap_datatype
1927 : */
1928 68 : memcpy(&(cr->u), src, sizeof(TDS_UNIQUE));
1929 68 : return sizeof(TDS_UNIQUE);
1930 : break;
1931 : /* do not warn for not convertible types */
1932 : case SYBBIT:
1933 : case SYBBITN:
1934 : case SYBINT1:
1935 : case SYBSINT1:
1936 : case SYBUINT1:
1937 : case SYBINT2:
1938 : case SYBUINT2:
1939 : case SYBINT4:
1940 : case SYBUINT4:
1941 : case SYBINT8:
1942 : case SYBUINT8:
1943 : case SYBMONEY4:
1944 : case SYBMONEY:
1945 : case SYBDATETIME4:
1946 : case SYBDATETIME:
1947 : case SYBDATETIMN:
1948 : case SYBREAL:
1949 : case SYBFLT8:
1950 : default:
1951 : break;
1952 : }
1953 : return TDS_CONVERT_NOAVAIL;
1954 : }
1955 :
1956 : static TDS_INT
1957 16590 : tds_convert_to_binary(int srctype, const TDS_CHAR * src, TDS_UINT srclen, int desttype, CONV_RESULT * cr)
1958 : {
1959 : size_t len;
1960 : TDS_CHAR *ib;
1961 :
1962 16590 : switch (srctype) {
1963 768 : case CASE_ALL_BINARY:
1964 768 : len = srclen;
1965 768 : break;
1966 : case SYBBIT:
1967 : case SYBBITN:
1968 : case SYBINT1:
1969 : case SYBSINT1:
1970 : case SYBUINT1:
1971 : len = 1;
1972 : break;
1973 130 : case SYBINT2:
1974 : case SYBUINT2:
1975 130 : len = 2;
1976 130 : break;
1977 220 : case SYBINT4:
1978 : case SYBUINT4:
1979 220 : len = 4;
1980 220 : break;
1981 150 : case SYBINT8:
1982 : case SYBUINT8:
1983 150 : len = sizeof(TDS_INT8);
1984 150 : break;
1985 60 : case SYBMONEY4:
1986 60 : len = sizeof(TDS_MONEY4);
1987 60 : break;
1988 60 : case SYBMONEY:
1989 60 : len = sizeof(TDS_MONEY);
1990 60 : break;
1991 150 : case SYBNUMERIC:
1992 : case SYBDECIMAL:
1993 : {
1994 : /*
1995 : * Same format as Sybase library: sign and digits (as in
1996 : * protocol) padded with zeroes, no precision and scale.
1997 : */
1998 150 : const TDS_NUMERIC *num = (const TDS_NUMERIC *) src;
1999 : unsigned char buf[sizeof(num->array)];
2000 :
2001 150 : if (num->precision < 1 || num->precision > MAXPRECISION)
2002 : return TDS_CONVERT_FAIL;
2003 150 : memset(buf, 0, sizeof(buf));
2004 150 : memcpy(buf, num->array, tds_numeric_bytes_per_prec[num->precision]);
2005 150 : return binary_to_result(desttype, buf, sizeof(buf), cr);
2006 : }
2007 60 : case SYBREAL:
2008 60 : len = sizeof(TDS_REAL);
2009 60 : break;
2010 60 : case SYBFLT8:
2011 60 : len = sizeof(TDS_FLOAT);
2012 60 : break;
2013 60 : case SYBDATETIME:
2014 60 : len = sizeof(TDS_DATETIME);
2015 60 : break;
2016 60 : case SYBDATETIME4:
2017 60 : len = sizeof(TDS_DATETIME4);
2018 60 : break;
2019 60 : case SYBTIME:
2020 60 : len = sizeof(TDS_TIME);
2021 60 : break;
2022 60 : case SYBDATE:
2023 60 : len = sizeof(TDS_DATE);
2024 60 : break;
2025 240 : case SYBMSTIME:
2026 : case SYBMSDATE:
2027 : case SYBMSDATETIME2:
2028 : case SYBMSDATETIMEOFFSET:
2029 240 : len = sizeof(TDS_DATETIMEALL);
2030 240 : break;
2031 60 : case SYB5BIGTIME:
2032 60 : len = sizeof(TDS_BIGTIME);
2033 60 : break;
2034 60 : case SYB5BIGDATETIME:
2035 60 : len = sizeof(TDS_BIGDATETIME);
2036 60 : break;
2037 60 : case SYBUNIQUE:
2038 60 : len = sizeof(TDS_UNIQUE);
2039 60 : break;
2040 942 : case CASE_ALL_CHAR:
2041 942 : srclen = (TDS_UINT) tds_hex_trim(&src, srclen);
2042 :
2043 : /* a binary string output will be half the length of */
2044 : /* the string which represents it in hexadecimal */
2045 :
2046 942 : ib = cr->cb.ib;
2047 942 : if (desttype != TDS_CONVERT_BINARY) {
2048 : TDS_INT destlen;
2049 :
2050 728 : cr->ib = tds_new(TDS_CHAR, (srclen + 2u) / 2u);
2051 728 : test_alloc(cr->ib);
2052 728 : ib = cr->ib;
2053 728 : destlen = tds_char2hex(ib, 0xffffffffu, src, srclen);
2054 728 : if (destlen < 0)
2055 0 : TDS_ZERO_FREE(cr->ib);
2056 : return destlen;
2057 : }
2058 214 : return (TDS_INT) tds_char2hex(ib, cr->cb.len, src, srclen);
2059 :
2060 : default:
2061 : return TDS_CONVERT_NOAVAIL;
2062 : }
2063 2478 : return binary_to_result(desttype, src, len, cr);
2064 : }
2065 :
2066 : /**
2067 : * tds_convert
2068 : * converts a type to another.
2069 : * @p srctype and @p desttype should be SYB* TDS types, or, in case of @p desttype you can use
2070 : * TDS_CONVERT_CHAR/TDS_CONVERT_BINARY. Nullable types are not supported, use tds_get_conversion_type
2071 : * to get a not-nullable type.
2072 : *
2073 : * If you convert to SYBDECIMAL/SYBNUMERIC you MUST initialize precision and scale of cr->n.
2074 : *
2075 : * In case of fixed type you can pass directly the pointer to the value.
2076 : *
2077 : * Do not expect strings to be zero terminated. Databases support zero inside
2078 : * string. Using strlen may result on data loss or even a segmentation fault.
2079 : * Instead, use memcpy to copy destination using length returned.
2080 : *
2081 : * This function does not handle NULL, @p srclen should be >0. Client libraries handle NULLs each in their own way.
2082 : * @param tds_ctx context (used in conversion to data and to return messages)
2083 : * @param srctype type of source
2084 : * @param src pointer to source data to convert
2085 : * @param srclen length in bytes of source (not counting terminator or strings)
2086 : * @param desttype type of destination
2087 : * @param cr structure to hold result
2088 : * @return length of result or TDS_CONVERT_* failure code on failure. All TDS_CONVERT_* error constants are <0.
2089 : */
2090 : TDS_INT
2091 2724680 : tds_convert(const TDSCONTEXT *tds_ctx, int srctype, const void *src, TDS_UINT srclen, int desttype, CONV_RESULT *cr)
2092 : {
2093 2724680 : TDS_INT length = 0;
2094 :
2095 2724680 : assert(srclen >= 0 && srclen <= 2147483647u);
2096 :
2097 2724680 : if (srctype == SYBVARIANT) {
2098 2568 : const TDSVARIANT *v = (const TDSVARIANT*) src;
2099 2568 : srctype = v->type;
2100 2568 : src = v->data;
2101 2568 : srclen = v->data_len;
2102 : }
2103 :
2104 2724680 : switch (desttype) {
2105 16590 : case CASE_ALL_BINARY:
2106 16590 : return tds_convert_to_binary(srctype, src, srclen, desttype, cr);
2107 : }
2108 :
2109 2708090 : switch (srctype) {
2110 1489244 : case CASE_ALL_CHAR:
2111 1489244 : length = tds_convert_char(src, srclen, desttype, cr);
2112 1489244 : break;
2113 35772 : case SYBMONEY4:
2114 35772 : length = tds_convert_money4(tds_ctx, (const TDS_MONEY4 *) src, desttype, cr);
2115 35772 : break;
2116 54420 : case SYBMONEY:
2117 54420 : length = tds_convert_money(tds_ctx, (const TDS_MONEY *) src, desttype, cr);
2118 54420 : break;
2119 75248 : case SYBNUMERIC:
2120 : case SYBDECIMAL:
2121 75248 : length = tds_convert_numeric((const TDS_NUMERIC *) src, desttype, cr);
2122 75248 : break;
2123 6618 : case SYBBIT:
2124 : case SYBBITN:
2125 13236 : length = tds_convert_bit(src, desttype, cr);
2126 6618 : break;
2127 8424 : case SYBSINT1:
2128 16848 : length = tds_convert_int1((const int8_t *) src, desttype, cr);
2129 8424 : break;
2130 23056 : case SYBINT1:
2131 : case SYBUINT1:
2132 46112 : length = tds_convert_uint1((const TDS_TINYINT *) src, desttype, cr);
2133 23056 : break;
2134 28138 : case SYBINT2:
2135 56276 : length = tds_convert_int2((const TDS_SMALLINT *) src, desttype, cr);
2136 28138 : break;
2137 16562 : case SYBUINT2:
2138 33124 : length = tds_convert_uint2((const TDS_USMALLINT *) src, desttype, cr);
2139 16562 : break;
2140 113788 : case SYBINT4:
2141 227576 : length = tds_convert_int4((const TDS_INT *) src, desttype, cr);
2142 113788 : break;
2143 27378 : case SYBUINT4:
2144 54756 : length = tds_convert_uint4((const TDS_UINT *) src, desttype, cr);
2145 27378 : break;
2146 61284 : case SYBINT8:
2147 61284 : length = tds_convert_int8((const TDS_INT8 *) src, desttype, cr);
2148 61284 : break;
2149 35292 : case SYBUINT8:
2150 35292 : length = tds_convert_uint8((const TDS_UINT8 *) src, desttype, cr);
2151 35292 : break;
2152 65972 : case SYBREAL:
2153 65972 : length = tds_convert_real((const TDS_REAL *) src, desttype, cr);
2154 65972 : break;
2155 66084 : case SYBFLT8:
2156 66084 : length = tds_convert_flt8((const TDS_FLOAT *) src, desttype, cr);
2157 66084 : break;
2158 12416 : case SYBMSTIME:
2159 : case SYBMSDATE:
2160 : case SYBMSDATETIME2:
2161 : case SYBMSDATETIMEOFFSET:
2162 12416 : length = tds_convert_datetimeall(tds_ctx, srctype, (const TDS_DATETIMEALL *) src, desttype, cr);
2163 12416 : break;
2164 5022 : case SYBDATETIME:
2165 5022 : length = tds_convert_datetime(tds_ctx, (const TDS_DATETIME* ) src, desttype, 3, cr);
2166 5022 : break;
2167 3716 : case SYBDATETIME4:
2168 3716 : length = tds_convert_datetime4(tds_ctx, (const TDS_DATETIME4* ) src, desttype, cr);
2169 3716 : break;
2170 3768 : case SYBTIME:
2171 3768 : length = tds_convert_time(tds_ctx, (const TDS_TIME *) src, desttype, cr);
2172 3768 : break;
2173 3788 : case SYBDATE:
2174 3788 : length = tds_convert_date(tds_ctx, (const TDS_DATE *) src, desttype, cr);
2175 3788 : break;
2176 2758 : case SYB5BIGTIME:
2177 2758 : length = tds_convert_bigtime(tds_ctx, (const TDS_BIGTIME *) src, desttype, cr);
2178 2758 : break;
2179 2816 : case SYB5BIGDATETIME:
2180 2816 : length = tds_convert_bigdatetime(tds_ctx, (const TDS_BIGDATETIME *) src, desttype, cr);
2181 2816 : break;
2182 18502 : case CASE_ALL_BINARY:
2183 18502 : length = tds_convert_binary((const TDS_UCHAR *) src, srclen, desttype, cr);
2184 18502 : break;
2185 3134 : case SYBUNIQUE:
2186 3134 : length = tds_convert_unique(src, desttype, cr);
2187 3134 : break;
2188 : case SYBNVARCHAR:
2189 : case SYBNTEXT:
2190 : case SYBMSTABLE:
2191 : default:
2192 : length = TDS_CONVERT_NOAVAIL;
2193 : break;
2194 : }
2195 :
2196 : return length;
2197 : }
2198 :
2199 : static int
2200 3148 : string_to_datetime(const char *instr, TDS_UINT len, int desttype, CONV_RESULT * cr)
2201 : {
2202 : enum states {
2203 : GOING_IN_BLIND,
2204 : PUT_NUMERIC_IN_CONTEXT,
2205 : DOING_ALPHABETIC_DATE
2206 : };
2207 :
2208 : char *in;
2209 : char *tok;
2210 : char *lasts;
2211 : char last_token[32];
2212 3148 : int monthdone = 0;
2213 3148 : int yeardone = 0;
2214 3148 : int mdaydone = 0;
2215 :
2216 : struct tds_time t;
2217 :
2218 : unsigned int dt_time;
2219 : TDS_INT dt_days;
2220 : int i;
2221 :
2222 : enum states current_state;
2223 :
2224 3148 : memset(&t, '\0', sizeof(t));
2225 3148 : t.tm_mday = 1;
2226 :
2227 3148 : in = tds_strndup(instr, len);
2228 3148 : test_alloc(in);
2229 :
2230 3148 : tok = strtok_r(in, " ,", &lasts);
2231 :
2232 3148 : current_state = GOING_IN_BLIND;
2233 :
2234 12204 : while (tok != NULL) {
2235 :
2236 5918 : tdsdump_log(TDS_DBG_INFO1, "string_to_datetime: current_state = %d\n", current_state);
2237 5918 : switch (current_state) {
2238 4158 : case GOING_IN_BLIND:
2239 : /* If we have no idea of current context, then if we have */
2240 : /* encountered a purely alphabetic string, it MUST be an */
2241 : /* alphabetic month name or prefix... */
2242 :
2243 4158 : if (is_alphabetic(tok)) {
2244 870 : tdsdump_log(TDS_DBG_INFO1, "string_to_datetime: is_alphabetic\n");
2245 870 : if (store_monthname(tok, &t) >= 0) {
2246 860 : monthdone++;
2247 860 : current_state = DOING_ALPHABETIC_DATE;
2248 : } else {
2249 : goto string_garbled;
2250 : }
2251 : }
2252 :
2253 : /* ...whereas if it is numeric, it could be a number of */
2254 : /* things... */
2255 :
2256 3288 : else if (is_numeric(tok)) {
2257 40 : tdsdump_log(TDS_DBG_INFO1, "string_to_datetime: is_numeric\n");
2258 40 : switch (strlen(tok)) {
2259 : /* in this context a 4 character numeric can */
2260 : /* ONLY be the year part of an alphabetic date */
2261 :
2262 0 : case 4:
2263 0 : store_year(atoi(tok), &t);
2264 0 : yeardone++;
2265 0 : current_state = DOING_ALPHABETIC_DATE;
2266 0 : break;
2267 :
2268 : /* whereas these could be the hour part of a */
2269 : /* time specification ( 4 PM ) or the leading */
2270 : /* day part of an alphabetic date ( 15 Jan ) */
2271 :
2272 20 : case 2:
2273 : case 1:
2274 20 : strcpy(last_token, tok);
2275 20 : current_state = PUT_NUMERIC_IN_CONTEXT;
2276 20 : break;
2277 :
2278 : /* this must be a [YY]YYMMDD date */
2279 :
2280 20 : case 6:
2281 : case 8:
2282 20 : if (store_yymmdd_date(tok, &t))
2283 : current_state = GOING_IN_BLIND;
2284 : else
2285 : goto string_garbled;
2286 : break;
2287 :
2288 : /* anything else is nonsense... */
2289 :
2290 : default:
2291 : goto string_garbled;
2292 : break;
2293 : }
2294 : }
2295 :
2296 : /* it could be [M]M/[D]D/[YY]YY format */
2297 :
2298 3248 : else if (is_numeric_dateformat(tok)) {
2299 1210 : tdsdump_log(TDS_DBG_INFO1, "string_to_datetime: is_numeric_dateformat\n");
2300 1210 : store_numeric_date(tok, &t);
2301 1210 : current_state = GOING_IN_BLIND;
2302 2038 : } else if (is_dd_mon_yyyy(tok)) {
2303 10 : tdsdump_log(TDS_DBG_INFO1, "string_to_datetime: is_dd_mon_yyyy\n");
2304 10 : store_dd_mon_yyy_date(tok, &t);
2305 10 : current_state = GOING_IN_BLIND;
2306 2028 : } else if (is_timeformat(tok)) {
2307 2028 : tdsdump_log(TDS_DBG_INFO1, "string_to_datetime: is_timeformat\n");
2308 2028 : store_time(tok, &t);
2309 2028 : current_state = GOING_IN_BLIND;
2310 : } else {
2311 0 : tdsdump_log(TDS_DBG_INFO1, "string_to_datetime: string_garbled\n");
2312 : goto string_garbled;
2313 : }
2314 :
2315 : break; /* end of GOING_IN_BLIND */
2316 :
2317 1740 : case DOING_ALPHABETIC_DATE:
2318 :
2319 1740 : if (is_alphabetic(tok)) {
2320 0 : if (!monthdone && store_monthname(tok, &t) >= 0) {
2321 0 : monthdone++;
2322 0 : if (monthdone && yeardone && mdaydone)
2323 : current_state = GOING_IN_BLIND;
2324 : else
2325 0 : current_state = DOING_ALPHABETIC_DATE;
2326 : } else {
2327 : goto string_garbled;
2328 : }
2329 1740 : } else if (is_numeric(tok)) {
2330 1740 : if (mdaydone && yeardone)
2331 : goto string_garbled;
2332 : else
2333 1740 : switch (strlen(tok)) {
2334 880 : case 4:
2335 1760 : store_year(atoi(tok), &t);
2336 880 : yeardone++;
2337 880 : if (monthdone && yeardone && mdaydone)
2338 : current_state = GOING_IN_BLIND;
2339 : else
2340 0 : current_state = DOING_ALPHABETIC_DATE;
2341 : break;
2342 :
2343 860 : case 2:
2344 : case 1:
2345 860 : if (!mdaydone) {
2346 1720 : store_mday(tok, &t);
2347 :
2348 860 : mdaydone++;
2349 860 : if (monthdone && yeardone && mdaydone)
2350 : current_state = GOING_IN_BLIND;
2351 : else
2352 860 : current_state = DOING_ALPHABETIC_DATE;
2353 : } else {
2354 0 : store_year(atoi(tok), &t);
2355 0 : yeardone++;
2356 0 : if (monthdone && yeardone && mdaydone)
2357 : current_state = GOING_IN_BLIND;
2358 : else
2359 0 : current_state = DOING_ALPHABETIC_DATE;
2360 : }
2361 : break;
2362 :
2363 : default:
2364 : goto string_garbled;
2365 : }
2366 : } else {
2367 : goto string_garbled;
2368 : }
2369 :
2370 : break; /* end of DOING_ALPHABETIC_DATE */
2371 :
2372 20 : case PUT_NUMERIC_IN_CONTEXT:
2373 :
2374 20 : if (is_alphabetic(tok)) {
2375 20 : if (store_monthname(tok, &t) >= 0) {
2376 40 : store_mday(last_token, &t);
2377 20 : mdaydone++;
2378 20 : monthdone++;
2379 20 : if (monthdone && yeardone && mdaydone)
2380 : current_state = GOING_IN_BLIND;
2381 : else
2382 20 : current_state = DOING_ALPHABETIC_DATE;
2383 0 : } else if (is_ampm(tok)) {
2384 0 : store_hour(last_token, tok, &t);
2385 0 : current_state = GOING_IN_BLIND;
2386 : } else {
2387 : goto string_garbled;
2388 : }
2389 0 : } else if (is_numeric(tok)) {
2390 0 : switch (strlen(tok)) {
2391 : case 4:
2392 : case 2:
2393 0 : store_mday(last_token, &t);
2394 0 : mdaydone++;
2395 0 : store_year(atoi(tok), &t);
2396 0 : yeardone++;
2397 :
2398 0 : if (monthdone && yeardone && mdaydone)
2399 : current_state = GOING_IN_BLIND;
2400 : else
2401 0 : current_state = DOING_ALPHABETIC_DATE;
2402 : break;
2403 :
2404 : default:
2405 : goto string_garbled;
2406 : }
2407 : } else {
2408 : goto string_garbled;
2409 : }
2410 :
2411 : break; /* end of PUT_NUMERIC_IN_CONTEXT */
2412 : }
2413 :
2414 5908 : tok = strtok_r(NULL, " ,", &lasts);
2415 : }
2416 :
2417 3138 : i = (t.tm_mon - 13) / 12;
2418 9414 : dt_days = 1461 * (t.tm_year + 1900 + i) / 4 +
2419 6276 : (367 * (t.tm_mon - 1 - 12 * i)) / 12 - (3 * ((t.tm_year + 2000 + i) / 100)) / 4 + t.tm_mday - 693932;
2420 :
2421 3138 : free(in);
2422 :
2423 3138 : if (desttype == SYBDATE) {
2424 188 : cr->date = dt_days;
2425 188 : return sizeof(TDS_DATE);
2426 : }
2427 2950 : dt_time = t.tm_hour * 60 + t.tm_min;
2428 : /* TODO check for overflow */
2429 2950 : if (desttype == SYBDATETIME4) {
2430 680 : cr->dt4.days = dt_days;
2431 680 : cr->dt4.minutes = dt_time;
2432 680 : return sizeof(TDS_DATETIME4);
2433 : }
2434 2270 : dt_time = dt_time * 60 + t.tm_sec;
2435 2270 : if (desttype == SYBDATETIME) {
2436 842 : cr->dt.dtdays = dt_days;
2437 842 : cr->dt.dttime = dt_time * 300 + (t.tm_ns / 1000000u * 300 + 150) / 1000;
2438 842 : return sizeof(TDS_DATETIME);
2439 : }
2440 1428 : if (desttype == SYBTIME) {
2441 188 : cr->time = dt_time * 300 + (t.tm_ns / 1000000u * 300 + 150) / 1000;
2442 188 : return sizeof(TDS_TIME);
2443 : }
2444 1240 : if (desttype == SYB5BIGTIME) {
2445 108 : cr->bigtime = dt_time * UINT64_C(1000000) + t.tm_ns / 1000u;
2446 108 : return sizeof(TDS_BIGTIME);
2447 : }
2448 1132 : if (desttype == SYB5BIGDATETIME) {
2449 332 : cr->bigdatetime = (dt_days + BIGDATETIME_BIAS) * (UINT64_C(86400) * 1000000u)
2450 166 : + dt_time * UINT64_C(1000000) + t.tm_ns / 1000u;
2451 166 : return sizeof(TDS_BIGDATETIME);
2452 : }
2453 :
2454 966 : cr->dta.has_offset = 0;
2455 966 : cr->dta.offset = 0;
2456 966 : cr->dta.has_date = 1;
2457 966 : cr->dta.date = dt_days;
2458 966 : cr->dta.has_time = 1;
2459 966 : cr->dta.time_prec = 7; /* TODO correct value */
2460 966 : cr->dta.time = dt_time * UINT64_C(10000000) + t.tm_ns / 100u;
2461 966 : return sizeof(TDS_DATETIMEALL);
2462 :
2463 10 : string_garbled:
2464 10 : tdsdump_log(TDS_DBG_INFO1,
2465 : "error_handler: Attempt to convert data stopped by syntax error in source field \n");
2466 10 : free(in);
2467 10 : return TDS_CONVERT_SYNTAX;
2468 : }
2469 :
2470 : static int
2471 8970 : stringz_to_numeric(const char *instr, CONV_RESULT * cr)
2472 : {
2473 8970 : return string_to_numeric(instr, instr + strlen(instr), cr);
2474 : }
2475 :
2476 : static int
2477 116700 : string_to_numeric(const char *instr, const char *pend, CONV_RESULT * cr)
2478 : {
2479 : char mynumber[(MAXPRECISION + 7) / 8 * 8 + 8];
2480 :
2481 : /* num packaged 8 digit, see below for detail */
2482 : TDS_UINT packed_num[(MAXPRECISION + 7) / 8];
2483 :
2484 : char *ptr;
2485 :
2486 116700 : int i = 0;
2487 116700 : int j = 0;
2488 : int bytes;
2489 :
2490 : bool negative;
2491 : size_t digits, decimals;
2492 :
2493 : /* FIXME: application can pass invalid value for precision and scale ?? */
2494 116700 : if (cr->n.precision > MAXPRECISION)
2495 : return TDS_CONVERT_FAIL;
2496 :
2497 116700 : if (cr->n.precision == 0)
2498 0 : cr->n.precision = MAXPRECISION; /* assume max precision */
2499 :
2500 116700 : if (cr->n.scale > cr->n.precision)
2501 : return TDS_CONVERT_FAIL;
2502 :
2503 116700 : instr = parse_numeric(instr, pend, &negative, &digits, &decimals);
2504 116700 : if (!instr)
2505 : return TDS_CONVERT_SYNTAX;
2506 :
2507 116690 : cr->n.array[0] = negative ? 1 : 0;
2508 :
2509 : /* translate a number like 000ddddd.ffff to 00000000dddddffff00 */
2510 :
2511 : /*
2512 : * Having disposed of any sign and leading blanks,
2513 : * vet the digit string, counting places before and after
2514 : * the decimal point. Dispense with trailing blanks, if any.
2515 : */
2516 :
2517 116690 : ptr = mynumber;
2518 1050210 : for (i = 0; i < 8; ++i)
2519 933520 : *ptr++ = '0';
2520 :
2521 : /* too many digits, error */
2522 116690 : if (cr->n.precision - cr->n.scale < digits)
2523 : return TDS_CONVERT_OVERFLOW;
2524 :
2525 : /* copy digits before the dot */
2526 116400 : memcpy(ptr, instr, digits);
2527 116400 : ptr += digits;
2528 116400 : instr += digits + 1;
2529 :
2530 : /* copy digits after the dot */
2531 116400 : if (decimals > cr->n.scale)
2532 130 : decimals = cr->n.scale;
2533 116400 : memcpy(ptr, instr, decimals);
2534 :
2535 : /* fill up decimal digits */
2536 116400 : memset(ptr + decimals, '0', cr->n.scale - decimals);
2537 116400 : ptr += cr->n.scale;
2538 :
2539 : /*
2540 : * Packaged number explanation:
2541 : * We package 8 decimal digits in one number.
2542 : * Because 10^8 = 5^8 * 2^8 = 5^8 * 256, dividing 10^8 by 256 leaves no remainder.
2543 : * We can thus split it into bytes in an optimized way.
2544 : */
2545 :
2546 : /* transform to packaged one */
2547 116400 : j = -1;
2548 116400 : ptr -= 8;
2549 : do {
2550 183210 : TDS_UINT n = *ptr++;
2551 :
2552 1465680 : for (i = 1; i < 8; ++i)
2553 1282470 : n = n * 10u + *ptr++;
2554 : /* fix packet number and store */
2555 183210 : packed_num[++j] = n - ((TDS_UINT) '0' * 11111111lu);
2556 183210 : ptr -= 16;
2557 183210 : } while (ptr > mynumber);
2558 :
2559 116400 : memset(cr->n.array + 1, 0, sizeof(cr->n.array) - 1);
2560 116400 : bytes = tds_numeric_bytes_per_prec[cr->n.precision];
2561 232830 : while (j > 0 && !packed_num[j])
2562 30 : --j;
2563 :
2564 431340 : for (;;) {
2565 547740 : bool is_zero = true;
2566 547740 : TDS_UINT carry = 0;
2567 547740 : i = j;
2568 547740 : if (!packed_num[j])
2569 183180 : --j;
2570 : do {
2571 793530 : TDS_UINT tmp = packed_num[i];
2572 793530 : if (tmp)
2573 609090 : is_zero = false;
2574 :
2575 : /* divide for 256 for find another byte */
2576 : /*
2577 : * carry * (25u*25u*25u*25u) = carry * 10^8 / 256u
2578 : * using unsigned number is just an optimization
2579 : * compiler can translate division to a shift and remainder
2580 : * to a binary AND
2581 : */
2582 793530 : packed_num[i] = carry * (25u * 25u * 25u * 25u) + tmp / 256u;
2583 793530 : carry = tmp % 256u;
2584 793530 : } while(--i >= 0);
2585 547740 : if (is_zero)
2586 : break;
2587 : /*
2588 : * source number is limited to 38 decimal digit
2589 : * 10^39-1 < 2^128 (16 byte) so this cannot make an overflow
2590 : */
2591 431340 : cr->n.array[--bytes] = carry;
2592 : }
2593 : return sizeof(TDS_NUMERIC);
2594 : }
2595 :
2596 : static bool
2597 3248 : is_numeric_dateformat(const char *t)
2598 : {
2599 : const char *instr;
2600 3248 : int slashes = 0;
2601 3248 : int hyphens = 0;
2602 3248 : int periods = 0;
2603 3248 : int digits = 0;
2604 :
2605 18884 : for (instr = t; *instr; instr++) {
2606 17674 : if (!isdigit((unsigned char) *instr) && *instr != '/' && *instr != '-' && *instr != '.')
2607 : return false;
2608 :
2609 15636 : if (*instr == '/')
2610 0 : slashes++;
2611 15636 : else if (*instr == '-')
2612 2420 : hyphens++;
2613 13216 : else if (*instr == '.')
2614 0 : periods++;
2615 : else
2616 13216 : digits++;
2617 :
2618 : }
2619 1210 : if (hyphens + slashes + periods != 2)
2620 : return false;
2621 1210 : if (hyphens == 1 || slashes == 1 || periods == 1)
2622 : return false;
2623 :
2624 1210 : if (digits < 4 || digits > 8)
2625 : return false;
2626 :
2627 1210 : return true;
2628 :
2629 : }
2630 :
2631 : /* This function will check if an alphanumeric string */
2632 : /* holds a date in any of the following formats : */
2633 : /* DD-MON-YYYY */
2634 : /* DD-MON-YY */
2635 : /* DDMONYY */
2636 : /* DDMONYYYY */
2637 : static bool
2638 2038 : is_dd_mon_yyyy(char *t)
2639 : {
2640 : char *instr;
2641 : char month[4];
2642 :
2643 2038 : instr = t;
2644 :
2645 2038 : if (!isdigit((unsigned char) *instr))
2646 : return false;
2647 :
2648 2038 : instr++;
2649 :
2650 2038 : if (!isdigit((unsigned char) *instr))
2651 : return false;
2652 :
2653 1498 : instr++;
2654 :
2655 1498 : if (*instr == '-') {
2656 0 : instr++;
2657 :
2658 0 : strlcpy(month, instr, 4);
2659 :
2660 0 : if (!is_monthname(month))
2661 : return false;
2662 :
2663 0 : instr += 3;
2664 :
2665 0 : if (*instr != '-')
2666 : return false;
2667 :
2668 0 : instr++;
2669 0 : if (!isdigit((unsigned char) *instr))
2670 : return false;
2671 :
2672 0 : instr++;
2673 0 : if (!isdigit((unsigned char) *instr))
2674 : return false;
2675 :
2676 0 : instr++;
2677 :
2678 0 : if (*instr) {
2679 0 : if (!isdigit((unsigned char) *instr))
2680 : return false;
2681 :
2682 0 : instr++;
2683 0 : if (!isdigit((unsigned char) *instr))
2684 : return false;
2685 : }
2686 :
2687 : } else {
2688 :
2689 1498 : strlcpy(month, instr, 4);
2690 :
2691 1498 : if (!is_monthname(month))
2692 : return false;
2693 :
2694 10 : instr += 3;
2695 :
2696 10 : if (!isdigit((unsigned char) *instr))
2697 : return false;
2698 :
2699 10 : instr++;
2700 10 : if (!isdigit((unsigned char) *instr))
2701 : return false;
2702 :
2703 10 : instr++;
2704 10 : if (*instr) {
2705 10 : if (!isdigit((unsigned char) *instr))
2706 : return false;
2707 :
2708 10 : instr++;
2709 10 : if (!isdigit((unsigned char) *instr))
2710 : return false;
2711 : }
2712 : }
2713 :
2714 : return true;
2715 :
2716 : }
2717 :
2718 : static bool
2719 540 : is_ampm(const char *datestr)
2720 : {
2721 540 : if (strcasecmp(datestr, "am") == 0)
2722 : return true;
2723 :
2724 540 : if (strcasecmp(datestr, "pm") == 0)
2725 : return true;
2726 :
2727 0 : return false;
2728 : }
2729 :
2730 : static bool
2731 5918 : is_alphabetic(const char *datestr)
2732 : {
2733 : const char *s;
2734 :
2735 8668 : for (s = datestr; *s; s++) {
2736 7778 : if (!isalpha((unsigned char) *s))
2737 : return false;
2738 : }
2739 : return true;
2740 : }
2741 :
2742 : static bool
2743 5028 : is_numeric(const char *datestr)
2744 : {
2745 : const char *s;
2746 :
2747 18714 : for (s = datestr; *s; s++) {
2748 16934 : if (!isdigit((unsigned char) *s))
2749 : return false;
2750 : }
2751 : return true;
2752 : }
2753 :
2754 : static bool
2755 2028 : is_timeformat(const char *datestr)
2756 : {
2757 : const char *s;
2758 :
2759 21578 : for (s = datestr; *s; s++) {
2760 20090 : if (!isdigit((unsigned char) *s) && *s != ':' && *s != '.')
2761 : break;
2762 : }
2763 2028 : if (*s)
2764 540 : return is_ampm(s);
2765 :
2766 : return true;
2767 : }
2768 :
2769 : static int
2770 : store_year(int year, struct tds_time *t)
2771 : {
2772 :
2773 2120 : if (year < 0)
2774 : return 0;
2775 :
2776 2120 : if (year < 100) {
2777 10 : if (year > 49)
2778 0 : t->tm_year = year;
2779 : else
2780 10 : t->tm_year = 100 + year;
2781 : return (1);
2782 : }
2783 :
2784 2110 : if (year < 1753)
2785 : return (0);
2786 :
2787 2110 : if (year <= 9999) {
2788 2110 : t->tm_year = year - 1900;
2789 : return (1);
2790 : }
2791 :
2792 : return (0);
2793 :
2794 : }
2795 :
2796 : static int
2797 : store_mday(const char *datestr, struct tds_time *t)
2798 : {
2799 880 : int mday = atoi(datestr);
2800 :
2801 880 : if (mday > 0 && mday < 32) {
2802 880 : t->tm_mday = mday;
2803 : return 1;
2804 : }
2805 : return 0;
2806 : }
2807 :
2808 : static int
2809 1210 : store_numeric_date(const char *datestr, struct tds_time *t)
2810 : {
2811 1210 : int TDS_MONTH = 0;
2812 1210 : int TDS_DAY = 0;
2813 1210 : int TDS_YEAR = 0;
2814 :
2815 : int state;
2816 1210 : char last_char = 0;
2817 : const char *s;
2818 1210 : int month = 0, year = 0, mday = 0;
2819 :
2820 : /* Its YYYY-MM-DD format */
2821 :
2822 1210 : if (strlen(datestr) == 10 && *(datestr + 4) == '-' && *(datestr + 7) == '-') {
2823 :
2824 : TDS_YEAR = 0;
2825 : TDS_MONTH = 1;
2826 : TDS_DAY = 2;
2827 : state = TDS_YEAR;
2828 :
2829 : }
2830 : /* else we assume MDY */
2831 : else {
2832 0 : TDS_MONTH = 0;
2833 0 : TDS_DAY = 1;
2834 0 : TDS_YEAR = 2;
2835 0 : state = TDS_MONTH;
2836 : }
2837 13310 : for (s = datestr; *s; s++) {
2838 12100 : if (!isdigit((unsigned char) *s) && isdigit((unsigned char) last_char)) {
2839 2420 : state++;
2840 : } else {
2841 9680 : if (state == TDS_MONTH)
2842 2420 : month = (month * 10) + (*s - '0');
2843 9680 : if (state == TDS_DAY)
2844 2420 : mday = (mday * 10) + (*s - '0');
2845 9680 : if (state == TDS_YEAR)
2846 4840 : year = (year * 10) + (*s - '0');
2847 : }
2848 12100 : last_char = *s;
2849 : }
2850 :
2851 1210 : if (month > 0 && month < 13)
2852 1210 : t->tm_mon = month - 1;
2853 : else
2854 : return 0;
2855 1210 : if (mday > 0 && mday < 32)
2856 1210 : t->tm_mday = mday;
2857 : else
2858 : return 0;
2859 :
2860 1210 : return store_year(year, t);
2861 :
2862 : }
2863 :
2864 : static int
2865 10 : store_dd_mon_yyy_date(char *datestr, struct tds_time *t)
2866 : {
2867 :
2868 : char dd[3];
2869 : int mday;
2870 : char mon[4];
2871 : int year;
2872 :
2873 10 : tdsdump_log(TDS_DBG_INFO1, "store_dd_mon_yyy_date: %s\n", datestr);
2874 10 : strlcpy(dd, datestr, 3);
2875 10 : mday = atoi(dd);
2876 :
2877 10 : if (mday > 0 && mday < 32)
2878 10 : t->tm_mday = mday;
2879 : else
2880 : return 0;
2881 :
2882 10 : if (datestr[2] == '-') {
2883 0 : strlcpy(mon, &datestr[3], 4);
2884 :
2885 0 : if (store_monthname(mon, t) < 0) {
2886 0 : tdsdump_log(TDS_DBG_INFO1, "store_dd_mon_yyy_date: store_monthname failed\n");
2887 : return 0;
2888 : }
2889 :
2890 0 : year = atoi(&datestr[7]);
2891 0 : tdsdump_log(TDS_DBG_INFO1, "store_dd_mon_yyy_date: year %d\n", year);
2892 :
2893 0 : return store_year(year, t);
2894 : } else {
2895 10 : strlcpy(mon, &datestr[2], 4);
2896 :
2897 10 : if (store_monthname(mon, t) < 0) {
2898 0 : tdsdump_log(TDS_DBG_INFO1, "store_dd_mon_yyy_date: store_monthname failed\n");
2899 : return 0;
2900 : }
2901 :
2902 20 : year = atoi(&datestr[5]);
2903 10 : tdsdump_log(TDS_DBG_INFO1, "store_dd_mon_yyy_date: year %d\n", year);
2904 :
2905 10 : return store_year(year, t);
2906 : }
2907 :
2908 : }
2909 :
2910 : /**
2911 : * Test if a string is a month name and store correct month number
2912 : * @return month number (0-11) or -1 if not match
2913 : * @param datestr string to check
2914 : * @param t where to store month (if NULL no store is done)
2915 : */
2916 : static int
2917 2398 : store_monthname(const char *datestr, struct tds_time *t)
2918 : {
2919 : int ret;
2920 :
2921 2398 : tdsdump_log(TDS_DBG_INFO1, "store_monthname: %ld %s\n", (long) strlen(datestr), datestr);
2922 2398 : if (strlen(datestr) == 3) {
2923 2368 : if (strcasecmp(datestr, "jan") == 0)
2924 : ret = 0;
2925 2218 : else if (strcasecmp(datestr, "feb") == 0)
2926 : ret = 1;
2927 2218 : else if (strcasecmp(datestr, "mar") == 0)
2928 : ret = 2;
2929 2218 : else if (strcasecmp(datestr, "apr") == 0)
2930 : ret = 3;
2931 2038 : else if (strcasecmp(datestr, "may") == 0)
2932 : ret = 4;
2933 2028 : else if (strcasecmp(datestr, "jun") == 0)
2934 : ret = 5;
2935 2028 : else if (strcasecmp(datestr, "jul") == 0)
2936 : ret = 6;
2937 2028 : else if (strcasecmp(datestr, "aug") == 0)
2938 : ret = 7;
2939 2028 : else if (strcasecmp(datestr, "sep") == 0)
2940 : ret = 8;
2941 2028 : else if (strcasecmp(datestr, "oct") == 0)
2942 : ret = 9;
2943 2028 : else if (strcasecmp(datestr, "nov") == 0)
2944 : ret = 10;
2945 2028 : else if (strcasecmp(datestr, "dec") == 0)
2946 : ret = 11;
2947 : else
2948 : return -1;
2949 : } else {
2950 30 : if (strcasecmp(datestr, "january") == 0)
2951 : ret = 0;
2952 20 : else if (strcasecmp(datestr, "february") == 0)
2953 : ret = 1;
2954 20 : else if (strcasecmp(datestr, "march") == 0)
2955 : ret = 2;
2956 10 : else if (strcasecmp(datestr, "april") == 0)
2957 : ret = 3;
2958 10 : else if (strcasecmp(datestr, "june") == 0)
2959 : ret = 5;
2960 10 : else if (strcasecmp(datestr, "july") == 0)
2961 : ret = 6;
2962 10 : else if (strcasecmp(datestr, "august") == 0)
2963 : ret = 7;
2964 10 : else if (strcasecmp(datestr, "september") == 0)
2965 : ret = 8;
2966 10 : else if (strcasecmp(datestr, "october") == 0)
2967 : ret = 9;
2968 10 : else if (strcasecmp(datestr, "november") == 0)
2969 : ret = 10;
2970 10 : else if (strcasecmp(datestr, "december") == 0)
2971 : ret = 11;
2972 : else
2973 : return -1;
2974 : }
2975 900 : if (t)
2976 890 : t->tm_mon = ret;
2977 : return ret;
2978 : }
2979 :
2980 : static int
2981 20 : store_yymmdd_date(const char *datestr, struct tds_time *t)
2982 : {
2983 20 : int month = 0, year = 0, mday = 0;
2984 :
2985 : int wholedate;
2986 :
2987 20 : wholedate = atoi(datestr);
2988 :
2989 20 : year = wholedate / 10000;
2990 20 : month = (wholedate - (year * 10000)) / 100;
2991 20 : mday = (wholedate - (year * 10000) - (month * 100));
2992 :
2993 20 : if (month > 0 && month < 13)
2994 20 : t->tm_mon = month - 1;
2995 : else
2996 : return 0;
2997 20 : if (mday > 0 && mday < 32)
2998 20 : t->tm_mday = mday;
2999 : else
3000 : return 0;
3001 :
3002 20 : return (store_year(year, t));
3003 :
3004 : }
3005 :
3006 : static int
3007 2028 : store_time(const char *datestr, struct tds_time *t)
3008 : {
3009 : enum
3010 : { TDS_HOURS,
3011 : TDS_MINUTES,
3012 : TDS_SECONDS,
3013 : TDS_FRACTIONS
3014 : };
3015 :
3016 2028 : int state = TDS_HOURS;
3017 2028 : char last_sep = '\0';
3018 : const char *s;
3019 2028 : unsigned int hours = 0, minutes = 0, seconds = 0, nanosecs = 0;
3020 2028 : int ret = 1;
3021 2028 : unsigned ns_div = 1;
3022 :
3023 21578 : for (s = datestr; *s && strchr("apmAPM", (int) *s) == NULL; s++) {
3024 19550 : if (*s == ':' || *s == '.') {
3025 4454 : last_sep = *s;
3026 4454 : state++;
3027 : } else {
3028 15096 : if (*s < '0' || *s > '9')
3029 0 : ret = 0;
3030 15096 : switch (state) {
3031 3516 : case TDS_HOURS:
3032 3516 : hours = (hours * 10u) + (*s - '0');
3033 3516 : break;
3034 4056 : case TDS_MINUTES:
3035 4056 : minutes = (minutes * 10u) + (*s - '0');
3036 4056 : break;
3037 2976 : case TDS_SECONDS:
3038 2976 : seconds = (seconds * 10u) + (*s - '0');
3039 2976 : break;
3040 4548 : case TDS_FRACTIONS:
3041 4548 : if (ns_div < 1000000000u) {
3042 4548 : nanosecs = (nanosecs * 10u) + (*s - '0');
3043 4548 : ns_div *= 10;
3044 : }
3045 : break;
3046 : }
3047 : }
3048 : }
3049 2028 : if (*s) {
3050 540 : if (strcasecmp(s, "am") == 0) {
3051 0 : if (hours == 12)
3052 0 : hours = 0;
3053 :
3054 0 : t->tm_hour = hours;
3055 : }
3056 540 : if (strcasecmp(s, "pm") == 0) {
3057 540 : if (hours == 0)
3058 0 : ret = 0;
3059 540 : if (hours > 0u && hours < 12u)
3060 540 : t->tm_hour = hours + 12;
3061 : else
3062 0 : t->tm_hour = hours;
3063 : }
3064 : } else {
3065 1488 : if (hours < 24u)
3066 1488 : t->tm_hour = hours;
3067 : else
3068 : ret = 0;
3069 : }
3070 2028 : if (minutes < 60u)
3071 2028 : t->tm_min = minutes;
3072 : else
3073 : ret = 0;
3074 2028 : if (seconds < 60u)
3075 2028 : t->tm_sec = seconds;
3076 : else
3077 : ret = 0;
3078 2028 : tdsdump_log(TDS_DBG_FUNC, "store_time() nanosecs = %d\n", nanosecs);
3079 2028 : if (nanosecs) {
3080 720 : if (nanosecs < ns_div && last_sep == '.')
3081 720 : t->tm_ns = nanosecs * (1000000000u / ns_div);
3082 0 : else if (nanosecs < 1000u)
3083 0 : t->tm_ns = nanosecs * 1000000u;
3084 : else
3085 : ret = 0;
3086 : }
3087 :
3088 2028 : return (ret);
3089 : }
3090 :
3091 : static int
3092 0 : store_hour(const char *hour, const char *ampm, struct tds_time *t)
3093 : {
3094 0 : int ret = 1;
3095 : int hours;
3096 :
3097 0 : hours = atoi(hour);
3098 :
3099 0 : if (hours >= 0 && hours < 24) {
3100 0 : if (strcasecmp(ampm, "am") == 0) {
3101 0 : if (hours == 12)
3102 0 : hours = 0;
3103 :
3104 0 : t->tm_hour = hours;
3105 : }
3106 0 : if (strcasecmp(ampm, "pm") == 0) {
3107 0 : if (hours == 0)
3108 0 : ret = 0;
3109 0 : if (hours > 0 && hours < 12)
3110 0 : t->tm_hour = hours + 12;
3111 : else
3112 0 : t->tm_hour = hours;
3113 : }
3114 : }
3115 0 : return ret;
3116 : }
3117 :
3118 : /**
3119 : * Get same type but nullable
3120 : * @param srctype type requires
3121 : * @return nullable type
3122 : */
3123 : TDS_SERVER_TYPE
3124 86 : tds_get_null_type(TDS_SERVER_TYPE srctype)
3125 : {
3126 :
3127 86 : switch (srctype) {
3128 : case SYBCHAR:
3129 : return SYBVARCHAR;
3130 : break;
3131 32 : case SYBINT1:
3132 : case SYBSINT1:
3133 : case SYBUINT1:
3134 : case SYBINT2:
3135 : case SYBINT4:
3136 : case SYBINT8:
3137 : /* TODO sure ?? */
3138 : case SYBUINT2:
3139 : case SYBUINT4:
3140 : case SYBUINT8:
3141 32 : return SYBINTN;
3142 : break;
3143 0 : case SYBREAL:
3144 : case SYBFLT8:
3145 0 : return SYBFLTN;
3146 : break;
3147 0 : case SYBDATETIME:
3148 : case SYBDATETIME4:
3149 0 : return SYBDATETIMN;
3150 : break;
3151 4 : case SYBBIT:
3152 4 : return SYBBITN;
3153 : break;
3154 0 : case SYBMONEY:
3155 : case SYBMONEY4:
3156 0 : return SYBMONEYN;
3157 : break;
3158 0 : case SYBTIME:
3159 0 : return SYBTIMEN;
3160 : break;
3161 0 : case SYBDATE:
3162 0 : return SYBDATEN;
3163 : break;
3164 : default:
3165 : break;
3166 : }
3167 30 : return srctype;
3168 : }
3169 :
3170 : static void
3171 : two_digit(char *out, int num)
3172 : {
3173 1038 : if (num < 1)
3174 : num = 1;
3175 1038 : if (num > 31)
3176 0 : num = 31;
3177 1654 : tds02dfast(out, num);
3178 1654 : if (out[0] == '0')
3179 894 : out[0] = ' ';
3180 : }
3181 :
3182 : static size_t
3183 5524 : tds_strftime_tm(char *buf, size_t maxsize, const char *format, const struct tm *ptm, TDS_INT decimicrosecond, int prec)
3184 : {
3185 : struct tm tm;
3186 :
3187 : size_t length;
3188 : char *our_format;
3189 : char *pz;
3190 5524 : bool z_found = false;
3191 5524 : size_t z_opt_len = 2;
3192 :
3193 5524 : assert(buf);
3194 5524 : assert(format);
3195 5524 : assert(ptm);
3196 5524 : tm = *ptm;
3197 :
3198 : /* TDS date formatting does not support time zones */
3199 : #ifdef HAVE_STRUCT_TM_TM_ZONE
3200 5524 : tm.tm_zone = NULL;
3201 : #elif defined(HAVE_STRUCT_TM___TM_ZONE)
3202 : tm.__tm_zone = NULL;
3203 : #endif
3204 :
3205 5524 : if (prec < 0 || prec > 7)
3206 0 : prec = 3;
3207 :
3208 : /* more characters are required because we replace %z with up to 7 digits */
3209 5524 : our_format = tds_new(char, strlen(format) + (1 + 5 + 1));
3210 5524 : if (!our_format)
3211 : return 0;
3212 :
3213 5524 : strcpy(our_format, format);
3214 :
3215 63808 : for (pz = our_format; *pz; ) {
3216 52760 : if (*pz++ != '%')
3217 23262 : continue;
3218 :
3219 29498 : switch (*pz) {
3220 10 : case 0:
3221 10 : *pz++ = '%';
3222 10 : *pz = 0;
3223 10 : continue;
3224 : case '%':
3225 : /* escaped, do not treat as format on next iteration */
3226 : break;
3227 1038 : case 'e':
3228 : /* not portable: day of month, single digit preceded by a blank */
3229 : /* not supported on old Windows versions */
3230 1038 : two_digit(pz - 1, tm.tm_mday);
3231 : break;
3232 616 : case 'l':
3233 : /* not portable: 12-hour, single digit preceded by a blank */
3234 : /* not supported on: SCO Unix, AIX, HP-UX, Windows
3235 : * supported on: *BSD, MacOS, Linux, Solaris */
3236 616 : two_digit(pz - 1, (tm.tm_hour + 11u) % 12u + 1);
3237 : break;
3238 410 : case '1':
3239 : case '2':
3240 : case '3':
3241 : case '4':
3242 : case '5':
3243 : case '6':
3244 : case '7':
3245 : case '8':
3246 : case '9':
3247 410 : if (pz[1] != 'z')
3248 : break;
3249 410 : prec = pz[0] - '0';
3250 410 : z_opt_len = 3;
3251 3460 : case 'z':
3252 : /*
3253 : * Look for "%z" in the format string. If found, replace it with decimicrosecond.
3254 : * For example, if milliseconds is 124, the format string
3255 : * "%b %d %Y %H:%M:%S.%z" would become
3256 : * "%b %d %Y %H:%M:%S.124".
3257 : */
3258 3460 : if (z_found)
3259 : break;
3260 3460 : z_found = true;
3261 :
3262 3460 : --pz;
3263 6604 : if (prec || pz <= our_format || pz[-1] != '.') {
3264 : char buf[10];
3265 : /* decimicrosecond should be a number from 0 to 9,999,999
3266 : * (regardless of prec, which is just the requested
3267 : * display precision). In case we are erroneously passed a
3268 : * sign, discard the sign. If erroneously given a number
3269 : * too big, discard leading digits.
3270 : */
3271 3144 : memset(buf, '0', sizeof(buf));
3272 3144 : tds_u32toa_fast_right(buf, decimicrosecond & 0x7fffffff);
3273 3144 : memcpy(pz, buf + 3, prec);
3274 3144 : strcpy(pz + prec, format + (pz - our_format) + z_opt_len);
3275 3144 : pz += prec;
3276 : } else {
3277 316 : strcpy(pz - 1, format + (pz - our_format) + 2);
3278 316 : pz--;
3279 : }
3280 3460 : continue;
3281 : }
3282 26028 : ++pz;
3283 : }
3284 :
3285 5524 : length = strftime(buf, maxsize, our_format, &tm);
3286 :
3287 5524 : free(our_format);
3288 :
3289 5524 : return length;
3290 : }
3291 :
3292 : /**
3293 : * format a date string according to an "extended" strftime(3) formatting definition.
3294 : * @param buf output buffer
3295 : * @param maxsize size of buffer in bytes (space include terminator)
3296 : * @param format format string passed to strftime(3), except that %z represents fraction of seconds.
3297 : * @param dr date to convert
3298 : * @param prec second fraction precision (0-7).
3299 : * @return length of string returned, 0 for error
3300 : */
3301 : size_t
3302 3794 : tds_strftime(char *buf, size_t maxsize, const char *format, const TDSDATEREC *dr, int prec)
3303 : {
3304 3794 : struct tm tm = { 0 };
3305 :
3306 3794 : tm.tm_sec = dr->second;
3307 3794 : tm.tm_min = dr->minute;
3308 3794 : tm.tm_hour = dr->hour;
3309 3794 : tm.tm_mday = dr->day;
3310 3794 : tm.tm_mon = dr->month;
3311 3794 : tm.tm_year = dr->year - 1900;
3312 3794 : tm.tm_wday = dr->weekday;
3313 3794 : tm.tm_yday = dr->dayofyear;
3314 3794 : return tds_strftime_tm(buf, maxsize, format, &tm, dr->decimicrosecond, prec);
3315 : }
3316 :
3317 : size_t
3318 1730 : tds_strftime_maxsize(const char *format, int prec)
3319 : {
3320 : char buf[1000];
3321 1730 : struct tm tm = { 0 };
3322 :
3323 : /* The longest possible time.
3324 : * "Wednesday" for %A, "September" for %B.
3325 : * If they use other locale specific fields... Might get wrong answer.
3326 : * The consequences of an error here could be display truncation in
3327 : * ODBC clients which choose to depend on this; should not lead to
3328 : * buffer overflows.
3329 : */
3330 1730 : tm.tm_sec = 59;
3331 1730 : tm.tm_min = 59;
3332 1730 : tm.tm_hour = 19;
3333 1730 : tm.tm_mday = 24;
3334 1730 : tm.tm_mon = 9 - 1;
3335 1730 : tm.tm_year = 2025 - 1900;
3336 1730 : tm.tm_wday = 3;
3337 1730 : tm.tm_yday = 266;
3338 :
3339 1730 : return tds_strftime_tm(buf, sizeof buf, format, &tm, 1234567, prec);
3340 : }
3341 :
3342 : #if 0
3343 : static TDS_UINT
3344 : utf16len(const utf16_t *s)
3345 : {
3346 : const utf16_t *p = s;
3347 :
3348 : while (*p++)
3349 : continue;
3350 : return p - s;
3351 : }
3352 : #endif
3353 :
3354 : #include "tds_willconvert.h"
3355 :
3356 : /**
3357 : * Test if a conversion is possible
3358 : * @param srctype source type
3359 : * @param desttype destination type
3360 : * @return 0 if not convertible
3361 : */
3362 : unsigned char
3363 1613262 : tds_willconvert(int srctype, int desttype)
3364 : {
3365 : TDS_TINYINT cat_from, cat_to;
3366 : TDS_UINT yn;
3367 :
3368 1613262 : tdsdump_log(TDS_DBG_FUNC, "tds_willconvert(%d, %d)\n", srctype, desttype);
3369 :
3370 : /* they must be from 0 to 255 */
3371 1613262 : if (((srctype|desttype) & ~0xff) != 0)
3372 : return 0;
3373 :
3374 1613262 : cat_from = type2category[srctype];
3375 1613262 : cat_to = type2category[desttype];
3376 1613262 : yn = category_conversion[cat_from];
3377 :
3378 1613262 : yn = (yn >> cat_to) & 1;
3379 :
3380 1613262 : tdsdump_log(TDS_DBG_FUNC, "tds_willconvert(%d, %d) returns %s\n",
3381 : srctype, desttype, yn? "yes":"no");
3382 1613262 : return yn;
3383 : }
3384 :
3385 : #if 0
3386 : select day(d) as day, datepart(dw, d) as weekday, datepart(week, d) as week, d as 'date' from #t order by d
3387 : day weekday week date
3388 : ----------- ----------- ----------- ----------
3389 : 1 5 1 2009-01-01 Thursday
3390 : 2 6 1 2009-01-02 Friday
3391 : 3 7 1 2009-01-03 Saturday
3392 : 4 1 2 2009-01-04 Sunday
3393 : 5 2 2 2009-01-05
3394 : 6 3 2 2009-01-06
3395 : 7 4 2 2009-01-07
3396 : 8 5 2 2009-01-08
3397 : 9 6 2 2009-01-09
3398 : 10 7 2 2009-01-10
3399 : 11 1 3 2009-01-11
3400 : 12 2 3 2009-01-12
3401 : 13 3 3 2009-01-13
3402 : 14 4 3 2009-01-14
3403 : 15 5 3 2009-01-15
3404 : 16 6 3 2009-01-16
3405 : 17 7 3 2009-01-17
3406 : 18 1 4 2009-01-18
3407 : 19 2 4 2009-01-19
3408 : 20 3 4 2009-01-20
3409 : 21 4 4 2009-01-21
3410 : 22 5 4 2009-01-22
3411 : 23 6 4 2009-01-23
3412 : 24 7 4 2009-01-24
3413 : 25 1 5 2009-01-25
3414 : 26 2 5 2009-01-26
3415 : 27 3 5 2009-01-27
3416 : 28 4 5 2009-01-28
3417 : 29 5 5 2009-01-29
3418 : 30 6 5 2009-01-30
3419 : 31 7 5 2009-01-31
3420 : #endif
3421 : /**
3422 : * Convert from db date format to a structured date format
3423 : * @param datetype source date type. SYBDATETIME or SYBDATETIME4
3424 : * @param di source date
3425 : * @param dr destination date
3426 : * @return TDS_FAIL or TDS_SUCCESS
3427 : */
3428 : TDSRET
3429 6544 : tds_datecrack(TDS_INT datetype, const void *di, TDSDATEREC * dr)
3430 : {
3431 : int dt_days;
3432 : unsigned int dt_time;
3433 :
3434 6544 : int years, months, days, ydays, wday, hours, mins, secs, dms, tzone = 0;
3435 : int l, n, i, j;
3436 :
3437 6544 : memset(dr, 0, sizeof(*dr));
3438 :
3439 6544 : if (datetype == SYBMSDATE || datetype == SYBMSTIME
3440 6544 : || datetype == SYBMSDATETIME2 || datetype == SYBMSDATETIMEOFFSET) {
3441 4786 : const TDS_DATETIMEALL *dta = (const TDS_DATETIMEALL *) di;
3442 4786 : dt_days = (datetype == SYBMSTIME) ? 0 : dta->date;
3443 4786 : if (datetype == SYBMSDATE) {
3444 : dms = 0;
3445 : secs = 0;
3446 : dt_time = 0;
3447 : } else {
3448 4000 : dms = dta->time % 10000000u;
3449 4000 : dt_time = (unsigned int) (dta->time / 10000000u);
3450 4000 : secs = dt_time % 60;
3451 4000 : dt_time = dt_time / 60;
3452 : }
3453 4786 : if (datetype == SYBMSDATETIMEOFFSET) {
3454 126 : --dt_days;
3455 126 : dt_time = dt_time + 1440 + dta->offset;
3456 126 : dt_days += dt_time / 1440;
3457 126 : dt_time %= 1440;
3458 126 : tzone = dta->offset;
3459 : }
3460 1758 : } else if (datetype == SYBDATETIME) {
3461 1372 : const TDS_DATETIME *dt = (const TDS_DATETIME *) di;
3462 1372 : dt_time = dt->dttime;
3463 1372 : dms = ((dt_time % 300) * 1000 + 150) / 300 * 10000u;
3464 1372 : dt_time = dt_time / 300;
3465 1372 : secs = dt_time % 60;
3466 1372 : dt_time = dt_time / 60;
3467 1372 : dt_days = dt->dtdays;
3468 386 : } else if (datetype == SYBDATETIME4) {
3469 140 : const TDS_DATETIME4 *dt4 = (const TDS_DATETIME4 *) di;
3470 140 : secs = 0;
3471 140 : dms = 0;
3472 140 : dt_days = dt4->days;
3473 140 : dt_time = dt4->minutes;
3474 246 : } else if (datetype == SYBDATE) {
3475 92 : dt_days = *((const TDS_DATE *) di);
3476 92 : dms = 0;
3477 92 : secs = 0;
3478 92 : dt_time = 0;
3479 154 : } else if (datetype == SYBTIME) {
3480 94 : dt_time = *((const TDS_TIME *) di);
3481 94 : dms = ((dt_time % 300) * 1000 + 150) / 300 * 10000u;
3482 94 : dt_time = dt_time / 300;
3483 94 : secs = dt_time % 60;
3484 94 : dt_time = dt_time / 60;
3485 94 : dt_days = 0;
3486 60 : } else if (datetype == SYB5BIGTIME) {
3487 30 : TDS_UINT8 bigtime = *((const TDS_BIGTIME *) di);
3488 30 : dt_days = 0;
3489 30 : dms = bigtime % 1000000u * 10u;
3490 30 : dt_time = (bigtime / 1000000u) % 86400u;
3491 30 : secs = dt_time % 60;
3492 30 : dt_time = dt_time / 60u;
3493 30 : } else if (datetype == SYB5BIGDATETIME) {
3494 30 : TDS_UINT8 bigdatetime = *((const TDS_BIGDATETIME*) di);
3495 30 : dms = bigdatetime % 1000000u * 10u;
3496 30 : bigdatetime /= 1000000u;
3497 30 : secs = bigdatetime % 60u;
3498 30 : bigdatetime /= 60u;
3499 30 : dt_time = bigdatetime % (24u*60u);
3500 30 : dt_days = (int) (bigdatetime / (24u*60u) - BIGDATETIME_BIAS);
3501 : } else {
3502 : return TDS_FAIL;
3503 : }
3504 :
3505 : /*
3506 : * -53690 is minimun (1753-1-1) (Gregorian calendar start in 1732)
3507 : * 2958463 is maximun (9999-12-31)
3508 : */
3509 6544 : l = dt_days + (146038 + 146097*4);
3510 6544 : wday = (l + 4) % 7;
3511 6544 : n = (4 * l) / 146097; /* n century */
3512 6544 : l = l - (146097 * n + 3) / 4; /* days from xx00-02-28 (y-m-d) */
3513 6544 : i = (4000 * (l + 1)) / 1461001; /* years from xx00-02-28 */
3514 6544 : l = l - (1461 * i) / 4; /* year days from xx00-02-28 */
3515 6544 : ydays = l >= 306 ? l - 305 : l + 60;
3516 6544 : l += 31;
3517 6544 : j = (80 * l) / 2447;
3518 6544 : days = l - (2447 * j) / 80;
3519 6544 : l = j / 11;
3520 6544 : months = j + 1 - 12 * l;
3521 6544 : years = 100 * (n - 1) + i + l;
3522 6544 : if (l == 0 && (years & 3) == 0 && (years % 100 != 0 || years % 400 == 0))
3523 582 : ++ydays;
3524 :
3525 6544 : hours = dt_time / 60;
3526 6544 : mins = dt_time % 60;
3527 :
3528 6544 : dr->year = years;
3529 6544 : dr->month = months;
3530 6544 : dr->quarter = months / 3;
3531 6544 : dr->day = days;
3532 6544 : dr->dayofyear = ydays;
3533 6544 : dr->weekday = wday;
3534 6544 : dr->hour = hours;
3535 6544 : dr->minute = mins;
3536 6544 : dr->second = secs;
3537 6544 : dr->decimicrosecond = dms;
3538 6544 : dr->timezone = tzone;
3539 6544 : return TDS_SUCCESS;
3540 : }
3541 :
3542 : /**
3543 : * \brief convert a number in string to TDS_INT
3544 : *
3545 : * \return TDS_CONVERT_* or failure code on error
3546 : * \remarks Sybase's char->int conversion tolerates embedded blanks,
3547 : * such that "convert( int, ' - 13 ' )" works.
3548 : * If we find blanks, we copy the string to a temporary buffer,
3549 : * skipping the blanks.
3550 : * We return the results of atoi() with a clean string.
3551 : *
3552 : * n.b. it is possible to embed all sorts of non-printable characters, but we
3553 : * only check for spaces. at this time, no one on the project has tested anything else.
3554 : */
3555 : static TDS_INT
3556 603112 : string_to_int(const char *buf, const char *pend, TDS_INT * res)
3557 : {
3558 : bool negative;
3559 : unsigned int num; /* we use unsigned here for best overflow check */
3560 : size_t digits, decimals;
3561 :
3562 603112 : buf = parse_numeric(buf, pend, &negative, &digits, &decimals);
3563 603112 : if (!buf)
3564 : return TDS_CONVERT_SYNTAX;
3565 :
3566 : num = 0;
3567 3767646 : for (; digits; --digits, ++buf) {
3568 : /* add a digit to number and check for overflow */
3569 : /* NOTE I didn't forget a digit, I check overflow before multiply to prevent overflow */
3570 3988976 : if (num > 214748364u)
3571 : return TDS_CONVERT_OVERFLOW;
3572 3767646 : num = num * 10u + (*buf - '0');
3573 : }
3574 :
3575 : /* check for overflow and convert unsigned to signed */
3576 381192 : if (negative) {
3577 173226 : if (num > 2147483648u)
3578 : return TDS_CONVERT_OVERFLOW;
3579 171036 : *res = 0 - num;
3580 : } else {
3581 207966 : if (num >= 2147483648u)
3582 : return TDS_CONVERT_OVERFLOW;
3583 204336 : *res = num;
3584 : }
3585 :
3586 : return sizeof(TDS_INT);
3587 : }
3588 :
3589 : /**
3590 : * \brief convert a number in string to TDS_INT8
3591 : *
3592 : * \return TDS_CONVERT_* or failure code on error
3593 : */
3594 : static TDS_INT /* copied from string_ti_int and modified */
3595 476292 : parse_int8(const char *buf, const char *pend, TDS_UINT8 * res, bool * p_negative)
3596 : {
3597 : TDS_UINT8 num;
3598 : size_t digits, decimals;
3599 :
3600 476292 : buf = parse_numeric(buf, pend, p_negative, &digits, &decimals);
3601 476292 : if (!buf)
3602 : return TDS_CONVERT_SYNTAX;
3603 :
3604 : num = 0;
3605 4363262 : for (; digits; --digits, ++buf) {
3606 : /* add a digit to number and check for overflow */
3607 4375242 : TDS_UINT8 prev = num;
3608 4375242 : if (num > (UINT64_C(1) << 63) / 5u)
3609 : return TDS_CONVERT_OVERFLOW;
3610 4367802 : num = num * 10u + (*buf - '0');
3611 4367802 : if (num < prev)
3612 : return TDS_CONVERT_OVERFLOW;
3613 : }
3614 :
3615 463942 : *res = num;
3616 463942 : return sizeof(TDS_INT8);
3617 : }
3618 :
3619 : /**
3620 : * \brief convert a number in string to TDS_INT8
3621 : *
3622 : * \return TDS_CONVERT_* or failure code on error
3623 : */
3624 : static TDS_INT /* copied from string_ti_int and modified */
3625 374702 : string_to_int8(const char *buf, const char *pend, TDS_INT8 * res)
3626 : {
3627 : TDS_UINT8 num;
3628 : TDS_INT parse_res;
3629 : bool negative;
3630 :
3631 374702 : parse_res = parse_int8(buf, pend, &num, &negative);
3632 374702 : if (parse_res < 0)
3633 : return parse_res;
3634 :
3635 : /* check for overflow and convert unsigned to signed */
3636 366472 : if (negative) {
3637 168400 : if (num > UINT64_C(1) << 63)
3638 : return TDS_CONVERT_OVERFLOW;
3639 157150 : *res = 0 - num;
3640 : } else {
3641 198072 : if (num >= UINT64_C(1) << 63)
3642 : return TDS_CONVERT_OVERFLOW;
3643 185372 : *res = num;
3644 : }
3645 : return sizeof(TDS_INT8);
3646 : }
3647 :
3648 : /**
3649 : * \brief convert a number in string to TDS_UINT8
3650 : *
3651 : * \return TDS_CONVERT_* or failure code on error
3652 : */
3653 : static TDS_INT /* copied from string_to_int8 and modified */
3654 101590 : string_to_uint8(const char *buf, const char *pend, TDS_UINT8 * res)
3655 : {
3656 : TDS_UINT8 num;
3657 : TDS_INT parse_res;
3658 : bool negative;
3659 :
3660 101590 : parse_res = parse_int8(buf, pend, &num, &negative);
3661 101590 : if (parse_res < 0)
3662 : return parse_res;
3663 :
3664 : /* check for overflow */
3665 97470 : if (negative && num)
3666 : return TDS_CONVERT_OVERFLOW;
3667 :
3668 52470 : *res = num;
3669 52470 : return sizeof(TDS_UINT8);
3670 : }
3671 :
3672 : /**
3673 : * Parse a string for numbers.
3674 : *
3675 : * Syntax can be something like " *[+-] *[0-9]*\.[0-9]* *".
3676 : *
3677 : * The function ignore all spaces. It strips leading zeroes which could
3678 : * possibly lead to overflow.
3679 : * The function returns a pointer to the integer part followed by *p_digits
3680 : * digits followed by a dot followed by *p_decimals digits (dot and
3681 : * fractional digits are optional, in this case *p_decimals is 0).
3682 : *
3683 : * @param buf start of string
3684 : * @param pend pointer to string end
3685 : * @param p_negative store if number is negative
3686 : * @param p_digits store number of integer digits
3687 : * @param p_decimals store number of fractional digits
3688 : * @return pointer to first not zero digit. If NULL this indicate a syntax
3689 : * error.
3690 : */
3691 : static const char *
3692 1399894 : parse_numeric(const char *buf, const char *pend, bool *p_negative, size_t *p_digits, size_t *p_decimals)
3693 : {
3694 : enum { blank = ' ' };
3695 : #define SKIP_IF(cond) while (p != pend && (cond)) ++p;
3696 : const char *p, *start;
3697 1399894 : bool negative = false;
3698 :
3699 1399894 : *p_decimals = 0;
3700 1399894 : p = buf;
3701 :
3702 : /* ignore leading spaces */
3703 1399894 : SKIP_IF(*p == blank);
3704 1399894 : if (p == pend) {
3705 740 : *p_negative = false;
3706 740 : *p_digits = 0;
3707 740 : return p;
3708 : }
3709 :
3710 : /* check for sign */
3711 1399154 : switch (*p) {
3712 644186 : case '-':
3713 644186 : negative = true;
3714 : /* fall thru */
3715 644356 : case '+':
3716 : /* skip spaces between sign and number */
3717 644356 : ++p;
3718 644356 : SKIP_IF(*p == blank);
3719 : break;
3720 : }
3721 1399154 : *p_negative = negative;
3722 :
3723 : /* a digit must be present */
3724 1399154 : if (p == pend)
3725 : return NULL;
3726 :
3727 : /*
3728 : * skip leading zeroes
3729 : * Not skipping them cause numbers like "000000000000" to
3730 : * appear like overflow
3731 : */
3732 10914 : SKIP_IF(*p == '0');
3733 :
3734 : start = p;
3735 12175068 : SKIP_IF(TDS_ISDIGIT(*p));
3736 1398994 : *p_digits = p - start;
3737 :
3738 : /* parse decimal part */
3739 1398994 : if (p != pend && *p == '.') {
3740 3970 : const char *decimals_start = ++p;
3741 3970 : SKIP_IF(TDS_ISDIGIT(*p));
3742 3970 : *p_decimals = p - decimals_start;
3743 : }
3744 :
3745 : /* check for trailing spaces */
3746 586 : SKIP_IF(*p == blank);
3747 1398994 : if (p != pend)
3748 : return NULL;
3749 :
3750 1398154 : return start;
3751 : }
3752 :
3753 : static TDS_INT
3754 189290 : string_to_float(const TDS_CHAR * src, TDS_UINT srclen, int desttype, CONV_RESULT * cr)
3755 : {
3756 : char tmpstr[128];
3757 : char *end;
3758 : double res;
3759 :
3760 : /* ignore leading spaces */
3761 378580 : while (srclen > 0 && src[0] == ' ')
3762 0 : ++src, --srclen;
3763 :
3764 : /* ignore trailing blanks and nulls */
3765 189290 : while (srclen > 0 && (src[srclen - 1] == ' ' || src[srclen - 1] == '\0'))
3766 : --srclen;
3767 :
3768 189290 : if (srclen >= sizeof(tmpstr))
3769 : return TDS_CONVERT_OVERFLOW;
3770 :
3771 189290 : memcpy(tmpstr, src, srclen);
3772 189290 : tmpstr[srclen] = 0;
3773 :
3774 189290 : errno = 0;
3775 189290 : res = strtod(tmpstr, &end);
3776 189290 : if (errno == ERANGE)
3777 : return TDS_CONVERT_OVERFLOW;
3778 189290 : if (end != tmpstr + srclen)
3779 : return TDS_CONVERT_SYNTAX;
3780 :
3781 189290 : if (desttype == SYBREAL) {
3782 : /* FIXME check overflows */
3783 94640 : cr->r = (TDS_REAL)res;
3784 94640 : return sizeof(TDS_REAL);
3785 : }
3786 94650 : cr->f = res;
3787 94650 : return sizeof(TDS_FLOAT);
3788 : }
3789 :
3790 : /** @} */
|