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