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