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