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