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