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