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 23167 : string_to_result(int desttype, const char *s, CONV_RESULT * cr)
177 : {
178 23167 : size_t len = strlen(s);
179 :
180 23167 : if (desttype != TDS_CONVERT_CHAR) {
181 4296 : cr->c = tds_new(TDS_CHAR, len + 1);
182 4296 : test_alloc(cr->c);
183 4296 : memcpy(cr->c, s, len + 1);
184 : } else {
185 18871 : memcpy(cr->cc.c, s, TDS_MIN(len, cr->cc.len));
186 : }
187 23167 : 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 2336 : binary_to_result(int desttype, const void *data, size_t len, CONV_RESULT * cr)
195 : {
196 2336 : if (desttype != TDS_CONVERT_BINARY) {
197 2246 : cr->ib = tds_new(TDS_CHAR, len);
198 2246 : test_alloc(cr->ib);
199 2246 : memcpy(cr->ib, data, len);
200 : } else {
201 90 : memcpy(cr->cb.ib, data, TDS_MIN(len, cr->cb.len));
202 : }
203 2336 : 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 18306 : 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 18306 : switch (desttype) {
238 926 : case TDS_CONVERT_CHAR:
239 926 : cplen = srclen * 2;
240 926 : if ((TDS_UINT)cplen > cr->cc.len)
241 490 : cplen = cr->cc.len;
242 :
243 926 : c = cr->cc.c;
244 803596 : for (s = 0; cplen >= 2; ++s, cplen -= 2) {
245 802670 : *c++ = tds_hex_digits[src[s]>>4];
246 802670 : *c++ = tds_hex_digits[src[s]&0xF];
247 : }
248 926 : if (cplen)
249 240 : *c = tds_hex_digits[src[s]>>4];
250 : return srclen * 2;
251 :
252 480 : 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 480 : cr->c = tds_new(TDS_CHAR, (srclen * 2) + 1);
263 480 : test_alloc(cr->c);
264 :
265 : c = cr->c;
266 :
267 112312 : for (s = 0; s < srclen; s++) {
268 112312 : *c++ = tds_hex_digits[src[s]>>4];
269 112312 : *c++ = tds_hex_digits[src[s]&0xF];
270 : }
271 :
272 480 : *c = '\0';
273 480 : 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 1122 : tds_hex_trim(const TDS_CHAR **p_src, size_t srclen)
315 : {
316 1122 : const TDS_CHAR *src = *p_src;
317 :
318 : /* skip leading spaces and tabs */
319 2344 : while (srclen > 0 && (src[0] == ' ' || src[0] == '\t')) {
320 100 : src++;
321 100 : srclen--;
322 : }
323 :
324 : /* skip leading "0x" or "0X" */
325 1122 : if (srclen >= 2 && src[0] == '0' && (src[1] == 'x' || src[1] == 'X')) {
326 270 : src += 2;
327 270 : srclen -= 2;
328 : }
329 :
330 : /* ignore trailing spaces and tabs */
331 1222 : while (srclen > 0 && (src[srclen - 1] == ' ' || src[srclen - 1] == '\t'))
332 : --srclen;
333 :
334 1122 : *p_src = src;
335 1122 : return srclen;
336 : }
337 :
338 : ptrdiff_t
339 1162 : tds_char2hex(TDS_CHAR *dest, size_t destlen, const TDS_CHAR *src, size_t srclen)
340 : {
341 : size_t i;
342 1162 : unsigned char hex1, c = 0;
343 :
344 : /* if srclen if odd we must add a "0" before ... */
345 1162 : i = 0; /* number where to start converting */
346 1162 : if (srclen & 1) {
347 400 : ++srclen;
348 400 : i = 1;
349 400 : --src;
350 : }
351 622760 : for (; i < srclen; ++i) {
352 622780 : hex1 = (unsigned char) src[i];
353 :
354 622780 : if ('0' <= hex1 && hex1 <= '9')
355 520002 : hex1 &= 0x0f;
356 : else {
357 102778 : hex1 &= 0x20 ^ 0xff; /* mask off 0x20 to ensure upper case */
358 102778 : if ('A' <= hex1 && hex1 <= 'F') {
359 102758 : hex1 -= ('A' - 10);
360 : } else {
361 20 : 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 622760 : tds_extra_assert(hex1 < 0x10);
367 :
368 622760 : if ((i/2u) >= destlen)
369 0 : continue;
370 :
371 622760 : if (i & 1)
372 311570 : dest[i / 2u] = (char) (c | hex1);
373 : else
374 311190 : c = hex1 << 4;
375 : }
376 1142 : return (ptrdiff_t) (srclen / 2u);
377 : }
378 :
379 : static TDS_INT
380 1427301 : 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 1427301 : switch (desttype) {
396 2235 : case TDS_CONVERT_CHAR:
397 2235 : memcpy(cr->cc.c, src, TDS_MIN(srclen, cr->cc.len));
398 2235 : return srclen;
399 :
400 2768 : case CASE_ALL_CHAR:
401 2768 : cr->c = tds_new(TDS_CHAR, srclen + 1);
402 2768 : test_alloc(cr->c);
403 2768 : memcpy(cr->c, src, srclen);
404 2768 : cr->c[srclen] = 0;
405 2768 : 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 102206 : case SYBINT4:
442 102206 : if ((rc = string_to_int(src, src + srclen, &tds_i)) < 0)
443 : return rc;
444 63596 : cr->i = tds_i;
445 63596 : return sizeof(TDS_INT);
446 : break;
447 101464 : case SYBUINT4:
448 101464 : if ((rc = string_to_int8(src, src + srclen, &tds_i8)) < 0)
449 : return rc;
450 89594 : if (!INT_IS_UINT(tds_i8))
451 : return TDS_CONVERT_OVERFLOW;
452 39104 : cr->ui = (TDS_UINT) tds_i8;
453 39104 : 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 2916 : 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 2916 : return string_to_datetime(src, srclen, desttype, cr);
521 : break;
522 107710 : case SYBNUMERIC:
523 : case SYBDECIMAL:
524 107710 : 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 6608 : 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 22564 : 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 27654 : 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 51915 : 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 27382 : num = *src;
647 27382 : 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 18602 : out[0] = digits2[v * 2];
685 18602 : out[1] = digits2[v * 2 + 1];
686 : }
687 :
688 : void
689 180 : tds_02d_fast(char out[2], int v)
690 : {
691 180 : tds02dfast(out, v);
692 180 : }
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 10048 : tds_u32toa_fast_right(char out[10], uint32_t v)
700 : {
701 10048 : char *p = out + 10;
702 :
703 : /* Fill buffer from the end so it comes out in the right order */
704 34954 : while (v >= 100u) {
705 14858 : uint32_t q = v / 100u;
706 14858 : uint32_t r = v % 100u;
707 :
708 14858 : p -= 2;
709 29716 : tds02dfast(p, r);
710 14858 : v = q;
711 : }
712 :
713 10048 : if (v >= 10u) {
714 1256 : p -= 2;
715 1256 : tds02dfast(p, v);
716 8792 : } else if (v > 0u)
717 7958 : *--p = (char) ('0' + v);
718 :
719 10048 : return p - out;
720 : }
721 :
722 : /* Returns number of digits written */
723 : size_t
724 12763 : tds_u32toa_fast(char out[10], uint32_t v)
725 : {
726 : char buf[10];
727 : size_t pad;
728 :
729 : /* Small case optimizations */
730 12763 : if (v < 10u) {
731 3727 : *out = (char) ('0' + v);
732 3727 : return 1;
733 : }
734 9036 : if (v < 100u) {
735 1388 : tds02dfast(out, v);
736 694 : return 2;
737 : }
738 :
739 8342 : pad = tds_u32toa_fast_right(buf, v);
740 :
741 8342 : memcpy(out, buf + pad, 10 - pad);
742 8342 : return 10 - pad;
743 : }
744 :
745 : size_t
746 0 : tds_i32toa_fast(char out[11], int32_t v)
747 : {
748 12727 : size_t sign_length = 0;
749 :
750 12727 : 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 12727 : return tds_u32toa_fast(out, v) + sign_length;
757 : }
758 :
759 : static TDS_INT
760 220781 : tds_convert_int(TDS_INT num, int desttype, CONV_RESULT * cr)
761 : {
762 : TDS_CHAR tmp_str[16];
763 :
764 220781 : switch (desttype) {
765 12727 : case TDS_CONVERT_CHAR:
766 : case CASE_ALL_CHAR:
767 12727 : tmp_str[tds_i32toa_fast(tmp_str, num)] = 0;
768 12727 : 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 22332 : case SYBINT4:
796 22332 : cr->i = num;
797 22332 : 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 62674 : 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 62674 : memcpy(&buf, src, sizeof(buf));
940 : /* INT_IS_INT does not work here due to unsigned/signed conversions */
941 62674 : if (buf <= TDS_INT_MAX)
942 46460 : 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 75208 : 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 75208 : switch (desttype) {
1024 2306 : case TDS_CONVERT_CHAR:
1025 : case CASE_ALL_CHAR:
1026 2306 : if (tds_numeric_to_string(src, u.tmpstr) < 0)
1027 : return TDS_CONVERT_FAIL;
1028 2306 : 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 5672 : case SYBNUMERIC:
1177 : case SYBDECIMAL:
1178 : {
1179 5672 : unsigned char prec = cr->n.precision, scale = cr->n.scale;
1180 :
1181 5672 : cr->n = *src;
1182 5672 : 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 25426 : 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 25426 : switch (desttype) {
1450 1704 : case TDS_CONVERT_CHAR:
1451 : case CASE_ALL_CHAR:
1452 1704 : tds_datecrack(srctype, dta, &when);
1453 1704 : datetime_fmt = tds_ctx->locale->datetime_fmt;
1454 1704 : if (srctype == SYBMSDATE && tds_ctx->locale->date_fmt)
1455 660 : datetime_fmt = tds_ctx->locale->date_fmt;
1456 1704 : if (srctype == SYBMSTIME && tds_ctx->locale->time_fmt)
1457 770 : datetime_fmt = tds_ctx->locale->time_fmt;
1458 1704 : tds_strftime(whole_date_string, sizeof(whole_date_string), datetime_fmt, &when,
1459 1704 : dta->time_prec);
1460 :
1461 1704 : return string_to_result(desttype, whole_date_string, cr);
1462 350 : case SYBDATETIME:
1463 350 : cr->dt.dtdays = dta->date;
1464 350 : 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 1552 : case SYBMSDATETIMEOFFSET:
1473 : case SYBMSDATE:
1474 : case SYBMSTIME:
1475 : case SYBMSDATETIME2:
1476 1552 : 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 8688 : 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 8688 : switch (desttype) {
1521 1062 : case TDS_CONVERT_CHAR:
1522 : case CASE_ALL_CHAR:
1523 1062 : tds_datecrack(SYBDATETIME, dt, &when);
1524 1062 : tds_strftime(whole_date_string, sizeof(whole_date_string), tds_ctx->locale->datetime_fmt, &when, 3);
1525 :
1526 1062 : 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 1206 : case SYBMSDATETIMEOFFSET:
1543 : case SYBMSDATE:
1544 : case SYBMSTIME:
1545 : case SYBMSDATETIME2:
1546 1206 : memset(&cr->dta, 0, sizeof(cr->dta));
1547 1206 : cr->dta.time_prec = precision;
1548 1206 : if (desttype == SYBMSDATETIMEOFFSET)
1549 20 : cr->dta.has_offset = 1;
1550 1206 : if (desttype != SYBMSDATE) {
1551 1186 : cr->dta.has_time = 1;
1552 1186 : cr->dta.time_prec = 3;
1553 1186 : cr->dta.time = (dt->dttime * UINT64_C(20) + 3) / 6 * 10000u;
1554 : }
1555 1206 : if (desttype != SYBMSTIME) {
1556 1186 : cr->dta.has_date = 1;
1557 1186 : 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 3696 : tds_convert_datetime4(const TDSCONTEXT * tds_ctx, const TDS_DATETIME4 * dt4, int desttype, CONV_RESULT * cr)
1592 : {
1593 : TDS_DATETIME dt;
1594 :
1595 3696 : 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 3696 : dt.dtdays = dt4->days;
1602 3696 : dt.dttime = dt4->minutes * (60u * 300u);
1603 3696 : return tds_convert_datetime(tds_ctx, &dt, desttype, 0, cr);
1604 : }
1605 :
1606 : static TDS_INT
1607 3750 : tds_convert_time(const TDSCONTEXT * tds_ctx, const TDS_TIME * time, int desttype, CONV_RESULT * cr)
1608 : {
1609 : TDS_DATETIMEALL dta;
1610 :
1611 3750 : 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 3740 : memset(&dta, 0, sizeof(dta));
1618 3740 : dta.has_time = 1;
1619 3740 : dta.time_prec = 3;
1620 3740 : dta.time = (*time * UINT64_C(100000) + 2) / 3;
1621 3740 : dta.time = (*time * UINT64_C(20) + 3) / 6 * 10000;
1622 3740 : return tds_convert_datetimeall(tds_ctx, SYBMSTIME, &dta, desttype, cr);
1623 : }
1624 :
1625 : static TDS_INT
1626 3770 : tds_convert_date(const TDSCONTEXT * tds_ctx, const TDS_DATE * date, int desttype, CONV_RESULT * cr)
1627 : {
1628 : TDS_DATETIMEALL dta;
1629 :
1630 3770 : 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 3760 : memset(&dta, 0, sizeof(dta));
1637 3760 : dta.has_date = 1;
1638 3760 : dta.date = *date;
1639 3760 : return tds_convert_datetimeall(tds_ctx, SYBMSDATE, &dta, desttype, cr);
1640 : }
1641 :
1642 : static TDS_INT
1643 2740 : tds_convert_bigtime(const TDSCONTEXT * tds_ctx, const TDS_BIGTIME * bigtime, int desttype, CONV_RESULT * cr)
1644 : {
1645 : TDS_DATETIMEALL dta;
1646 :
1647 2740 : 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 2740 : memset(&dta, 0, sizeof(dta));
1654 2740 : dta.time_prec = 6;
1655 2740 : dta.has_time = 1;
1656 2740 : dta.time = *bigtime % (UINT64_C(86400) * 1000000u) * 10u;
1657 2740 : return tds_convert_datetimeall(tds_ctx, SYBMSTIME, &dta, desttype, cr);
1658 : }
1659 :
1660 : static TDS_INT
1661 2770 : 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 2770 : 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 2770 : bdt = *bigdatetime;
1673 2770 : memset(&dta, 0, sizeof(dta));
1674 2770 : dta.time_prec = 6;
1675 2770 : dta.has_time = 1;
1676 2770 : dta.time = bdt % (UINT64_C(86400) * 1000000u) * 10u;
1677 2770 : bdt /= UINT64_C(86400) * 1000000u;
1678 2770 : dta.has_date = 1;
1679 2770 : dta.date = (TDS_INT) (bdt - BIGDATETIME_BIAS);
1680 2770 : 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 16298 : 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 16298 : switch (srctype) {
1963 556 : case CASE_ALL_BINARY:
1964 556 : len = srclen;
1965 556 : 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 170 : case SYBINT4:
1978 : case SYBUINT4:
1979 170 : len = 4;
1980 170 : 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 120 : case SYBNUMERIC:
1992 : case SYBDECIMAL:
1993 120 : len = sizeof(TDS_NUMERIC);
1994 120 : break;
1995 60 : case SYBREAL:
1996 60 : len = sizeof(TDS_REAL);
1997 60 : break;
1998 60 : case SYBFLT8:
1999 60 : len = sizeof(TDS_FLOAT);
2000 60 : break;
2001 60 : case SYBDATETIME:
2002 60 : len = sizeof(TDS_DATETIME);
2003 60 : break;
2004 60 : case SYBDATETIME4:
2005 60 : len = sizeof(TDS_DATETIME4);
2006 60 : break;
2007 60 : case SYBTIME:
2008 60 : len = sizeof(TDS_TIME);
2009 60 : break;
2010 60 : case SYBDATE:
2011 60 : len = sizeof(TDS_DATE);
2012 60 : break;
2013 240 : case SYBMSTIME:
2014 : case SYBMSDATE:
2015 : case SYBMSDATETIME2:
2016 : case SYBMSDATETIMEOFFSET:
2017 240 : len = sizeof(TDS_DATETIMEALL);
2018 240 : break;
2019 60 : case SYB5BIGTIME:
2020 60 : len = sizeof(TDS_BIGTIME);
2021 60 : break;
2022 60 : case SYB5BIGDATETIME:
2023 60 : len = sizeof(TDS_BIGDATETIME);
2024 60 : break;
2025 60 : case SYBUNIQUE:
2026 60 : len = sizeof(TDS_UNIQUE);
2027 60 : break;
2028 942 : case CASE_ALL_CHAR:
2029 942 : srclen = (TDS_UINT) tds_hex_trim(&src, srclen);
2030 :
2031 : /* a binary string output will be half the length of */
2032 : /* the string which represents it in hexadecimal */
2033 :
2034 942 : ib = cr->cb.ib;
2035 942 : if (desttype != TDS_CONVERT_BINARY) {
2036 : TDS_INT destlen;
2037 :
2038 728 : cr->ib = tds_new(TDS_CHAR, (srclen + 2u) / 2u);
2039 728 : test_alloc(cr->ib);
2040 728 : ib = cr->ib;
2041 728 : destlen = tds_char2hex(ib, 0xffffffffu, src, srclen);
2042 728 : if (destlen < 0)
2043 0 : TDS_ZERO_FREE(cr->ib);
2044 : return destlen;
2045 : }
2046 214 : return (TDS_INT) tds_char2hex(ib, cr->cb.len, src, srclen);
2047 :
2048 : default:
2049 : return TDS_CONVERT_NOAVAIL;
2050 : }
2051 2336 : return binary_to_result(desttype, src, len, cr);
2052 : }
2053 :
2054 : /**
2055 : * tds_convert
2056 : * converts a type to another.
2057 : * @p srctype and @p desttype should be SYB* TDS types, or, in case of @p desttype you can use
2058 : * TDS_CONVERT_CHAR/TDS_CONVERT_BINARY. Nullable types are not supported, use tds_get_conversion_type
2059 : * to get a not-nullable type.
2060 : *
2061 : * If you convert to SYBDECIMAL/SYBNUMERIC you MUST initialize precision and scale of cr->n.
2062 : *
2063 : * In case of fixed type you can pass directly the pointer to the value.
2064 : *
2065 : * Do not expect strings to be zero terminated. Databases support zero inside
2066 : * string. Using strlen may result on data loss or even a segmentation fault.
2067 : * Instead, use memcpy to copy destination using length returned.
2068 : *
2069 : * This function does not handle NULL, @p srclen should be >0. Client libraries handle NULLs each in their own way.
2070 : * @param tds_ctx context (used in conversion to data and to return messages)
2071 : * @param srctype type of source
2072 : * @param src pointer to source data to convert
2073 : * @param srclen length in bytes of source (not counting terminator or strings)
2074 : * @param desttype type of destination
2075 : * @param cr structure to hold result
2076 : * @return length of result or TDS_CONVERT_* failure code on failure. All TDS_CONVERT_* error constants are <0.
2077 : */
2078 : TDS_INT
2079 2599204 : tds_convert(const TDSCONTEXT *tds_ctx, int srctype, const void *src, TDS_UINT srclen, int desttype, CONV_RESULT *cr)
2080 : {
2081 2599204 : TDS_INT length = 0;
2082 :
2083 2599204 : assert(srclen >= 0 && srclen <= 2147483647u);
2084 :
2085 2599204 : if (srctype == SYBVARIANT) {
2086 2568 : const TDSVARIANT *v = (const TDSVARIANT*) src;
2087 2568 : srctype = v->type;
2088 2568 : src = v->data;
2089 2568 : srclen = v->data_len;
2090 : }
2091 :
2092 2599204 : switch (desttype) {
2093 16298 : case CASE_ALL_BINARY:
2094 16298 : return tds_convert_to_binary(srctype, src, srclen, desttype, cr);
2095 : }
2096 :
2097 2582906 : switch (srctype) {
2098 1427301 : case CASE_ALL_CHAR:
2099 1427301 : length = tds_convert_char(src, srclen, desttype, cr);
2100 1427301 : break;
2101 35772 : case SYBMONEY4:
2102 35772 : length = tds_convert_money4(tds_ctx, (const TDS_MONEY4 *) src, desttype, cr);
2103 35772 : break;
2104 54420 : case SYBMONEY:
2105 54420 : length = tds_convert_money(tds_ctx, (const TDS_MONEY *) src, desttype, cr);
2106 54420 : break;
2107 75208 : case SYBNUMERIC:
2108 : case SYBDECIMAL:
2109 75208 : length = tds_convert_numeric((const TDS_NUMERIC *) src, desttype, cr);
2110 75208 : break;
2111 6608 : case SYBBIT:
2112 : case SYBBITN:
2113 13216 : length = tds_convert_bit(src, desttype, cr);
2114 6608 : break;
2115 8424 : case SYBSINT1:
2116 16848 : length = tds_convert_int1((const int8_t *) src, desttype, cr);
2117 8424 : break;
2118 22564 : case SYBINT1:
2119 : case SYBUINT1:
2120 45128 : length = tds_convert_uint1((const TDS_TINYINT *) src, desttype, cr);
2121 22564 : break;
2122 27654 : case SYBINT2:
2123 55308 : length = tds_convert_int2((const TDS_SMALLINT *) src, desttype, cr);
2124 27654 : break;
2125 16562 : case SYBUINT2:
2126 33124 : length = tds_convert_uint2((const TDS_USMALLINT *) src, desttype, cr);
2127 16562 : break;
2128 51915 : case SYBINT4:
2129 103830 : length = tds_convert_int4((const TDS_INT *) src, desttype, cr);
2130 51915 : break;
2131 27382 : case SYBUINT4:
2132 54764 : length = tds_convert_uint4((const TDS_UINT *) src, desttype, cr);
2133 27382 : break;
2134 61284 : case SYBINT8:
2135 61284 : length = tds_convert_int8((const TDS_INT8 *) src, desttype, cr);
2136 61284 : break;
2137 35292 : case SYBUINT8:
2138 35292 : length = tds_convert_uint8((const TDS_UINT8 *) src, desttype, cr);
2139 35292 : break;
2140 65972 : case SYBREAL:
2141 65972 : length = tds_convert_real((const TDS_REAL *) src, desttype, cr);
2142 65972 : break;
2143 66084 : case SYBFLT8:
2144 66084 : length = tds_convert_flt8((const TDS_FLOAT *) src, desttype, cr);
2145 66084 : break;
2146 12416 : case SYBMSTIME:
2147 : case SYBMSDATE:
2148 : case SYBMSDATETIME2:
2149 : case SYBMSDATETIMEOFFSET:
2150 12416 : length = tds_convert_datetimeall(tds_ctx, srctype, (const TDS_DATETIMEALL *) src, desttype, cr);
2151 12416 : break;
2152 4992 : case SYBDATETIME:
2153 4992 : length = tds_convert_datetime(tds_ctx, (const TDS_DATETIME* ) src, desttype, 3, cr);
2154 4992 : break;
2155 3696 : case SYBDATETIME4:
2156 3696 : length = tds_convert_datetime4(tds_ctx, (const TDS_DATETIME4* ) src, desttype, cr);
2157 3696 : break;
2158 3750 : case SYBTIME:
2159 3750 : length = tds_convert_time(tds_ctx, (const TDS_TIME *) src, desttype, cr);
2160 3750 : break;
2161 3770 : case SYBDATE:
2162 3770 : length = tds_convert_date(tds_ctx, (const TDS_DATE *) src, desttype, cr);
2163 3770 : break;
2164 2740 : case SYB5BIGTIME:
2165 2740 : length = tds_convert_bigtime(tds_ctx, (const TDS_BIGTIME *) src, desttype, cr);
2166 2740 : break;
2167 2770 : case SYB5BIGDATETIME:
2168 2770 : length = tds_convert_bigdatetime(tds_ctx, (const TDS_BIGDATETIME *) src, desttype, cr);
2169 2770 : break;
2170 18306 : case CASE_ALL_BINARY:
2171 18306 : length = tds_convert_binary((const TDS_UCHAR *) src, srclen, desttype, cr);
2172 18306 : break;
2173 3134 : case SYBUNIQUE:
2174 3134 : length = tds_convert_unique(src, desttype, cr);
2175 3134 : break;
2176 : case SYBNVARCHAR:
2177 : case SYBNTEXT:
2178 : case SYBMSTABLE:
2179 : default:
2180 : length = TDS_CONVERT_NOAVAIL;
2181 : break;
2182 : }
2183 :
2184 : return length;
2185 : }
2186 :
2187 : static int
2188 2916 : string_to_datetime(const char *instr, TDS_UINT len, int desttype, CONV_RESULT * cr)
2189 : {
2190 : enum states {
2191 : GOING_IN_BLIND,
2192 : PUT_NUMERIC_IN_CONTEXT,
2193 : DOING_ALPHABETIC_DATE
2194 : };
2195 :
2196 : char *in;
2197 : char *tok;
2198 : char *lasts;
2199 : char last_token[32];
2200 2916 : int monthdone = 0;
2201 2916 : int yeardone = 0;
2202 2916 : int mdaydone = 0;
2203 :
2204 : struct tds_time t;
2205 :
2206 : unsigned int dt_time;
2207 : TDS_INT dt_days;
2208 : int i;
2209 :
2210 : enum states current_state;
2211 :
2212 2916 : memset(&t, '\0', sizeof(t));
2213 2916 : t.tm_mday = 1;
2214 :
2215 2916 : in = tds_strndup(instr, len);
2216 2916 : test_alloc(in);
2217 :
2218 2916 : tok = strtok_r(in, " ,", &lasts);
2219 :
2220 2916 : current_state = GOING_IN_BLIND;
2221 :
2222 11354 : while (tok != NULL) {
2223 :
2224 5532 : tdsdump_log(TDS_DBG_INFO1, "string_to_datetime: current_state = %d\n", current_state);
2225 5532 : switch (current_state) {
2226 3772 : case GOING_IN_BLIND:
2227 : /* If we have no idea of current context, then if we have */
2228 : /* encountered a purely alphabetic string, it MUST be an */
2229 : /* alphabetic month name or prefix... */
2230 :
2231 3772 : if (is_alphabetic(tok)) {
2232 870 : tdsdump_log(TDS_DBG_INFO1, "string_to_datetime: is_alphabetic\n");
2233 870 : if (store_monthname(tok, &t) >= 0) {
2234 860 : monthdone++;
2235 860 : current_state = DOING_ALPHABETIC_DATE;
2236 : } else {
2237 : goto string_garbled;
2238 : }
2239 : }
2240 :
2241 : /* ...whereas if it is numeric, it could be a number of */
2242 : /* things... */
2243 :
2244 2902 : else if (is_numeric(tok)) {
2245 40 : tdsdump_log(TDS_DBG_INFO1, "string_to_datetime: is_numeric\n");
2246 40 : switch (strlen(tok)) {
2247 : /* in this context a 4 character numeric can */
2248 : /* ONLY be the year part of an alphabetic date */
2249 :
2250 0 : case 4:
2251 0 : store_year(atoi(tok), &t);
2252 0 : yeardone++;
2253 0 : current_state = DOING_ALPHABETIC_DATE;
2254 0 : break;
2255 :
2256 : /* whereas these could be the hour part of a */
2257 : /* time specification ( 4 PM ) or the leading */
2258 : /* day part of an alphabetic date ( 15 Jan ) */
2259 :
2260 20 : case 2:
2261 : case 1:
2262 20 : strcpy(last_token, tok);
2263 20 : current_state = PUT_NUMERIC_IN_CONTEXT;
2264 20 : break;
2265 :
2266 : /* this must be a [YY]YYMMDD date */
2267 :
2268 20 : case 6:
2269 : case 8:
2270 20 : if (store_yymmdd_date(tok, &t))
2271 : current_state = GOING_IN_BLIND;
2272 : else
2273 : goto string_garbled;
2274 : break;
2275 :
2276 : /* anything else is nonsense... */
2277 :
2278 : default:
2279 : goto string_garbled;
2280 : break;
2281 : }
2282 : }
2283 :
2284 : /* it could be [M]M/[D]D/[YY]YY format */
2285 :
2286 2862 : else if (is_numeric_dateformat(tok)) {
2287 1026 : tdsdump_log(TDS_DBG_INFO1, "string_to_datetime: is_numeric_dateformat\n");
2288 1026 : store_numeric_date(tok, &t);
2289 1026 : current_state = GOING_IN_BLIND;
2290 1836 : } else if (is_dd_mon_yyyy(tok)) {
2291 10 : tdsdump_log(TDS_DBG_INFO1, "string_to_datetime: is_dd_mon_yyyy\n");
2292 10 : store_dd_mon_yyy_date(tok, &t);
2293 10 : current_state = GOING_IN_BLIND;
2294 1826 : } else if (is_timeformat(tok)) {
2295 1826 : tdsdump_log(TDS_DBG_INFO1, "string_to_datetime: is_timeformat\n");
2296 1826 : store_time(tok, &t);
2297 1826 : current_state = GOING_IN_BLIND;
2298 : } else {
2299 0 : tdsdump_log(TDS_DBG_INFO1, "string_to_datetime: string_garbled\n");
2300 : goto string_garbled;
2301 : }
2302 :
2303 : break; /* end of GOING_IN_BLIND */
2304 :
2305 1740 : case DOING_ALPHABETIC_DATE:
2306 :
2307 1740 : if (is_alphabetic(tok)) {
2308 0 : if (!monthdone && store_monthname(tok, &t) >= 0) {
2309 0 : monthdone++;
2310 0 : if (monthdone && yeardone && mdaydone)
2311 : current_state = GOING_IN_BLIND;
2312 : else
2313 0 : current_state = DOING_ALPHABETIC_DATE;
2314 : } else {
2315 : goto string_garbled;
2316 : }
2317 1740 : } else if (is_numeric(tok)) {
2318 1740 : if (mdaydone && yeardone)
2319 : goto string_garbled;
2320 : else
2321 1740 : switch (strlen(tok)) {
2322 880 : case 4:
2323 1760 : store_year(atoi(tok), &t);
2324 880 : yeardone++;
2325 880 : if (monthdone && yeardone && mdaydone)
2326 : current_state = GOING_IN_BLIND;
2327 : else
2328 0 : current_state = DOING_ALPHABETIC_DATE;
2329 : break;
2330 :
2331 860 : case 2:
2332 : case 1:
2333 860 : if (!mdaydone) {
2334 1720 : store_mday(tok, &t);
2335 :
2336 860 : mdaydone++;
2337 860 : if (monthdone && yeardone && mdaydone)
2338 : current_state = GOING_IN_BLIND;
2339 : else
2340 860 : current_state = DOING_ALPHABETIC_DATE;
2341 : } else {
2342 0 : store_year(atoi(tok), &t);
2343 0 : yeardone++;
2344 0 : if (monthdone && yeardone && mdaydone)
2345 : current_state = GOING_IN_BLIND;
2346 : else
2347 0 : current_state = DOING_ALPHABETIC_DATE;
2348 : }
2349 : break;
2350 :
2351 : default:
2352 : goto string_garbled;
2353 : }
2354 : } else {
2355 : goto string_garbled;
2356 : }
2357 :
2358 : break; /* end of DOING_ALPHABETIC_DATE */
2359 :
2360 20 : case PUT_NUMERIC_IN_CONTEXT:
2361 :
2362 20 : if (is_alphabetic(tok)) {
2363 20 : if (store_monthname(tok, &t) >= 0) {
2364 40 : store_mday(last_token, &t);
2365 20 : mdaydone++;
2366 20 : monthdone++;
2367 20 : if (monthdone && yeardone && mdaydone)
2368 : current_state = GOING_IN_BLIND;
2369 : else
2370 20 : current_state = DOING_ALPHABETIC_DATE;
2371 0 : } else if (is_ampm(tok)) {
2372 0 : store_hour(last_token, tok, &t);
2373 0 : current_state = GOING_IN_BLIND;
2374 : } else {
2375 : goto string_garbled;
2376 : }
2377 0 : } else if (is_numeric(tok)) {
2378 0 : switch (strlen(tok)) {
2379 : case 4:
2380 : case 2:
2381 0 : store_mday(last_token, &t);
2382 0 : mdaydone++;
2383 0 : store_year(atoi(tok), &t);
2384 0 : yeardone++;
2385 :
2386 0 : if (monthdone && yeardone && mdaydone)
2387 : current_state = GOING_IN_BLIND;
2388 : else
2389 0 : current_state = DOING_ALPHABETIC_DATE;
2390 : break;
2391 :
2392 : default:
2393 : goto string_garbled;
2394 : }
2395 : } else {
2396 : goto string_garbled;
2397 : }
2398 :
2399 : break; /* end of PUT_NUMERIC_IN_CONTEXT */
2400 : }
2401 :
2402 5522 : tok = strtok_r(NULL, " ,", &lasts);
2403 : }
2404 :
2405 2906 : i = (t.tm_mon - 13) / 12;
2406 8718 : dt_days = 1461 * (t.tm_year + 1900 + i) / 4 +
2407 5812 : (367 * (t.tm_mon - 1 - 12 * i)) / 12 - (3 * ((t.tm_year + 2000 + i) / 100)) / 4 + t.tm_mday - 693932;
2408 :
2409 2906 : free(in);
2410 :
2411 2906 : if (desttype == SYBDATE) {
2412 170 : cr->date = dt_days;
2413 170 : return sizeof(TDS_DATE);
2414 : }
2415 2736 : dt_time = t.tm_hour * 60 + t.tm_min;
2416 : /* TODO check for overflow */
2417 2736 : if (desttype == SYBDATETIME4) {
2418 660 : cr->dt4.days = dt_days;
2419 660 : cr->dt4.minutes = dt_time;
2420 660 : return sizeof(TDS_DATETIME4);
2421 : }
2422 2076 : dt_time = dt_time * 60 + t.tm_sec;
2423 2076 : if (desttype == SYBDATETIME) {
2424 790 : cr->dt.dtdays = dt_days;
2425 790 : cr->dt.dttime = dt_time * 300 + (t.tm_ns / 1000000u * 300 + 150) / 1000;
2426 790 : return sizeof(TDS_DATETIME);
2427 : }
2428 1286 : if (desttype == SYBTIME) {
2429 170 : cr->time = dt_time * 300 + (t.tm_ns / 1000000u * 300 + 150) / 1000;
2430 170 : return sizeof(TDS_TIME);
2431 : }
2432 1116 : if (desttype == SYB5BIGTIME) {
2433 90 : cr->bigtime = dt_time * UINT64_C(1000000) + t.tm_ns / 1000u;
2434 90 : return sizeof(TDS_BIGTIME);
2435 : }
2436 1026 : if (desttype == SYB5BIGDATETIME) {
2437 240 : cr->bigdatetime = (dt_days + BIGDATETIME_BIAS) * (UINT64_C(86400) * 1000000u)
2438 120 : + dt_time * UINT64_C(1000000) + t.tm_ns / 1000u;
2439 120 : return sizeof(TDS_BIGDATETIME);
2440 : }
2441 :
2442 906 : cr->dta.has_offset = 0;
2443 906 : cr->dta.offset = 0;
2444 906 : cr->dta.has_date = 1;
2445 906 : cr->dta.date = dt_days;
2446 906 : cr->dta.has_time = 1;
2447 906 : cr->dta.time_prec = 7; /* TODO correct value */
2448 906 : cr->dta.time = dt_time * UINT64_C(10000000) + t.tm_ns / 100u;
2449 906 : return sizeof(TDS_DATETIMEALL);
2450 :
2451 10 : string_garbled:
2452 10 : tdsdump_log(TDS_DBG_INFO1,
2453 : "error_handler: Attempt to convert data stopped by syntax error in source field \n");
2454 10 : free(in);
2455 10 : return TDS_CONVERT_SYNTAX;
2456 : }
2457 :
2458 : static int
2459 8970 : stringz_to_numeric(const char *instr, CONV_RESULT * cr)
2460 : {
2461 8970 : return string_to_numeric(instr, instr + strlen(instr), cr);
2462 : }
2463 :
2464 : static int
2465 116680 : string_to_numeric(const char *instr, const char *pend, CONV_RESULT * cr)
2466 : {
2467 : char mynumber[(MAXPRECISION + 7) / 8 * 8 + 8];
2468 :
2469 : /* num packaged 8 digit, see below for detail */
2470 : TDS_UINT packed_num[(MAXPRECISION + 7) / 8];
2471 :
2472 : char *ptr;
2473 :
2474 116680 : int i = 0;
2475 116680 : int j = 0;
2476 : int bytes;
2477 :
2478 : bool negative;
2479 : size_t digits, decimals;
2480 :
2481 : /* FIXME: application can pass invalid value for precision and scale ?? */
2482 116680 : if (cr->n.precision > MAXPRECISION)
2483 : return TDS_CONVERT_FAIL;
2484 :
2485 116680 : if (cr->n.precision == 0)
2486 0 : cr->n.precision = MAXPRECISION; /* assume max precision */
2487 :
2488 116680 : if (cr->n.scale > cr->n.precision)
2489 : return TDS_CONVERT_FAIL;
2490 :
2491 116680 : instr = parse_numeric(instr, pend, &negative, &digits, &decimals);
2492 116680 : if (!instr)
2493 : return TDS_CONVERT_SYNTAX;
2494 :
2495 116670 : cr->n.array[0] = negative ? 1 : 0;
2496 :
2497 : /* translate a number like 000ddddd.ffff to 00000000dddddffff00 */
2498 :
2499 : /*
2500 : * Having disposed of any sign and leading blanks,
2501 : * vet the digit string, counting places before and after
2502 : * the decimal point. Dispense with trailing blanks, if any.
2503 : */
2504 :
2505 116670 : ptr = mynumber;
2506 1050030 : for (i = 0; i < 8; ++i)
2507 933360 : *ptr++ = '0';
2508 :
2509 : /* too many digits, error */
2510 116670 : if (cr->n.precision - cr->n.scale < digits)
2511 : return TDS_CONVERT_OVERFLOW;
2512 :
2513 : /* copy digits before the dot */
2514 116380 : memcpy(ptr, instr, digits);
2515 116380 : ptr += digits;
2516 116380 : instr += digits + 1;
2517 :
2518 : /* copy digits after the dot */
2519 116380 : if (decimals > cr->n.scale)
2520 130 : decimals = cr->n.scale;
2521 116380 : memcpy(ptr, instr, decimals);
2522 :
2523 : /* fill up decimal digits */
2524 116380 : memset(ptr + decimals, '0', cr->n.scale - decimals);
2525 116380 : ptr += cr->n.scale;
2526 :
2527 : /*
2528 : * Packaged number explanation:
2529 : * We package 8 decimal digits in one number.
2530 : * Because 10^8 = 5^8 * 2^8 = 5^8 * 256, dividing 10^8 by 256 leaves no remainder.
2531 : * We can thus split it into bytes in an optimized way.
2532 : */
2533 :
2534 : /* transform to packaged one */
2535 116380 : j = -1;
2536 116380 : ptr -= 8;
2537 : do {
2538 183190 : TDS_UINT n = *ptr++;
2539 :
2540 1465520 : for (i = 1; i < 8; ++i)
2541 1282330 : n = n * 10u + *ptr++;
2542 : /* fix packet number and store */
2543 183190 : packed_num[++j] = n - ((TDS_UINT) '0' * 11111111lu);
2544 183190 : ptr -= 16;
2545 183190 : } while (ptr > mynumber);
2546 :
2547 116380 : memset(cr->n.array + 1, 0, sizeof(cr->n.array) - 1);
2548 116380 : bytes = tds_numeric_bytes_per_prec[cr->n.precision];
2549 232790 : while (j > 0 && !packed_num[j])
2550 30 : --j;
2551 :
2552 431300 : for (;;) {
2553 547680 : bool is_zero = true;
2554 547680 : TDS_UINT carry = 0;
2555 547680 : i = j;
2556 547680 : if (!packed_num[j])
2557 183160 : --j;
2558 : do {
2559 793470 : TDS_UINT tmp = packed_num[i];
2560 793470 : if (tmp)
2561 609050 : is_zero = false;
2562 :
2563 : /* divide for 256 for find another byte */
2564 : /*
2565 : * carry * (25u*25u*25u*25u) = carry * 10^8 / 256u
2566 : * using unsigned number is just an optimization
2567 : * compiler can translate division to a shift and remainder
2568 : * to a binary AND
2569 : */
2570 793470 : packed_num[i] = carry * (25u * 25u * 25u * 25u) + tmp / 256u;
2571 793470 : carry = tmp % 256u;
2572 793470 : } while(--i >= 0);
2573 547680 : if (is_zero)
2574 : break;
2575 : /*
2576 : * source number is limited to 38 decimal digit
2577 : * 10^39-1 < 2^128 (16 byte) so this cannot make an overflow
2578 : */
2579 431300 : cr->n.array[--bytes] = carry;
2580 : }
2581 : return sizeof(TDS_NUMERIC);
2582 : }
2583 :
2584 : static bool
2585 2862 : is_numeric_dateformat(const char *t)
2586 : {
2587 : const char *instr;
2588 2862 : int slashes = 0;
2589 2862 : int hyphens = 0;
2590 2862 : int periods = 0;
2591 2862 : int digits = 0;
2592 :
2593 16254 : for (instr = t; *instr; instr++) {
2594 15228 : if (!isdigit((unsigned char) *instr) && *instr != '/' && *instr != '-' && *instr != '.')
2595 : return false;
2596 :
2597 13392 : if (*instr == '/')
2598 0 : slashes++;
2599 13392 : else if (*instr == '-')
2600 2052 : hyphens++;
2601 11340 : else if (*instr == '.')
2602 0 : periods++;
2603 : else
2604 11340 : digits++;
2605 :
2606 : }
2607 1026 : if (hyphens + slashes + periods != 2)
2608 : return false;
2609 1026 : if (hyphens == 1 || slashes == 1 || periods == 1)
2610 : return false;
2611 :
2612 1026 : if (digits < 4 || digits > 8)
2613 : return false;
2614 :
2615 1026 : return true;
2616 :
2617 : }
2618 :
2619 : /* This function will check if an alphanumeric string */
2620 : /* holds a date in any of the following formats : */
2621 : /* DD-MON-YYYY */
2622 : /* DD-MON-YY */
2623 : /* DDMONYY */
2624 : /* DDMONYYYY */
2625 : static bool
2626 1836 : is_dd_mon_yyyy(char *t)
2627 : {
2628 : char *instr;
2629 : char month[4];
2630 :
2631 1836 : instr = t;
2632 :
2633 1836 : if (!isdigit((unsigned char) *instr))
2634 : return false;
2635 :
2636 1836 : instr++;
2637 :
2638 1836 : if (!isdigit((unsigned char) *instr))
2639 : return false;
2640 :
2641 1296 : instr++;
2642 :
2643 1296 : if (*instr == '-') {
2644 0 : instr++;
2645 :
2646 0 : strlcpy(month, instr, 4);
2647 :
2648 0 : if (!is_monthname(month))
2649 : return false;
2650 :
2651 0 : instr += 3;
2652 :
2653 0 : if (*instr != '-')
2654 : return false;
2655 :
2656 0 : instr++;
2657 0 : if (!isdigit((unsigned char) *instr))
2658 : return false;
2659 :
2660 0 : instr++;
2661 0 : if (!isdigit((unsigned char) *instr))
2662 : return false;
2663 :
2664 0 : instr++;
2665 :
2666 0 : if (*instr) {
2667 0 : if (!isdigit((unsigned char) *instr))
2668 : return false;
2669 :
2670 0 : instr++;
2671 0 : if (!isdigit((unsigned char) *instr))
2672 : return false;
2673 : }
2674 :
2675 : } else {
2676 :
2677 1296 : strlcpy(month, instr, 4);
2678 :
2679 1296 : if (!is_monthname(month))
2680 : return false;
2681 :
2682 10 : instr += 3;
2683 :
2684 10 : if (!isdigit((unsigned char) *instr))
2685 : return false;
2686 :
2687 10 : instr++;
2688 10 : if (!isdigit((unsigned char) *instr))
2689 : return false;
2690 :
2691 10 : instr++;
2692 10 : if (*instr) {
2693 10 : if (!isdigit((unsigned char) *instr))
2694 : return false;
2695 :
2696 10 : instr++;
2697 10 : if (!isdigit((unsigned char) *instr))
2698 : return false;
2699 : }
2700 : }
2701 :
2702 : return true;
2703 :
2704 : }
2705 :
2706 : static bool
2707 540 : is_ampm(const char *datestr)
2708 : {
2709 540 : if (strcasecmp(datestr, "am") == 0)
2710 : return true;
2711 :
2712 540 : if (strcasecmp(datestr, "pm") == 0)
2713 : return true;
2714 :
2715 0 : return false;
2716 : }
2717 :
2718 : static bool
2719 5532 : is_alphabetic(const char *datestr)
2720 : {
2721 : const char *s;
2722 :
2723 8282 : for (s = datestr; *s; s++) {
2724 7392 : if (!isalpha((unsigned char) *s))
2725 : return false;
2726 : }
2727 : return true;
2728 : }
2729 :
2730 : static bool
2731 4642 : is_numeric(const char *datestr)
2732 : {
2733 : const char *s;
2734 :
2735 17188 : for (s = datestr; *s; s++) {
2736 15408 : if (!isdigit((unsigned char) *s))
2737 : return false;
2738 : }
2739 : return true;
2740 : }
2741 :
2742 : static bool
2743 1826 : is_timeformat(const char *datestr)
2744 : {
2745 : const char *s;
2746 :
2747 18720 : for (s = datestr; *s; s++) {
2748 17434 : if (!isdigit((unsigned char) *s) && *s != ':' && *s != '.')
2749 : break;
2750 : }
2751 1826 : if (*s)
2752 540 : return is_ampm(s);
2753 :
2754 : return true;
2755 : }
2756 :
2757 : static int
2758 : store_year(int year, struct tds_time *t)
2759 : {
2760 :
2761 1936 : if (year < 0)
2762 : return 0;
2763 :
2764 1936 : if (year < 100) {
2765 10 : if (year > 49)
2766 0 : t->tm_year = year;
2767 : else
2768 10 : t->tm_year = 100 + year;
2769 : return (1);
2770 : }
2771 :
2772 1926 : if (year < 1753)
2773 : return (0);
2774 :
2775 1926 : if (year <= 9999) {
2776 1926 : t->tm_year = year - 1900;
2777 : return (1);
2778 : }
2779 :
2780 : return (0);
2781 :
2782 : }
2783 :
2784 : static int
2785 : store_mday(const char *datestr, struct tds_time *t)
2786 : {
2787 880 : int mday = atoi(datestr);
2788 :
2789 880 : if (mday > 0 && mday < 32) {
2790 880 : t->tm_mday = mday;
2791 : return 1;
2792 : }
2793 : return 0;
2794 : }
2795 :
2796 : static int
2797 1026 : store_numeric_date(const char *datestr, struct tds_time *t)
2798 : {
2799 1026 : int TDS_MONTH = 0;
2800 1026 : int TDS_DAY = 0;
2801 1026 : int TDS_YEAR = 0;
2802 :
2803 : int state;
2804 1026 : char last_char = 0;
2805 : const char *s;
2806 1026 : int month = 0, year = 0, mday = 0;
2807 :
2808 : /* Its YYYY-MM-DD format */
2809 :
2810 1026 : if (strlen(datestr) == 10 && *(datestr + 4) == '-' && *(datestr + 7) == '-') {
2811 :
2812 : TDS_YEAR = 0;
2813 : TDS_MONTH = 1;
2814 : TDS_DAY = 2;
2815 : state = TDS_YEAR;
2816 :
2817 : }
2818 : /* else we assume MDY */
2819 : else {
2820 0 : TDS_MONTH = 0;
2821 0 : TDS_DAY = 1;
2822 0 : TDS_YEAR = 2;
2823 0 : state = TDS_MONTH;
2824 : }
2825 11286 : for (s = datestr; *s; s++) {
2826 10260 : if (!isdigit((unsigned char) *s) && isdigit((unsigned char) last_char)) {
2827 2052 : state++;
2828 : } else {
2829 8208 : if (state == TDS_MONTH)
2830 2052 : month = (month * 10) + (*s - '0');
2831 8208 : if (state == TDS_DAY)
2832 2052 : mday = (mday * 10) + (*s - '0');
2833 8208 : if (state == TDS_YEAR)
2834 4104 : year = (year * 10) + (*s - '0');
2835 : }
2836 10260 : last_char = *s;
2837 : }
2838 :
2839 1026 : if (month > 0 && month < 13)
2840 1026 : t->tm_mon = month - 1;
2841 : else
2842 : return 0;
2843 1026 : if (mday > 0 && mday < 32)
2844 1026 : t->tm_mday = mday;
2845 : else
2846 : return 0;
2847 :
2848 1026 : return store_year(year, t);
2849 :
2850 : }
2851 :
2852 : static int
2853 10 : store_dd_mon_yyy_date(char *datestr, struct tds_time *t)
2854 : {
2855 :
2856 : char dd[3];
2857 : int mday;
2858 : char mon[4];
2859 : int year;
2860 :
2861 10 : tdsdump_log(TDS_DBG_INFO1, "store_dd_mon_yyy_date: %s\n", datestr);
2862 10 : strlcpy(dd, datestr, 3);
2863 10 : mday = atoi(dd);
2864 :
2865 10 : if (mday > 0 && mday < 32)
2866 10 : t->tm_mday = mday;
2867 : else
2868 : return 0;
2869 :
2870 10 : if (datestr[2] == '-') {
2871 0 : strlcpy(mon, &datestr[3], 4);
2872 :
2873 0 : if (store_monthname(mon, t) < 0) {
2874 0 : tdsdump_log(TDS_DBG_INFO1, "store_dd_mon_yyy_date: store_monthname failed\n");
2875 : return 0;
2876 : }
2877 :
2878 0 : year = atoi(&datestr[7]);
2879 0 : tdsdump_log(TDS_DBG_INFO1, "store_dd_mon_yyy_date: year %d\n", year);
2880 :
2881 0 : return store_year(year, t);
2882 : } else {
2883 10 : strlcpy(mon, &datestr[2], 4);
2884 :
2885 10 : 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 20 : year = atoi(&datestr[5]);
2891 10 : tdsdump_log(TDS_DBG_INFO1, "store_dd_mon_yyy_date: year %d\n", year);
2892 :
2893 10 : return store_year(year, t);
2894 : }
2895 :
2896 : }
2897 :
2898 : /**
2899 : * Test if a string is a month name and store correct month number
2900 : * @return month number (0-11) or -1 if not match
2901 : * @param datestr string to check
2902 : * @param t where to store month (if NULL no store is done)
2903 : */
2904 : static int
2905 2196 : store_monthname(const char *datestr, struct tds_time *t)
2906 : {
2907 : int ret;
2908 :
2909 2196 : tdsdump_log(TDS_DBG_INFO1, "store_monthname: %ld %s\n", (long) strlen(datestr), datestr);
2910 2196 : if (strlen(datestr) == 3) {
2911 2166 : if (strcasecmp(datestr, "jan") == 0)
2912 : ret = 0;
2913 2016 : else if (strcasecmp(datestr, "feb") == 0)
2914 : ret = 1;
2915 2016 : else if (strcasecmp(datestr, "mar") == 0)
2916 : ret = 2;
2917 2016 : else if (strcasecmp(datestr, "apr") == 0)
2918 : ret = 3;
2919 1836 : else if (strcasecmp(datestr, "may") == 0)
2920 : ret = 4;
2921 1826 : else if (strcasecmp(datestr, "jun") == 0)
2922 : ret = 5;
2923 1826 : else if (strcasecmp(datestr, "jul") == 0)
2924 : ret = 6;
2925 1826 : else if (strcasecmp(datestr, "aug") == 0)
2926 : ret = 7;
2927 1826 : else if (strcasecmp(datestr, "sep") == 0)
2928 : ret = 8;
2929 1826 : else if (strcasecmp(datestr, "oct") == 0)
2930 : ret = 9;
2931 1826 : else if (strcasecmp(datestr, "nov") == 0)
2932 : ret = 10;
2933 1826 : else if (strcasecmp(datestr, "dec") == 0)
2934 : ret = 11;
2935 : else
2936 : return -1;
2937 : } else {
2938 30 : if (strcasecmp(datestr, "january") == 0)
2939 : ret = 0;
2940 20 : else if (strcasecmp(datestr, "february") == 0)
2941 : ret = 1;
2942 20 : else if (strcasecmp(datestr, "march") == 0)
2943 : ret = 2;
2944 10 : else if (strcasecmp(datestr, "april") == 0)
2945 : ret = 3;
2946 10 : else if (strcasecmp(datestr, "june") == 0)
2947 : ret = 5;
2948 10 : else if (strcasecmp(datestr, "july") == 0)
2949 : ret = 6;
2950 10 : else if (strcasecmp(datestr, "august") == 0)
2951 : ret = 7;
2952 10 : else if (strcasecmp(datestr, "september") == 0)
2953 : ret = 8;
2954 10 : else if (strcasecmp(datestr, "october") == 0)
2955 : ret = 9;
2956 10 : else if (strcasecmp(datestr, "november") == 0)
2957 : ret = 10;
2958 10 : else if (strcasecmp(datestr, "december") == 0)
2959 : ret = 11;
2960 : else
2961 : return -1;
2962 : }
2963 900 : if (t)
2964 890 : t->tm_mon = ret;
2965 : return ret;
2966 : }
2967 :
2968 : static int
2969 20 : store_yymmdd_date(const char *datestr, struct tds_time *t)
2970 : {
2971 20 : int month = 0, year = 0, mday = 0;
2972 :
2973 : int wholedate;
2974 :
2975 20 : wholedate = atoi(datestr);
2976 :
2977 20 : year = wholedate / 10000;
2978 20 : month = (wholedate - (year * 10000)) / 100;
2979 20 : mday = (wholedate - (year * 10000) - (month * 100));
2980 :
2981 20 : if (month > 0 && month < 13)
2982 20 : t->tm_mon = month - 1;
2983 : else
2984 : return 0;
2985 20 : if (mday > 0 && mday < 32)
2986 20 : t->tm_mday = mday;
2987 : else
2988 : return 0;
2989 :
2990 20 : return (store_year(year, t));
2991 :
2992 : }
2993 :
2994 : static int
2995 1826 : store_time(const char *datestr, struct tds_time *t)
2996 : {
2997 : enum
2998 : { TDS_HOURS,
2999 : TDS_MINUTES,
3000 : TDS_SECONDS,
3001 : TDS_FRACTIONS
3002 : };
3003 :
3004 1826 : int state = TDS_HOURS;
3005 1826 : char last_sep = '\0';
3006 : const char *s;
3007 1826 : unsigned int hours = 0, minutes = 0, seconds = 0, nanosecs = 0;
3008 1826 : int ret = 1;
3009 1826 : unsigned ns_div = 1;
3010 :
3011 18720 : for (s = datestr; *s && strchr("apmAPM", (int) *s) == NULL; s++) {
3012 16894 : if (*s == ':' || *s == '.') {
3013 3878 : last_sep = *s;
3014 3878 : state++;
3015 : } else {
3016 13016 : if (*s < '0' || *s > '9')
3017 0 : ret = 0;
3018 13016 : switch (state) {
3019 3112 : case TDS_HOURS:
3020 3112 : hours = (hours * 10u) + (*s - '0');
3021 3112 : break;
3022 3652 : case TDS_MINUTES:
3023 3652 : minutes = (minutes * 10u) + (*s - '0');
3024 3652 : break;
3025 2572 : case TDS_SECONDS:
3026 2572 : seconds = (seconds * 10u) + (*s - '0');
3027 2572 : break;
3028 3680 : case TDS_FRACTIONS:
3029 3680 : if (ns_div < 1000000000u) {
3030 3680 : nanosecs = (nanosecs * 10u) + (*s - '0');
3031 3680 : ns_div *= 10;
3032 : }
3033 : break;
3034 : }
3035 : }
3036 : }
3037 1826 : if (*s) {
3038 540 : if (strcasecmp(s, "am") == 0) {
3039 0 : if (hours == 12)
3040 0 : hours = 0;
3041 :
3042 0 : t->tm_hour = hours;
3043 : }
3044 540 : if (strcasecmp(s, "pm") == 0) {
3045 540 : if (hours == 0)
3046 0 : ret = 0;
3047 540 : if (hours > 0u && hours < 12u)
3048 540 : t->tm_hour = hours + 12;
3049 : else
3050 0 : t->tm_hour = hours;
3051 : }
3052 : } else {
3053 1286 : if (hours < 24u)
3054 1286 : t->tm_hour = hours;
3055 : else
3056 : ret = 0;
3057 : }
3058 1826 : if (minutes < 60u)
3059 1826 : t->tm_min = minutes;
3060 : else
3061 : ret = 0;
3062 1826 : if (seconds < 60u)
3063 1826 : t->tm_sec = seconds;
3064 : else
3065 : ret = 0;
3066 1826 : tdsdump_log(TDS_DBG_FUNC, "store_time() nanosecs = %d\n", nanosecs);
3067 1826 : if (nanosecs) {
3068 556 : if (nanosecs < ns_div && last_sep == '.')
3069 556 : t->tm_ns = nanosecs * (1000000000u / ns_div);
3070 0 : else if (nanosecs < 1000u)
3071 0 : t->tm_ns = nanosecs * 1000000u;
3072 : else
3073 : ret = 0;
3074 : }
3075 :
3076 1826 : return (ret);
3077 : }
3078 :
3079 : static int
3080 0 : store_hour(const char *hour, const char *ampm, struct tds_time *t)
3081 : {
3082 0 : int ret = 1;
3083 : int hours;
3084 :
3085 0 : hours = atoi(hour);
3086 :
3087 0 : if (hours >= 0 && hours < 24) {
3088 0 : if (strcasecmp(ampm, "am") == 0) {
3089 0 : if (hours == 12)
3090 0 : hours = 0;
3091 :
3092 0 : t->tm_hour = hours;
3093 : }
3094 0 : if (strcasecmp(ampm, "pm") == 0) {
3095 0 : if (hours == 0)
3096 0 : ret = 0;
3097 0 : if (hours > 0 && hours < 12)
3098 0 : t->tm_hour = hours + 12;
3099 : else
3100 0 : t->tm_hour = hours;
3101 : }
3102 : }
3103 0 : return ret;
3104 : }
3105 :
3106 : /**
3107 : * Get same type but nullable
3108 : * @param srctype type requires
3109 : * @return nullable type
3110 : */
3111 : TDS_SERVER_TYPE
3112 86 : tds_get_null_type(TDS_SERVER_TYPE srctype)
3113 : {
3114 :
3115 86 : switch (srctype) {
3116 : case SYBCHAR:
3117 : return SYBVARCHAR;
3118 : break;
3119 32 : case SYBINT1:
3120 : case SYBSINT1:
3121 : case SYBUINT1:
3122 : case SYBINT2:
3123 : case SYBINT4:
3124 : case SYBINT8:
3125 : /* TODO sure ?? */
3126 : case SYBUINT2:
3127 : case SYBUINT4:
3128 : case SYBUINT8:
3129 32 : return SYBINTN;
3130 : break;
3131 0 : case SYBREAL:
3132 : case SYBFLT8:
3133 0 : return SYBFLTN;
3134 : break;
3135 0 : case SYBDATETIME:
3136 : case SYBDATETIME4:
3137 0 : return SYBDATETIMN;
3138 : break;
3139 4 : case SYBBIT:
3140 4 : return SYBBITN;
3141 : break;
3142 0 : case SYBMONEY:
3143 : case SYBMONEY4:
3144 0 : return SYBMONEYN;
3145 : break;
3146 0 : case SYBTIME:
3147 0 : return SYBTIMEN;
3148 : break;
3149 0 : case SYBDATE:
3150 0 : return SYBDATEN;
3151 : break;
3152 : default:
3153 : break;
3154 : }
3155 30 : return srctype;
3156 : }
3157 :
3158 : static void
3159 : two_digit(char *out, int num)
3160 : {
3161 1028 : if (num < 1)
3162 : num = 1;
3163 1028 : if (num > 31)
3164 0 : num = 31;
3165 1614 : tds02dfast(out, num);
3166 1614 : if (out[0] == '0')
3167 880 : out[0] = ' ';
3168 : }
3169 :
3170 : /**
3171 : * format a date string according to an "extended" strftime(3) formatting definition.
3172 : * @param buf output buffer
3173 : * @param maxsize size of buffer in bytes (space include terminator)
3174 : * @param format format string passed to strftime(3), except that %z represents fraction of seconds.
3175 : * @param dr date to convert
3176 : * @param prec second fraction precision (0-7).
3177 : * @return length of string returned, 0 for error
3178 : */
3179 : size_t
3180 3694 : tds_strftime(char *buf, size_t maxsize, const char *format, const TDSDATEREC * dr, int prec)
3181 : {
3182 : struct tm tm;
3183 :
3184 : size_t length;
3185 : char *our_format;
3186 : char *pz;
3187 3694 : bool z_found = false;
3188 3694 : size_t z_opt_len = 2;
3189 :
3190 3694 : assert(buf);
3191 3694 : assert(format);
3192 3694 : assert(dr);
3193 3694 : if (prec < 0 || prec > 7)
3194 0 : prec = 3;
3195 :
3196 3694 : tm.tm_sec = dr->second;
3197 3694 : tm.tm_min = dr->minute;
3198 3694 : tm.tm_hour = dr->hour;
3199 3694 : tm.tm_mday = dr->day;
3200 3694 : tm.tm_mon = dr->month;
3201 3694 : tm.tm_year = dr->year - 1900;
3202 3694 : tm.tm_wday = dr->weekday;
3203 3694 : tm.tm_yday = dr->dayofyear;
3204 3694 : tm.tm_isdst = 0;
3205 : #ifdef HAVE_STRUCT_TM_TM_ZONE
3206 3694 : tm.tm_zone = NULL;
3207 : #elif defined(HAVE_STRUCT_TM___TM_ZONE)
3208 : tm.__tm_zone = NULL;
3209 : #endif
3210 :
3211 : /* more characters are required because we replace %z with up to 7 digits */
3212 3694 : our_format = tds_new(char, strlen(format) + (1 + 5 + 1));
3213 3694 : if (!our_format)
3214 : return 0;
3215 :
3216 3694 : strcpy(our_format, format);
3217 :
3218 38280 : for (pz = our_format; *pz; ) {
3219 30892 : if (*pz++ != '%')
3220 13170 : continue;
3221 :
3222 17722 : switch (*pz) {
3223 10 : case 0:
3224 10 : *pz++ = '%';
3225 10 : *pz = 0;
3226 10 : continue;
3227 : case '%':
3228 : /* escaped, do not treat as format on next iteration */
3229 : break;
3230 1028 : case 'e':
3231 : /* not portable: day of month, single digit preceded by a blank */
3232 : /* not supported on old Windows versions */
3233 1028 : two_digit(pz-1, dr->day);
3234 : break;
3235 586 : case 'l':
3236 : /* not portable: 12-hour, single digit preceded by a blank */
3237 : /* not supported on: SCO Unix, AIX, HP-UX, Windows
3238 : * supported on: *BSD, MacOS, Linux, Solaris */
3239 586 : two_digit(pz-1, (dr->hour + 11u) % 12u + 1);
3240 : break;
3241 410 : case '1':
3242 : case '2':
3243 : case '3':
3244 : case '4':
3245 : case '5':
3246 : case '6':
3247 : case '7':
3248 : case '8':
3249 : case '9':
3250 410 : if (pz[1] != 'z')
3251 : break;
3252 410 : prec = pz[0] - '0';
3253 410 : z_opt_len = 3;
3254 1818 : case 'z':
3255 : /*
3256 : * Look for "%z" in the format string. If found, replace it with dr->milliseconds.
3257 : * For example, if milliseconds is 124, the format string
3258 : * "%b %d %Y %H:%M:%S.%z" would become
3259 : * "%b %d %Y %H:%M:%S.124".
3260 : */
3261 1818 : if (z_found)
3262 : break;
3263 1818 : z_found = true;
3264 :
3265 1818 : --pz;
3266 3488 : if (prec || pz <= our_format || pz[-1] != '.') {
3267 : char buf[10];
3268 : /* decimicrosecond should be a number from 0 to 9,999,999
3269 : * (regardless of prec, which is just the requested
3270 : * display precision). In case we are erroneously passed a
3271 : * sign, discard the sign. If erroneously given a number
3272 : * too big, discard leading digits.
3273 : */
3274 1670 : memset(buf, '0', sizeof(buf));
3275 1670 : tds_u32toa_fast_right(buf, dr->decimicrosecond & 0x7fffffff);
3276 1670 : memcpy(pz, buf + 3, prec);
3277 1670 : strcpy(pz + prec, format + (pz - our_format) + z_opt_len);
3278 1670 : pz += prec;
3279 : } else {
3280 148 : strcpy(pz - 1, format + (pz - our_format) + 2);
3281 148 : pz--;
3282 : }
3283 1818 : continue;
3284 : }
3285 15894 : ++pz;
3286 : }
3287 :
3288 3694 : length = strftime(buf, maxsize, our_format, &tm);
3289 :
3290 3694 : free(our_format);
3291 :
3292 3694 : return length;
3293 : }
3294 :
3295 : #if 0
3296 : static TDS_UINT
3297 : utf16len(const utf16_t * s)
3298 : {
3299 : const utf16_t *p = s;
3300 :
3301 : while (*p++)
3302 : continue;
3303 : return p - s;
3304 : }
3305 : #endif
3306 :
3307 : #include "tds_willconvert.h"
3308 :
3309 : /**
3310 : * Test if a conversion is possible
3311 : * @param srctype source type
3312 : * @param desttype destination type
3313 : * @return 0 if not convertible
3314 : */
3315 : unsigned char
3316 1613254 : tds_willconvert(int srctype, int desttype)
3317 : {
3318 : TDS_TINYINT cat_from, cat_to;
3319 : TDS_UINT yn;
3320 :
3321 1613254 : tdsdump_log(TDS_DBG_FUNC, "tds_willconvert(%d, %d)\n", srctype, desttype);
3322 :
3323 : /* they must be from 0 to 255 */
3324 1613254 : if (((srctype|desttype) & ~0xff) != 0)
3325 : return 0;
3326 :
3327 1613254 : cat_from = type2category[srctype];
3328 1613254 : cat_to = type2category[desttype];
3329 1613254 : yn = category_conversion[cat_from];
3330 :
3331 1613254 : yn = (yn >> cat_to) & 1;
3332 :
3333 1613254 : tdsdump_log(TDS_DBG_FUNC, "tds_willconvert(%d, %d) returns %s\n",
3334 : srctype, desttype, yn? "yes":"no");
3335 1613254 : return yn;
3336 : }
3337 :
3338 : #if 0
3339 : select day(d) as day, datepart(dw, d) as weekday, datepart(week, d) as week, d as 'date' from #t order by d
3340 : day weekday week date
3341 : ----------- ----------- ----------- ----------
3342 : 1 5 1 2009-01-01 Thursday
3343 : 2 6 1 2009-01-02 Friday
3344 : 3 7 1 2009-01-03 Saturday
3345 : 4 1 2 2009-01-04 Sunday
3346 : 5 2 2 2009-01-05
3347 : 6 3 2 2009-01-06
3348 : 7 4 2 2009-01-07
3349 : 8 5 2 2009-01-08
3350 : 9 6 2 2009-01-09
3351 : 10 7 2 2009-01-10
3352 : 11 1 3 2009-01-11
3353 : 12 2 3 2009-01-12
3354 : 13 3 3 2009-01-13
3355 : 14 4 3 2009-01-14
3356 : 15 5 3 2009-01-15
3357 : 16 6 3 2009-01-16
3358 : 17 7 3 2009-01-17
3359 : 18 1 4 2009-01-18
3360 : 19 2 4 2009-01-19
3361 : 20 3 4 2009-01-20
3362 : 21 4 4 2009-01-21
3363 : 22 5 4 2009-01-22
3364 : 23 6 4 2009-01-23
3365 : 24 7 4 2009-01-24
3366 : 25 1 5 2009-01-25
3367 : 26 2 5 2009-01-26
3368 : 27 3 5 2009-01-27
3369 : 28 4 5 2009-01-28
3370 : 29 5 5 2009-01-29
3371 : 30 6 5 2009-01-30
3372 : 31 7 5 2009-01-31
3373 : #endif
3374 : /**
3375 : * Convert from db date format to a structured date format
3376 : * @param datetype source date type. SYBDATETIME or SYBDATETIME4
3377 : * @param di source date
3378 : * @param dr destination date
3379 : * @return TDS_FAIL or TDS_SUCCESS
3380 : */
3381 : TDSRET
3382 6444 : tds_datecrack(TDS_INT datetype, const void *di, TDSDATEREC * dr)
3383 : {
3384 : int dt_days;
3385 : unsigned int dt_time;
3386 :
3387 6444 : int years, months, days, ydays, wday, hours, mins, secs, dms, tzone = 0;
3388 : int l, n, i, j;
3389 :
3390 6444 : memset(dr, 0, sizeof(*dr));
3391 :
3392 6444 : if (datetype == SYBMSDATE || datetype == SYBMSTIME
3393 6444 : || datetype == SYBMSDATETIME2 || datetype == SYBMSDATETIMEOFFSET) {
3394 4750 : const TDS_DATETIMEALL *dta = (const TDS_DATETIMEALL *) di;
3395 4750 : dt_days = (datetype == SYBMSTIME) ? 0 : dta->date;
3396 4750 : if (datetype == SYBMSDATE) {
3397 : dms = 0;
3398 : secs = 0;
3399 : dt_time = 0;
3400 : } else {
3401 3968 : dms = dta->time % 10000000u;
3402 3968 : dt_time = (unsigned int) (dta->time / 10000000u);
3403 3968 : secs = dt_time % 60;
3404 3968 : dt_time = dt_time / 60;
3405 : }
3406 4750 : if (datetype == SYBMSDATETIMEOFFSET) {
3407 126 : --dt_days;
3408 126 : dt_time = dt_time + 1440 + dta->offset;
3409 126 : dt_days += dt_time / 1440;
3410 126 : dt_time %= 1440;
3411 126 : tzone = dta->offset;
3412 : }
3413 1694 : } else if (datetype == SYBDATETIME) {
3414 1308 : const TDS_DATETIME *dt = (const TDS_DATETIME *) di;
3415 1308 : dt_time = dt->dttime;
3416 1308 : dms = ((dt_time % 300) * 1000 + 150) / 300 * 10000u;
3417 1308 : dt_time = dt_time / 300;
3418 1308 : secs = dt_time % 60;
3419 1308 : dt_time = dt_time / 60;
3420 1308 : dt_days = dt->dtdays;
3421 386 : } else if (datetype == SYBDATETIME4) {
3422 140 : const TDS_DATETIME4 *dt4 = (const TDS_DATETIME4 *) di;
3423 140 : secs = 0;
3424 140 : dms = 0;
3425 140 : dt_days = dt4->days;
3426 140 : dt_time = dt4->minutes;
3427 246 : } else if (datetype == SYBDATE) {
3428 92 : dt_days = *((const TDS_DATE *) di);
3429 92 : dms = 0;
3430 92 : secs = 0;
3431 92 : dt_time = 0;
3432 154 : } else if (datetype == SYBTIME) {
3433 94 : dt_time = *((const TDS_TIME *) di);
3434 94 : dms = ((dt_time % 300) * 1000 + 150) / 300 * 10000u;
3435 94 : dt_time = dt_time / 300;
3436 94 : secs = dt_time % 60;
3437 94 : dt_time = dt_time / 60;
3438 94 : dt_days = 0;
3439 60 : } else if (datetype == SYB5BIGTIME) {
3440 30 : TDS_UINT8 bigtime = *((const TDS_BIGTIME *) di);
3441 30 : dt_days = 0;
3442 30 : dms = bigtime % 1000000u * 10u;
3443 30 : dt_time = (bigtime / 1000000u) % 86400u;
3444 30 : secs = dt_time % 60;
3445 30 : dt_time = dt_time / 60u;
3446 30 : } else if (datetype == SYB5BIGDATETIME) {
3447 30 : TDS_UINT8 bigdatetime = *((const TDS_BIGDATETIME*) di);
3448 30 : dms = bigdatetime % 1000000u * 10u;
3449 30 : bigdatetime /= 1000000u;
3450 30 : secs = bigdatetime % 60u;
3451 30 : bigdatetime /= 60u;
3452 30 : dt_time = bigdatetime % (24u*60u);
3453 30 : dt_days = (int) (bigdatetime / (24u*60u) - BIGDATETIME_BIAS);
3454 : } else {
3455 : return TDS_FAIL;
3456 : }
3457 :
3458 : /*
3459 : * -53690 is minimun (1753-1-1) (Gregorian calendar start in 1732)
3460 : * 2958463 is maximun (9999-12-31)
3461 : */
3462 6444 : l = dt_days + (146038 + 146097*4);
3463 6444 : wday = (l + 4) % 7;
3464 6444 : n = (4 * l) / 146097; /* n century */
3465 6444 : l = l - (146097 * n + 3) / 4; /* days from xx00-02-28 (y-m-d) */
3466 6444 : i = (4000 * (l + 1)) / 1461001; /* years from xx00-02-28 */
3467 6444 : l = l - (1461 * i) / 4; /* year days from xx00-02-28 */
3468 6444 : ydays = l >= 306 ? l - 305 : l + 60;
3469 6444 : l += 31;
3470 6444 : j = (80 * l) / 2447;
3471 6444 : days = l - (2447 * j) / 80;
3472 6444 : l = j / 11;
3473 6444 : months = j + 1 - 12 * l;
3474 6444 : years = 100 * (n - 1) + i + l;
3475 6444 : if (l == 0 && (years & 3) == 0 && (years % 100 != 0 || years % 400 == 0))
3476 550 : ++ydays;
3477 :
3478 6444 : hours = dt_time / 60;
3479 6444 : mins = dt_time % 60;
3480 :
3481 6444 : dr->year = years;
3482 6444 : dr->month = months;
3483 6444 : dr->quarter = months / 3;
3484 6444 : dr->day = days;
3485 6444 : dr->dayofyear = ydays;
3486 6444 : dr->weekday = wday;
3487 6444 : dr->hour = hours;
3488 6444 : dr->minute = mins;
3489 6444 : dr->second = secs;
3490 6444 : dr->decimicrosecond = dms;
3491 6444 : dr->timezone = tzone;
3492 6444 : return TDS_SUCCESS;
3493 : }
3494 :
3495 : /**
3496 : * \brief convert a number in string to TDS_INT
3497 : *
3498 : * \return TDS_CONVERT_* or failure code on error
3499 : * \remarks Sybase's char->int conversion tolerates embedded blanks,
3500 : * such that "convert( int, ' - 13 ' )" works.
3501 : * If we find blanks, we copy the string to a temporary buffer,
3502 : * skipping the blanks.
3503 : * We return the results of atoi() with a clean string.
3504 : *
3505 : * n.b. it is possible to embed all sorts of non-printable characters, but we
3506 : * only check for spaces. at this time, no one on the project has tested anything else.
3507 : */
3508 : static TDS_INT
3509 602686 : string_to_int(const char *buf, const char *pend, TDS_INT * res)
3510 : {
3511 : bool negative;
3512 : unsigned int num; /* we use unsigned here for best overflow check */
3513 : size_t digits, decimals;
3514 :
3515 602686 : buf = parse_numeric(buf, pend, &negative, &digits, &decimals);
3516 602686 : if (!buf)
3517 : return TDS_CONVERT_SYNTAX;
3518 :
3519 : num = 0;
3520 3767040 : for (; digits; --digits, ++buf) {
3521 : /* add a digit to number and check for overflow */
3522 : /* NOTE I didn't forget a digit, I check overflow before multiply to prevent overflow */
3523 3988370 : if (num > 214748364u)
3524 : return TDS_CONVERT_OVERFLOW;
3525 3767040 : num = num * 10u + (*buf - '0');
3526 : }
3527 :
3528 : /* check for overflow and convert unsigned to signed */
3529 380796 : if (negative) {
3530 173226 : if (num > 2147483648u)
3531 : return TDS_CONVERT_OVERFLOW;
3532 171036 : *res = 0 - num;
3533 : } else {
3534 207570 : if (num >= 2147483648u)
3535 : return TDS_CONVERT_OVERFLOW;
3536 203940 : *res = num;
3537 : }
3538 :
3539 : return sizeof(TDS_INT);
3540 : }
3541 :
3542 : /**
3543 : * \brief convert a number in string to TDS_INT8
3544 : *
3545 : * \return TDS_CONVERT_* or failure code on error
3546 : */
3547 : static TDS_INT /* copied from string_ti_int and modified */
3548 476294 : parse_int8(const char *buf, const char *pend, TDS_UINT8 * res, bool * p_negative)
3549 : {
3550 : TDS_UINT8 num;
3551 : size_t digits, decimals;
3552 :
3553 476294 : buf = parse_numeric(buf, pend, p_negative, &digits, &decimals);
3554 476294 : if (!buf)
3555 : return TDS_CONVERT_SYNTAX;
3556 :
3557 : num = 0;
3558 4363272 : for (; digits; --digits, ++buf) {
3559 : /* add a digit to number and check for overflow */
3560 4375252 : TDS_UINT8 prev = num;
3561 4375252 : if (num > (UINT64_C(1) << 63) / 5u)
3562 : return TDS_CONVERT_OVERFLOW;
3563 4367812 : num = num * 10u + (*buf - '0');
3564 4367812 : if (num < prev)
3565 : return TDS_CONVERT_OVERFLOW;
3566 : }
3567 :
3568 463944 : *res = num;
3569 463944 : return sizeof(TDS_INT8);
3570 : }
3571 :
3572 : /**
3573 : * \brief convert a number in string to TDS_INT8
3574 : *
3575 : * \return TDS_CONVERT_* or failure code on error
3576 : */
3577 : static TDS_INT /* copied from string_ti_int and modified */
3578 374704 : string_to_int8(const char *buf, const char *pend, TDS_INT8 * res)
3579 : {
3580 : TDS_UINT8 num;
3581 : TDS_INT parse_res;
3582 : bool negative;
3583 :
3584 374704 : parse_res = parse_int8(buf, pend, &num, &negative);
3585 374704 : if (parse_res < 0)
3586 : return parse_res;
3587 :
3588 : /* check for overflow and convert unsigned to signed */
3589 366474 : if (negative) {
3590 168400 : if (num > UINT64_C(1) << 63)
3591 : return TDS_CONVERT_OVERFLOW;
3592 157150 : *res = 0 - num;
3593 : } else {
3594 198074 : if (num >= UINT64_C(1) << 63)
3595 : return TDS_CONVERT_OVERFLOW;
3596 185374 : *res = num;
3597 : }
3598 : return sizeof(TDS_INT8);
3599 : }
3600 :
3601 : /**
3602 : * \brief convert a number in string to TDS_UINT8
3603 : *
3604 : * \return TDS_CONVERT_* or failure code on error
3605 : */
3606 : static TDS_INT /* copied from string_to_int8 and modified */
3607 101590 : string_to_uint8(const char *buf, const char *pend, TDS_UINT8 * res)
3608 : {
3609 : TDS_UINT8 num;
3610 : TDS_INT parse_res;
3611 : bool negative;
3612 :
3613 101590 : parse_res = parse_int8(buf, pend, &num, &negative);
3614 101590 : if (parse_res < 0)
3615 : return parse_res;
3616 :
3617 : /* check for overflow */
3618 97470 : if (negative && num)
3619 : return TDS_CONVERT_OVERFLOW;
3620 :
3621 52470 : *res = num;
3622 52470 : return sizeof(TDS_UINT8);
3623 : }
3624 :
3625 : /**
3626 : * Parse a string for numbers.
3627 : *
3628 : * Syntax can be something like " *[+-] *[0-9]*\.[0-9]* *".
3629 : *
3630 : * The function ignore all spaces. It strips leading zeroes which could
3631 : * possibly lead to overflow.
3632 : * The function returns a pointer to the integer part followed by *p_digits
3633 : * digits followed by a dot followed by *p_decimals digits (dot and
3634 : * fractional digits are optional, in this case *p_decimals is 0).
3635 : *
3636 : * @param buf start of string
3637 : * @param pend pointer to string end
3638 : * @param p_negative store if number is negative
3639 : * @param p_digits store number of integer digits
3640 : * @param p_decimals store number of fractional digits
3641 : * @return pointer to first not zero digit. If NULL this indicate a syntax
3642 : * error.
3643 : */
3644 : static const char *
3645 1399450 : parse_numeric(const char *buf, const char *pend, bool *p_negative, size_t *p_digits, size_t *p_decimals)
3646 : {
3647 : enum { blank = ' ' };
3648 : #define SKIP_IF(cond) while (p != pend && (cond)) ++p;
3649 : const char *p, *start;
3650 1399450 : bool negative = false;
3651 :
3652 1399450 : *p_decimals = 0;
3653 1399450 : p = buf;
3654 :
3655 : /* ignore leading spaces */
3656 1399450 : SKIP_IF(*p == blank);
3657 1399450 : if (p == pend) {
3658 730 : *p_negative = false;
3659 730 : *p_digits = 0;
3660 730 : return p;
3661 : }
3662 :
3663 : /* check for sign */
3664 1398720 : switch (*p) {
3665 644176 : case '-':
3666 644176 : negative = true;
3667 : /* fall thru */
3668 644346 : case '+':
3669 : /* skip spaces between sign and number */
3670 644346 : ++p;
3671 644346 : SKIP_IF(*p == blank);
3672 : break;
3673 : }
3674 1398720 : *p_negative = negative;
3675 :
3676 : /* a digit must be present */
3677 1398720 : if (p == pend)
3678 : return NULL;
3679 :
3680 : /*
3681 : * skip leading zeroes
3682 : * Not skipping them cause numbers like "000000000000" to
3683 : * appear like overflow
3684 : */
3685 10910 : SKIP_IF(*p == '0');
3686 :
3687 : start = p;
3688 12174412 : SKIP_IF(TDS_ISDIGIT(*p));
3689 1398560 : *p_digits = p - start;
3690 :
3691 : /* parse decimal part */
3692 1398560 : if (p != pend && *p == '.') {
3693 3950 : const char *decimals_start = ++p;
3694 3950 : SKIP_IF(TDS_ISDIGIT(*p));
3695 3950 : *p_decimals = p - decimals_start;
3696 : }
3697 :
3698 : /* check for trailing spaces */
3699 586 : SKIP_IF(*p == blank);
3700 1398560 : if (p != pend)
3701 : return NULL;
3702 :
3703 1397750 : return start;
3704 : }
3705 :
3706 : static TDS_INT
3707 189290 : string_to_float(const TDS_CHAR * src, TDS_UINT srclen, int desttype, CONV_RESULT * cr)
3708 : {
3709 : char tmpstr[128];
3710 : char *end;
3711 : double res;
3712 :
3713 : /* ignore leading spaces */
3714 378580 : while (srclen > 0 && src[0] == ' ')
3715 0 : ++src, --srclen;
3716 :
3717 : /* ignore trailing blanks and nulls */
3718 189290 : while (srclen > 0 && (src[srclen - 1] == ' ' || src[srclen - 1] == '\0'))
3719 : --srclen;
3720 :
3721 189290 : if (srclen >= sizeof(tmpstr))
3722 : return TDS_CONVERT_OVERFLOW;
3723 :
3724 189290 : memcpy(tmpstr, src, srclen);
3725 189290 : tmpstr[srclen] = 0;
3726 :
3727 189290 : errno = 0;
3728 189290 : res = strtod(tmpstr, &end);
3729 189290 : if (errno == ERANGE)
3730 : return TDS_CONVERT_OVERFLOW;
3731 189290 : if (end != tmpstr + srclen)
3732 : return TDS_CONVERT_SYNTAX;
3733 :
3734 189290 : if (desttype == SYBREAL) {
3735 : /* FIXME check overflows */
3736 94640 : cr->r = (TDS_REAL)res;
3737 94640 : return sizeof(TDS_REAL);
3738 : }
3739 94650 : cr->f = res;
3740 94650 : return sizeof(TDS_FLOAT);
3741 : }
3742 :
3743 : /** @} */
|