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 16480 : string_to_result(int desttype, const char *s, CONV_RESULT * cr)
179 : {
180 16480 : size_t len = strlen(s);
181 :
182 16480 : if (desttype != TDS_CONVERT_CHAR) {
183 4598 : cr->c = tds_new(TDS_CHAR, len + 1);
184 4598 : test_alloc(cr->c);
185 4598 : 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 16480 : 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 760 : tds_char2hex(TDS_CHAR *dest, TDS_UINT destlen, const TDS_CHAR * src, TDS_UINT srclen)
308 : {
309 : unsigned int i;
310 760 : unsigned char hex1, c = 0;
311 :
312 : /* if srclen if odd we must add a "0" before ... */
313 760 : i = 0; /* number where to start converting */
314 760 : if (srclen & 1) {
315 288 : ++srclen;
316 288 : i = 1;
317 288 : --src;
318 : }
319 497052 : for (; i < srclen; ++i) {
320 497052 : hex1 = src[i];
321 :
322 497052 : if ('0' <= hex1 && hex1 <= '9')
323 414854 : hex1 &= 0x0f;
324 : else {
325 82198 : hex1 &= 0x20 ^ 0xff; /* mask off 0x20 to ensure upper case */
326 82198 : if ('A' <= hex1 && hex1 <= 'F') {
327 82198 : hex1 -= ('A' - 10);
328 : } else {
329 0 : 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 5260 : 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 20990 : 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 38552 : 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 159604 : tds_convert_int(TDS_INT num, int desttype, CONV_RESULT * cr)
635 : {
636 : TDS_CHAR tmp_str[16];
637 :
638 159604 : switch (desttype) {
639 9520 : case TDS_CONVERT_CHAR:
640 : case CASE_ALL_CHAR:
641 9520 : sprintf(tmp_str, "%d", num);
642 9520 : 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 12874 : 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 12874 : 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 728 : case CASE_ALL_CHAR:
1854 :
1855 : /* skip leading "0x" or "0X" */
1856 728 : 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 772 : 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 728 : ib = cr->cb.ib;
1870 728 : if (desttype != TDS_CONVERT_BINARY) {
1871 564 : cr->ib = tds_new(TDS_CHAR, (srclen + 2u) / 2u);
1872 564 : test_alloc(cr->ib);
1873 : ib = cr->ib;
1874 : }
1875 728 : return tds_char2hex(ib, desttype == TDS_CONVERT_BINARY ? cr->cb.len : 0xffffffffu, src, srclen);
1876 :
1877 : default:
1878 : return TDS_CONVERT_NOAVAIL;
1879 : }
1880 1682 : return binary_to_result(desttype, src, len, cr);
1881 : }
1882 :
1883 : /**
1884 : * tds_convert
1885 : * convert a type to another.
1886 : * If you convert to SYBDECIMAL/SYBNUMERIC you MUST initialize precision
1887 : * and scale of cr.
1888 : * Do not expect strings to be zero terminated. Databases support zero inside
1889 : * string. Using strlen may result on data loss or even a segmentation fault.
1890 : * Instead, use memcpy to copy destination using length returned.
1891 : * This function does not handle NULL, srclen should be >0. Client libraries handle NULLs each in their own way.
1892 : * @param tds_ctx context (used in conversion to data and to return messages)
1893 : * @param srctype type of source
1894 : * @param src pointer to source data to convert
1895 : * @param srclen length in bytes of source (not counting terminator or strings)
1896 : * @param desttype type of destination
1897 : * @param cr structure to hold result
1898 : * @return length of result or TDS_CONVERT_* failure code on failure. All TDS_CONVERT_* constants are <0.
1899 : */
1900 : TDS_INT
1901 1917284 : tds_convert(const TDSCONTEXT *tds_ctx, int srctype, const void *src, TDS_UINT srclen, int desttype, CONV_RESULT *cr)
1902 : {
1903 1917284 : TDS_INT length = 0;
1904 :
1905 1917284 : assert(srclen >= 0 && srclen <= 2147483647u);
1906 :
1907 1917284 : if (srctype == SYBVARIANT) {
1908 2054 : const TDSVARIANT *v = (const TDSVARIANT*) src;
1909 2054 : srctype = v->type;
1910 2054 : src = v->data;
1911 2054 : srclen = v->data_len;
1912 : }
1913 :
1914 1917284 : switch (desttype) {
1915 12874 : case CASE_ALL_BINARY:
1916 12874 : return tds_convert_to_binary(srctype, src, srclen, desttype, cr);
1917 : }
1918 :
1919 1904410 : switch (srctype) {
1920 1013408 : case CASE_ALL_CHAR:
1921 1013408 : length = tds_convert_char(src, srclen, desttype, cr);
1922 1013408 : break;
1923 26920 : case SYBMONEY4:
1924 26920 : length = tds_convert_money4(tds_ctx, (const TDS_MONEY4 *) src, desttype, cr);
1925 26920 : break;
1926 40826 : case SYBMONEY:
1927 40826 : length = tds_convert_money(tds_ctx, (const TDS_MONEY *) src, desttype, cr);
1928 40826 : break;
1929 56398 : case SYBNUMERIC:
1930 : case SYBDECIMAL:
1931 56398 : length = tds_convert_numeric((const TDS_NUMERIC *) src, desttype, cr);
1932 56398 : break;
1933 5260 : case SYBBIT:
1934 : case SYBBITN:
1935 10520 : length = tds_convert_bit(src, desttype, cr);
1936 5260 : break;
1937 16932 : case SYBINT1:
1938 : case SYBUINT1:
1939 33864 : length = tds_convert_int1((const TDS_TINYINT *) src, desttype, cr);
1940 16932 : break;
1941 20990 : case SYBINT2:
1942 41980 : length = tds_convert_int2((const TDS_SMALLINT *) src, desttype, cr);
1943 20990 : break;
1944 12578 : case SYBUINT2:
1945 25156 : length = tds_convert_uint2((const TDS_USMALLINT *) src, desttype, cr);
1946 12578 : break;
1947 38552 : case SYBINT4:
1948 77104 : length = tds_convert_int4((const TDS_INT *) src, desttype, cr);
1949 38552 : break;
1950 20422 : case SYBUINT4:
1951 40844 : length = tds_convert_uint4((const TDS_UINT *) src, desttype, cr);
1952 20422 : break;
1953 45998 : case SYBINT8:
1954 45998 : length = tds_convert_int8((const TDS_INT8 *) src, desttype, cr);
1955 45998 : break;
1956 26546 : case SYBUINT8:
1957 26546 : length = tds_convert_uint8((const TDS_UINT8 *) src, desttype, cr);
1958 26546 : break;
1959 49232 : case SYBREAL:
1960 49232 : length = tds_convert_real((const TDS_REAL *) src, desttype, cr);
1961 49232 : break;
1962 49322 : case SYBFLT8:
1963 49322 : length = tds_convert_flt8((const TDS_FLOAT *) src, desttype, cr);
1964 49322 : break;
1965 9892 : case SYBMSTIME:
1966 : case SYBMSDATE:
1967 : case SYBMSDATETIME2:
1968 : case SYBMSDATETIMEOFFSET:
1969 9892 : length = tds_convert_datetimeall(tds_ctx, srctype, (const TDS_DATETIMEALL *) src, desttype, cr);
1970 9892 : break;
1971 3556 : case SYBDATETIME:
1972 3556 : length = tds_convert_datetime(tds_ctx, (const TDS_DATETIME* ) src, desttype, 3, cr);
1973 3556 : break;
1974 2948 : case SYBDATETIME4:
1975 2948 : length = tds_convert_datetime4(tds_ctx, (const TDS_DATETIME4* ) src, desttype, cr);
1976 2948 : break;
1977 2560 : case SYBTIME:
1978 2560 : length = tds_convert_time(tds_ctx, (const TDS_TIME *) src, desttype, cr);
1979 2560 : break;
1980 2576 : case SYBDATE:
1981 2576 : length = tds_convert_date(tds_ctx, (const TDS_DATE *) src, desttype, cr);
1982 2576 : break;
1983 2192 : case SYB5BIGTIME:
1984 2192 : length = tds_convert_bigtime(tds_ctx, (const TDS_BIGTIME *) src, desttype, cr);
1985 2192 : break;
1986 2216 : case SYB5BIGDATETIME:
1987 2216 : length = tds_convert_bigdatetime(tds_ctx, (const TDS_BIGDATETIME *) src, desttype, cr);
1988 2216 : break;
1989 14676 : case CASE_ALL_BINARY:
1990 14676 : length = tds_convert_binary((const TDS_UCHAR *) src, srclen, desttype, cr);
1991 14676 : break;
1992 2498 : case SYBUNIQUE:
1993 2498 : length = tds_convert_unique(src, desttype, cr);
1994 2498 : break;
1995 : case SYBNVARCHAR:
1996 : case SYBNTEXT:
1997 : case SYBMSTABLE:
1998 : default:
1999 : return TDS_CONVERT_NOAVAIL;
2000 : break;
2001 : }
2002 :
2003 : /* fix MONEY case */
2004 : #if !defined(WORDS_BIGENDIAN)
2005 1466498 : if (length > 0 && desttype == SYBMONEY) {
2006 85968 : cr->m.mny = ((TDS_UINT8) cr->m.mny) >> 32 | (cr->m.mny << 32);
2007 : }
2008 : #endif
2009 : return length;
2010 : }
2011 :
2012 : static int
2013 2292 : string_to_datetime(const char *instr, TDS_UINT len, int desttype, CONV_RESULT * cr)
2014 : {
2015 : enum states {
2016 : GOING_IN_BLIND,
2017 : PUT_NUMERIC_IN_CONTEXT,
2018 : DOING_ALPHABETIC_DATE
2019 : };
2020 :
2021 : char *in;
2022 : char *tok;
2023 : char *lasts;
2024 : char last_token[32];
2025 2292 : int monthdone = 0;
2026 2292 : int yeardone = 0;
2027 2292 : int mdaydone = 0;
2028 :
2029 : struct tds_time t;
2030 :
2031 : unsigned int dt_time;
2032 : TDS_INT dt_days;
2033 : int i;
2034 :
2035 : enum states current_state;
2036 :
2037 2292 : memset(&t, '\0', sizeof(t));
2038 2292 : t.tm_mday = 1;
2039 :
2040 2292 : in = tds_strndup(instr, len);
2041 2292 : test_alloc(in);
2042 :
2043 2292 : tok = strtok_r(in, " ,", &lasts);
2044 :
2045 2292 : current_state = GOING_IN_BLIND;
2046 :
2047 9176 : while (tok != NULL) {
2048 :
2049 4600 : tdsdump_log(TDS_DBG_INFO1, "string_to_datetime: current_state = %d\n", current_state);
2050 4600 : switch (current_state) {
2051 3096 : case GOING_IN_BLIND:
2052 : /* If we have no idea of current context, then if we have */
2053 : /* encountered a purely alphabetic string, it MUST be an */
2054 : /* alphabetic month name or prefix... */
2055 :
2056 3096 : if (is_alphabetic(tok)) {
2057 744 : tdsdump_log(TDS_DBG_INFO1, "string_to_datetime: is_alphabetic\n");
2058 744 : if (store_monthname(tok, &t) >= 0) {
2059 736 : monthdone++;
2060 736 : current_state = DOING_ALPHABETIC_DATE;
2061 : } else {
2062 : goto string_garbled;
2063 : }
2064 : }
2065 :
2066 : /* ...whereas if it is numeric, it could be a number of */
2067 : /* things... */
2068 :
2069 2352 : else if (is_numeric(tok)) {
2070 32 : tdsdump_log(TDS_DBG_INFO1, "string_to_datetime: is_numeric\n");
2071 32 : switch (strlen(tok)) {
2072 : /* in this context a 4 character numeric can */
2073 : /* ONLY be the year part of an alphabetic date */
2074 :
2075 0 : case 4:
2076 0 : store_year(atoi(tok), &t);
2077 0 : yeardone++;
2078 0 : current_state = DOING_ALPHABETIC_DATE;
2079 0 : break;
2080 :
2081 : /* whereas these could be the hour part of a */
2082 : /* time specification ( 4 PM ) or the leading */
2083 : /* day part of an alphabetic date ( 15 Jan ) */
2084 :
2085 16 : case 2:
2086 : case 1:
2087 16 : strcpy(last_token, tok);
2088 16 : current_state = PUT_NUMERIC_IN_CONTEXT;
2089 16 : break;
2090 :
2091 : /* this must be a [YY]YYMMDD date */
2092 :
2093 16 : case 6:
2094 : case 8:
2095 16 : if (store_yymmdd_date(tok, &t))
2096 : current_state = GOING_IN_BLIND;
2097 : else
2098 : goto string_garbled;
2099 : break;
2100 :
2101 : /* anything else is nonsense... */
2102 :
2103 : default:
2104 : goto string_garbled;
2105 : break;
2106 : }
2107 : }
2108 :
2109 : /* it could be [M]M/[D]D/[YY]YY format */
2110 :
2111 2320 : else if (is_numeric_dateformat(tok)) {
2112 812 : tdsdump_log(TDS_DBG_INFO1, "string_to_datetime: is_numeric_dateformat\n");
2113 812 : store_numeric_date(tok, &t);
2114 812 : current_state = GOING_IN_BLIND;
2115 1508 : } else if (is_dd_mon_yyyy(tok)) {
2116 8 : tdsdump_log(TDS_DBG_INFO1, "string_to_datetime: is_dd_mon_yyyy\n");
2117 8 : store_dd_mon_yyy_date(tok, &t);
2118 8 : current_state = GOING_IN_BLIND;
2119 1500 : } else if (is_timeformat(tok)) {
2120 1500 : tdsdump_log(TDS_DBG_INFO1, "string_to_datetime: is_timeformat\n");
2121 1500 : store_time(tok, &t);
2122 1500 : current_state = GOING_IN_BLIND;
2123 : } else {
2124 0 : tdsdump_log(TDS_DBG_INFO1, "string_to_datetime: string_garbled\n");
2125 : goto string_garbled;
2126 : }
2127 :
2128 : break; /* end of GOING_IN_BLIND */
2129 :
2130 1488 : case DOING_ALPHABETIC_DATE:
2131 :
2132 1488 : if (is_alphabetic(tok)) {
2133 0 : if (!monthdone && store_monthname(tok, &t) >= 0) {
2134 0 : monthdone++;
2135 0 : if (monthdone && yeardone && mdaydone)
2136 : current_state = GOING_IN_BLIND;
2137 : else
2138 0 : current_state = DOING_ALPHABETIC_DATE;
2139 : } else {
2140 : goto string_garbled;
2141 : }
2142 1488 : } else if (is_numeric(tok)) {
2143 1488 : if (mdaydone && yeardone)
2144 : goto string_garbled;
2145 : else
2146 1488 : switch (strlen(tok)) {
2147 752 : case 4:
2148 1504 : store_year(atoi(tok), &t);
2149 752 : yeardone++;
2150 752 : if (monthdone && yeardone && mdaydone)
2151 : current_state = GOING_IN_BLIND;
2152 : else
2153 0 : current_state = DOING_ALPHABETIC_DATE;
2154 : break;
2155 :
2156 736 : case 2:
2157 : case 1:
2158 736 : if (!mdaydone) {
2159 1472 : store_mday(tok, &t);
2160 :
2161 736 : mdaydone++;
2162 736 : if (monthdone && yeardone && mdaydone)
2163 : current_state = GOING_IN_BLIND;
2164 : else
2165 736 : current_state = DOING_ALPHABETIC_DATE;
2166 : } else {
2167 0 : store_year(atoi(tok), &t);
2168 0 : yeardone++;
2169 0 : if (monthdone && yeardone && mdaydone)
2170 : current_state = GOING_IN_BLIND;
2171 : else
2172 0 : current_state = DOING_ALPHABETIC_DATE;
2173 : }
2174 : break;
2175 :
2176 : default:
2177 : goto string_garbled;
2178 : }
2179 : } else {
2180 : goto string_garbled;
2181 : }
2182 :
2183 : break; /* end of DOING_ALPHABETIC_DATE */
2184 :
2185 16 : case PUT_NUMERIC_IN_CONTEXT:
2186 :
2187 16 : if (is_alphabetic(tok)) {
2188 16 : if (store_monthname(tok, &t) >= 0) {
2189 32 : store_mday(last_token, &t);
2190 16 : mdaydone++;
2191 16 : monthdone++;
2192 16 : if (monthdone && yeardone && mdaydone)
2193 : current_state = GOING_IN_BLIND;
2194 : else
2195 16 : current_state = DOING_ALPHABETIC_DATE;
2196 0 : } else if (is_ampm(tok)) {
2197 0 : store_hour(last_token, tok, &t);
2198 0 : current_state = GOING_IN_BLIND;
2199 : } else {
2200 : goto string_garbled;
2201 : }
2202 0 : } else if (is_numeric(tok)) {
2203 0 : switch (strlen(tok)) {
2204 : case 4:
2205 : case 2:
2206 0 : store_mday(last_token, &t);
2207 0 : mdaydone++;
2208 0 : store_year(atoi(tok), &t);
2209 0 : yeardone++;
2210 :
2211 0 : if (monthdone && yeardone && mdaydone)
2212 : current_state = GOING_IN_BLIND;
2213 : else
2214 0 : current_state = DOING_ALPHABETIC_DATE;
2215 : break;
2216 :
2217 : default:
2218 : goto string_garbled;
2219 : }
2220 : } else {
2221 : goto string_garbled;
2222 : }
2223 :
2224 : break; /* end of PUT_NUMERIC_IN_CONTEXT */
2225 : }
2226 :
2227 4592 : tok = strtok_r(NULL, " ,", &lasts);
2228 : }
2229 :
2230 2284 : i = (t.tm_mon - 13) / 12;
2231 6852 : dt_days = 1461 * (t.tm_year + 1900 + i) / 4 +
2232 4568 : (367 * (t.tm_mon - 1 - 12 * i)) / 12 - (3 * ((t.tm_year + 2000 + i) / 100)) / 4 + t.tm_mday - 693932;
2233 :
2234 2284 : free(in);
2235 :
2236 2284 : if (desttype == SYBDATE) {
2237 136 : cr->date = dt_days;
2238 136 : return sizeof(TDS_DATE);
2239 : }
2240 2148 : dt_time = t.tm_hour * 60 + t.tm_min;
2241 : /* TODO check for overflow */
2242 2148 : if (desttype == SYBDATETIME4) {
2243 512 : cr->dt4.days = dt_days;
2244 512 : cr->dt4.minutes = dt_time;
2245 512 : return sizeof(TDS_DATETIME4);
2246 : }
2247 1636 : dt_time = dt_time * 60 + t.tm_sec;
2248 1636 : if (desttype == SYBDATETIME) {
2249 616 : cr->dt.dtdays = dt_days;
2250 616 : cr->dt.dttime = dt_time * 300 + (t.tm_ns / 1000000u * 300 + 150) / 1000;
2251 616 : return sizeof(TDS_DATETIME);
2252 : }
2253 1020 : if (desttype == SYBTIME) {
2254 136 : cr->time = dt_time * 300 + (t.tm_ns / 1000000u * 300 + 150) / 1000;
2255 136 : return sizeof(TDS_TIME);
2256 : }
2257 884 : if (desttype == SYB5BIGTIME) {
2258 72 : cr->bigtime = dt_time * (TDS_UINT8) 1000000u + t.tm_ns / 1000u;
2259 72 : return sizeof(TDS_BIGTIME);
2260 : }
2261 812 : if (desttype == SYB5BIGDATETIME) {
2262 192 : cr->bigdatetime = (dt_days + BIGDATETIME_BIAS) * ((TDS_UINT8) 86400u * 1000000u)
2263 96 : + dt_time * (TDS_UINT8) 1000000u + t.tm_ns / 1000u;
2264 96 : return sizeof(TDS_BIGDATETIME);
2265 : }
2266 :
2267 716 : cr->dta.has_offset = 0;
2268 716 : cr->dta.offset = 0;
2269 716 : cr->dta.has_date = 1;
2270 716 : cr->dta.date = dt_days;
2271 716 : cr->dta.has_time = 1;
2272 716 : cr->dta.time_prec = 7; /* TODO correct value */
2273 716 : cr->dta.time = ((TDS_UINT8) dt_time) * 10000000u + t.tm_ns / 100u;
2274 716 : return sizeof(TDS_DATETIMEALL);
2275 :
2276 8 : string_garbled:
2277 8 : tdsdump_log(TDS_DBG_INFO1,
2278 : "error_handler: Attempt to convert data stopped by syntax error in source field \n");
2279 8 : free(in);
2280 8 : return TDS_CONVERT_SYNTAX;
2281 : }
2282 :
2283 : static int
2284 7176 : stringz_to_numeric(const char *instr, CONV_RESULT * cr)
2285 : {
2286 7176 : return string_to_numeric(instr, instr + strlen(instr), cr);
2287 : }
2288 :
2289 : static int
2290 88976 : string_to_numeric(const char *instr, const char *pend, CONV_RESULT * cr)
2291 : {
2292 : char mynumber[(MAXPRECISION + 7) / 8 * 8 + 8];
2293 :
2294 : /* num packaged 8 digit, see below for detail */
2295 : TDS_UINT packed_num[(MAXPRECISION + 7) / 8];
2296 :
2297 : char *ptr;
2298 :
2299 88976 : int i = 0;
2300 88976 : int j = 0;
2301 : int bytes;
2302 :
2303 : bool negative;
2304 : size_t digits, decimals;
2305 :
2306 : /* FIXME: application can pass invalid value for precision and scale ?? */
2307 88976 : if (cr->n.precision > MAXPRECISION)
2308 : return TDS_CONVERT_FAIL;
2309 :
2310 88976 : if (cr->n.precision == 0)
2311 0 : cr->n.precision = MAXPRECISION; /* assume max precision */
2312 :
2313 88976 : if (cr->n.scale > cr->n.precision)
2314 : return TDS_CONVERT_FAIL;
2315 :
2316 88976 : instr = parse_numeric(instr, pend, &negative, &digits, &decimals);
2317 88976 : if (!instr)
2318 : return TDS_CONVERT_SYNTAX;
2319 :
2320 88968 : cr->n.array[0] = negative ? 1 : 0;
2321 :
2322 : /* translate a number like 000ddddd.ffff to 00000000dddddffff00 */
2323 :
2324 : /*
2325 : * Having disposed of any sign and leading blanks,
2326 : * vet the digit string, counting places before and after
2327 : * the decimal point. Dispense with trailing blanks, if any.
2328 : */
2329 :
2330 88968 : ptr = mynumber;
2331 800712 : for (i = 0; i < 8; ++i)
2332 711744 : *ptr++ = '0';
2333 :
2334 : /* too many digits, error */
2335 88968 : if (cr->n.precision - cr->n.scale < digits)
2336 : return TDS_CONVERT_OVERFLOW;
2337 :
2338 : /* copy digits before the dot */
2339 88736 : memcpy(ptr, instr, digits);
2340 88736 : ptr += digits;
2341 88736 : instr += digits + 1;
2342 :
2343 : /* copy digits after the dot */
2344 88736 : if (decimals > cr->n.scale)
2345 104 : decimals = cr->n.scale;
2346 88736 : memcpy(ptr, instr, decimals);
2347 :
2348 : /* fill up decimal digits */
2349 88736 : memset(ptr + decimals, '0', cr->n.scale - decimals);
2350 88736 : ptr += cr->n.scale;
2351 :
2352 : /*
2353 : * Packaged number explanation:
2354 : * We package 8 decimal digits in one number.
2355 : * Because 10^8 = 5^8 * 2^8 = 5^8 * 256, dividing 10^8 by 256 leaves no remainder.
2356 : * We can thus split it into bytes in an optimized way.
2357 : */
2358 :
2359 : /* transform to packaged one */
2360 88736 : j = -1;
2361 88736 : ptr -= 8;
2362 : do {
2363 139336 : TDS_UINT n = *ptr++;
2364 :
2365 1114688 : for (i = 1; i < 8; ++i)
2366 975352 : n = n * 10u + *ptr++;
2367 : /* fix packet number and store */
2368 139336 : packed_num[++j] = n - ((TDS_UINT) '0' * 11111111lu);
2369 139336 : ptr -= 16;
2370 139336 : } while (ptr > mynumber);
2371 :
2372 88736 : memset(cr->n.array + 1, 0, sizeof(cr->n.array) - 1);
2373 88736 : bytes = tds_numeric_bytes_per_prec[cr->n.precision];
2374 177472 : while (j > 0 && !packed_num[j])
2375 0 : --j;
2376 :
2377 328032 : for (;;) {
2378 416768 : bool is_zero = true;
2379 416768 : TDS_UINT carry = 0;
2380 416768 : i = j;
2381 416768 : if (!packed_num[j])
2382 139336 : --j;
2383 : do {
2384 602216 : TDS_UINT tmp = packed_num[i];
2385 602216 : if (tmp)
2386 462368 : is_zero = false;
2387 :
2388 : /* divide for 256 for find another byte */
2389 : /*
2390 : * carry * (25u*25u*25u*25u) = carry * 10^8 / 256u
2391 : * using unsigned number is just an optimization
2392 : * compiler can translate division to a shift and remainder
2393 : * to a binary AND
2394 : */
2395 602216 : packed_num[i] = carry * (25u * 25u * 25u * 25u) + tmp / 256u;
2396 602216 : carry = tmp % 256u;
2397 602216 : } while(--i >= 0);
2398 416768 : if (is_zero)
2399 : break;
2400 : /*
2401 : * source number is limited to 38 decimal digit
2402 : * 10^39-1 < 2^128 (16 byte) so this cannot make an overflow
2403 : */
2404 328032 : cr->n.array[--bytes] = carry;
2405 : }
2406 : return sizeof(TDS_NUMERIC);
2407 : }
2408 :
2409 : static bool
2410 2320 : is_numeric_dateformat(const char *t)
2411 : {
2412 : const char *instr;
2413 2320 : int slashes = 0;
2414 2320 : int hyphens = 0;
2415 2320 : int periods = 0;
2416 2320 : int digits = 0;
2417 :
2418 12976 : for (instr = t; *instr; instr++) {
2419 12164 : if (!isdigit((unsigned char) *instr) && *instr != '/' && *instr != '-' && *instr != '.')
2420 : return false;
2421 :
2422 10656 : if (*instr == '/')
2423 0 : slashes++;
2424 10656 : else if (*instr == '-')
2425 1624 : hyphens++;
2426 9032 : else if (*instr == '.')
2427 0 : periods++;
2428 : else
2429 9032 : digits++;
2430 :
2431 : }
2432 812 : if (hyphens + slashes + periods != 2)
2433 : return false;
2434 812 : if (hyphens == 1 || slashes == 1 || periods == 1)
2435 : return false;
2436 :
2437 812 : if (digits < 4 || digits > 8)
2438 : return false;
2439 :
2440 812 : return true;
2441 :
2442 : }
2443 :
2444 : /* This function will check if an alphanumeric string */
2445 : /* holds a date in any of the following formats : */
2446 : /* DD-MON-YYYY */
2447 : /* DD-MON-YY */
2448 : /* DDMONYY */
2449 : /* DDMONYYYY */
2450 : static bool
2451 1508 : is_dd_mon_yyyy(char *t)
2452 : {
2453 : char *instr;
2454 : char month[4];
2455 :
2456 1508 : instr = t;
2457 :
2458 1508 : if (!isdigit((unsigned char) *instr))
2459 : return false;
2460 :
2461 1508 : instr++;
2462 :
2463 1508 : if (!isdigit((unsigned char) *instr))
2464 : return false;
2465 :
2466 1028 : instr++;
2467 :
2468 1028 : if (*instr == '-') {
2469 0 : instr++;
2470 :
2471 0 : strlcpy(month, instr, 4);
2472 :
2473 0 : if (!is_monthname(month))
2474 : return false;
2475 :
2476 0 : instr += 3;
2477 :
2478 0 : if (*instr != '-')
2479 : return false;
2480 :
2481 0 : instr++;
2482 0 : if (!isdigit((unsigned char) *instr))
2483 : return false;
2484 :
2485 0 : instr++;
2486 0 : if (!isdigit((unsigned char) *instr))
2487 : return false;
2488 :
2489 0 : instr++;
2490 :
2491 0 : if (*instr) {
2492 0 : if (!isdigit((unsigned char) *instr))
2493 : return false;
2494 :
2495 0 : instr++;
2496 0 : if (!isdigit((unsigned char) *instr))
2497 : return false;
2498 : }
2499 :
2500 : } else {
2501 :
2502 1028 : strlcpy(month, instr, 4);
2503 :
2504 1028 : if (!is_monthname(month))
2505 : return false;
2506 :
2507 8 : instr += 3;
2508 :
2509 8 : if (!isdigit((unsigned char) *instr))
2510 : return false;
2511 :
2512 8 : instr++;
2513 8 : if (!isdigit((unsigned char) *instr))
2514 : return false;
2515 :
2516 8 : instr++;
2517 8 : if (*instr) {
2518 8 : if (!isdigit((unsigned char) *instr))
2519 : return false;
2520 :
2521 8 : instr++;
2522 8 : if (!isdigit((unsigned char) *instr))
2523 : return false;
2524 : }
2525 : }
2526 :
2527 : return true;
2528 :
2529 : }
2530 :
2531 : static bool
2532 480 : is_ampm(const char *datestr)
2533 : {
2534 480 : if (strcasecmp(datestr, "am") == 0)
2535 : return true;
2536 :
2537 480 : if (strcasecmp(datestr, "pm") == 0)
2538 : return true;
2539 :
2540 0 : return false;
2541 : }
2542 :
2543 : static bool
2544 4600 : is_alphabetic(const char *datestr)
2545 : {
2546 : const char *s;
2547 :
2548 6944 : for (s = datestr; *s; s++) {
2549 6184 : if (!isalpha((unsigned char) *s))
2550 : return false;
2551 : }
2552 : return true;
2553 : }
2554 :
2555 : static bool
2556 3840 : is_numeric(const char *datestr)
2557 : {
2558 : const char *s;
2559 :
2560 14160 : for (s = datestr; *s; s++) {
2561 12640 : if (!isdigit((unsigned char) *s))
2562 : return false;
2563 : }
2564 : return true;
2565 : }
2566 :
2567 : static bool
2568 1500 : is_timeformat(const char *datestr)
2569 : {
2570 : const char *s;
2571 :
2572 15076 : for (s = datestr; *s; s++) {
2573 14056 : if (!isdigit((unsigned char) *s) && *s != ':' && *s != '.')
2574 : break;
2575 : }
2576 1500 : if (*s)
2577 480 : return is_ampm(s);
2578 :
2579 : return true;
2580 : }
2581 :
2582 : static int
2583 : store_year(int year, struct tds_time *t)
2584 : {
2585 :
2586 1588 : if (year < 0)
2587 : return 0;
2588 :
2589 1588 : if (year < 100) {
2590 8 : if (year > 49)
2591 0 : t->tm_year = year;
2592 : else
2593 8 : t->tm_year = 100 + year;
2594 : return (1);
2595 : }
2596 :
2597 1580 : if (year < 1753)
2598 : return (0);
2599 :
2600 1580 : if (year <= 9999) {
2601 1580 : t->tm_year = year - 1900;
2602 : return (1);
2603 : }
2604 :
2605 : return (0);
2606 :
2607 : }
2608 :
2609 : static int
2610 : store_mday(const char *datestr, struct tds_time *t)
2611 : {
2612 752 : int mday = atoi(datestr);
2613 :
2614 752 : if (mday > 0 && mday < 32) {
2615 752 : t->tm_mday = mday;
2616 : return 1;
2617 : }
2618 : return 0;
2619 : }
2620 :
2621 : static int
2622 812 : store_numeric_date(const char *datestr, struct tds_time *t)
2623 : {
2624 812 : int TDS_MONTH = 0;
2625 812 : int TDS_DAY = 0;
2626 812 : int TDS_YEAR = 0;
2627 :
2628 : int state;
2629 812 : char last_char = 0;
2630 : const char *s;
2631 812 : int month = 0, year = 0, mday = 0;
2632 :
2633 : /* Its YYYY-MM-DD format */
2634 :
2635 812 : if (strlen(datestr) == 10 && *(datestr + 4) == '-' && *(datestr + 7) == '-') {
2636 :
2637 : TDS_YEAR = 0;
2638 : TDS_MONTH = 1;
2639 : TDS_DAY = 2;
2640 : state = TDS_YEAR;
2641 :
2642 : }
2643 : /* else we assume MDY */
2644 : else {
2645 0 : TDS_MONTH = 0;
2646 0 : TDS_DAY = 1;
2647 0 : TDS_YEAR = 2;
2648 0 : state = TDS_MONTH;
2649 : }
2650 8932 : for (s = datestr; *s; s++) {
2651 8120 : if (!isdigit((unsigned char) *s) && isdigit((unsigned char) last_char)) {
2652 1624 : state++;
2653 : } else {
2654 6496 : if (state == TDS_MONTH)
2655 1624 : month = (month * 10) + (*s - '0');
2656 6496 : if (state == TDS_DAY)
2657 1624 : mday = (mday * 10) + (*s - '0');
2658 6496 : if (state == TDS_YEAR)
2659 3248 : year = (year * 10) + (*s - '0');
2660 : }
2661 8120 : last_char = *s;
2662 : }
2663 :
2664 812 : if (month > 0 && month < 13)
2665 812 : t->tm_mon = month - 1;
2666 : else
2667 : return 0;
2668 812 : if (mday > 0 && mday < 32)
2669 812 : t->tm_mday = mday;
2670 : else
2671 : return 0;
2672 :
2673 812 : return store_year(year, t);
2674 :
2675 : }
2676 :
2677 : static int
2678 8 : store_dd_mon_yyy_date(char *datestr, struct tds_time *t)
2679 : {
2680 :
2681 : char dd[3];
2682 : int mday;
2683 : char mon[4];
2684 : int year;
2685 :
2686 8 : tdsdump_log(TDS_DBG_INFO1, "store_dd_mon_yyy_date: %s\n", datestr);
2687 8 : strlcpy(dd, datestr, 3);
2688 8 : mday = atoi(dd);
2689 :
2690 8 : if (mday > 0 && mday < 32)
2691 8 : t->tm_mday = mday;
2692 : else
2693 : return 0;
2694 :
2695 8 : if (datestr[2] == '-') {
2696 0 : strlcpy(mon, &datestr[3], 4);
2697 :
2698 0 : if (store_monthname(mon, t) < 0) {
2699 0 : tdsdump_log(TDS_DBG_INFO1, "store_dd_mon_yyy_date: store_monthname failed\n");
2700 : return 0;
2701 : }
2702 :
2703 0 : year = atoi(&datestr[7]);
2704 0 : tdsdump_log(TDS_DBG_INFO1, "store_dd_mon_yyy_date: year %d\n", year);
2705 :
2706 0 : return store_year(year, t);
2707 : } else {
2708 8 : strlcpy(mon, &datestr[2], 4);
2709 :
2710 8 : if (store_monthname(mon, t) < 0) {
2711 0 : tdsdump_log(TDS_DBG_INFO1, "store_dd_mon_yyy_date: store_monthname failed\n");
2712 : return 0;
2713 : }
2714 :
2715 16 : year = atoi(&datestr[5]);
2716 8 : tdsdump_log(TDS_DBG_INFO1, "store_dd_mon_yyy_date: year %d\n", year);
2717 :
2718 8 : return store_year(year, t);
2719 : }
2720 :
2721 : }
2722 :
2723 : /**
2724 : * Test if a string is a month name and store correct month number
2725 : * @return month number (0-11) or -1 if not match
2726 : * @param datestr string to check
2727 : * @param t where to store month (if NULL no store is done)
2728 : */
2729 : static int
2730 1796 : store_monthname(const char *datestr, struct tds_time *t)
2731 : {
2732 : int ret;
2733 :
2734 1796 : tdsdump_log(TDS_DBG_INFO1, "store_monthname: %ld %s\n", (long) strlen(datestr), datestr);
2735 1796 : if (strlen(datestr) == 3) {
2736 1772 : if (strcasecmp(datestr, "jan") == 0)
2737 : ret = 0;
2738 1652 : else if (strcasecmp(datestr, "feb") == 0)
2739 : ret = 1;
2740 1652 : else if (strcasecmp(datestr, "mar") == 0)
2741 : ret = 2;
2742 1652 : else if (strcasecmp(datestr, "apr") == 0)
2743 : ret = 3;
2744 1508 : else if (strcasecmp(datestr, "may") == 0)
2745 : ret = 4;
2746 1500 : else if (strcasecmp(datestr, "jun") == 0)
2747 : ret = 5;
2748 1500 : else if (strcasecmp(datestr, "jul") == 0)
2749 : ret = 6;
2750 1500 : else if (strcasecmp(datestr, "aug") == 0)
2751 : ret = 7;
2752 1500 : else if (strcasecmp(datestr, "sep") == 0)
2753 : ret = 8;
2754 1500 : else if (strcasecmp(datestr, "oct") == 0)
2755 : ret = 9;
2756 1500 : else if (strcasecmp(datestr, "nov") == 0)
2757 : ret = 10;
2758 1500 : else if (strcasecmp(datestr, "dec") == 0)
2759 : ret = 11;
2760 : else
2761 : return -1;
2762 : } else {
2763 24 : if (strcasecmp(datestr, "january") == 0)
2764 : ret = 0;
2765 16 : else if (strcasecmp(datestr, "february") == 0)
2766 : ret = 1;
2767 16 : else if (strcasecmp(datestr, "march") == 0)
2768 : ret = 2;
2769 8 : else if (strcasecmp(datestr, "april") == 0)
2770 : ret = 3;
2771 8 : else if (strcasecmp(datestr, "june") == 0)
2772 : ret = 5;
2773 8 : else if (strcasecmp(datestr, "july") == 0)
2774 : ret = 6;
2775 8 : else if (strcasecmp(datestr, "august") == 0)
2776 : ret = 7;
2777 8 : else if (strcasecmp(datestr, "september") == 0)
2778 : ret = 8;
2779 8 : else if (strcasecmp(datestr, "october") == 0)
2780 : ret = 9;
2781 8 : else if (strcasecmp(datestr, "november") == 0)
2782 : ret = 10;
2783 8 : else if (strcasecmp(datestr, "december") == 0)
2784 : ret = 11;
2785 : else
2786 : return -1;
2787 : }
2788 768 : if (t)
2789 760 : t->tm_mon = ret;
2790 : return ret;
2791 : }
2792 :
2793 : static int
2794 16 : store_yymmdd_date(const char *datestr, struct tds_time *t)
2795 : {
2796 16 : int month = 0, year = 0, mday = 0;
2797 :
2798 : int wholedate;
2799 :
2800 16 : wholedate = atoi(datestr);
2801 :
2802 16 : year = wholedate / 10000;
2803 16 : month = (wholedate - (year * 10000)) / 100;
2804 16 : mday = (wholedate - (year * 10000) - (month * 100));
2805 :
2806 16 : if (month > 0 && month < 13)
2807 16 : t->tm_mon = month - 1;
2808 : else
2809 : return 0;
2810 16 : if (mday > 0 && mday < 32)
2811 16 : t->tm_mday = mday;
2812 : else
2813 : return 0;
2814 :
2815 16 : return (store_year(year, t));
2816 :
2817 : }
2818 :
2819 : static int
2820 1500 : store_time(const char *datestr, struct tds_time *t)
2821 : {
2822 : enum
2823 : { TDS_HOURS,
2824 : TDS_MINUTES,
2825 : TDS_SECONDS,
2826 : TDS_FRACTIONS
2827 : };
2828 :
2829 1500 : int state = TDS_HOURS;
2830 1500 : char last_sep = '\0';
2831 : const char *s;
2832 1500 : unsigned int hours = 0, minutes = 0, seconds = 0, nanosecs = 0;
2833 1500 : int ret = 1;
2834 1500 : unsigned ns_div = 1;
2835 :
2836 15076 : for (s = datestr; *s && strchr("apmAPM", (int) *s) == NULL; s++) {
2837 13576 : if (*s == ':' || *s == '.') {
2838 3124 : last_sep = *s;
2839 3124 : state++;
2840 : } else {
2841 10452 : if (*s < '0' || *s > '9')
2842 0 : ret = 0;
2843 10452 : switch (state) {
2844 2520 : case TDS_HOURS:
2845 2520 : hours = (hours * 10u) + (*s - '0');
2846 2520 : break;
2847 3000 : case TDS_MINUTES:
2848 3000 : minutes = (minutes * 10u) + (*s - '0');
2849 3000 : break;
2850 2040 : case TDS_SECONDS:
2851 2040 : seconds = (seconds * 10u) + (*s - '0');
2852 2040 : break;
2853 2892 : case TDS_FRACTIONS:
2854 2892 : if (ns_div < 1000000000u) {
2855 2892 : nanosecs = (nanosecs * 10u) + (*s - '0');
2856 2892 : ns_div *= 10;
2857 : }
2858 : break;
2859 : }
2860 : }
2861 : }
2862 1500 : if (*s) {
2863 480 : if (strcasecmp(s, "am") == 0) {
2864 0 : if (hours == 12)
2865 0 : hours = 0;
2866 :
2867 0 : t->tm_hour = hours;
2868 : }
2869 480 : if (strcasecmp(s, "pm") == 0) {
2870 480 : if (hours == 0)
2871 0 : ret = 0;
2872 480 : if (hours > 0u && hours < 12u)
2873 480 : t->tm_hour = hours + 12;
2874 : else
2875 0 : t->tm_hour = hours;
2876 : }
2877 : } else {
2878 1020 : if (hours < 24u)
2879 1020 : t->tm_hour = hours;
2880 : else
2881 : ret = 0;
2882 : }
2883 1500 : if (minutes < 60u)
2884 1500 : t->tm_min = minutes;
2885 : else
2886 : ret = 0;
2887 1500 : if (seconds < 60u)
2888 1500 : t->tm_sec = seconds;
2889 : else
2890 : ret = 0;
2891 1500 : tdsdump_log(TDS_DBG_FUNC, "store_time() nanosecs = %d\n", nanosecs);
2892 1500 : if (nanosecs) {
2893 436 : if (nanosecs < ns_div && last_sep == '.')
2894 436 : t->tm_ns = nanosecs * (1000000000u / ns_div);
2895 0 : else if (nanosecs < 1000u)
2896 0 : t->tm_ns = nanosecs * 1000000u;
2897 : else
2898 : ret = 0;
2899 : }
2900 :
2901 1500 : return (ret);
2902 : }
2903 :
2904 : static int
2905 0 : store_hour(const char *hour, const char *ampm, struct tds_time *t)
2906 : {
2907 0 : int ret = 1;
2908 : int hours;
2909 :
2910 0 : hours = atoi(hour);
2911 :
2912 0 : if (hours >= 0 && hours < 24) {
2913 0 : if (strcasecmp(ampm, "am") == 0) {
2914 0 : if (hours == 12)
2915 0 : hours = 0;
2916 :
2917 0 : t->tm_hour = hours;
2918 : }
2919 0 : if (strcasecmp(ampm, "pm") == 0) {
2920 0 : if (hours == 0)
2921 0 : ret = 0;
2922 0 : if (hours > 0 && hours < 12)
2923 0 : t->tm_hour = hours + 12;
2924 : else
2925 0 : t->tm_hour = hours;
2926 : }
2927 : }
2928 0 : return ret;
2929 : }
2930 :
2931 : /**
2932 : * Get same type but nullable
2933 : * @param srctype type requires
2934 : * @return nullable type
2935 : */
2936 : TDS_SERVER_TYPE
2937 68 : tds_get_null_type(TDS_SERVER_TYPE srctype)
2938 : {
2939 :
2940 68 : switch (srctype) {
2941 : case SYBCHAR:
2942 : return SYBVARCHAR;
2943 : break;
2944 28 : case SYBINT1:
2945 : case SYBUINT1:
2946 : case SYBINT2:
2947 : case SYBINT4:
2948 : case SYBINT8:
2949 : /* TODO sure ?? */
2950 : case SYBUINT2:
2951 : case SYBUINT4:
2952 : case SYBUINT8:
2953 28 : return SYBINTN;
2954 : break;
2955 0 : case SYBREAL:
2956 : case SYBFLT8:
2957 0 : return SYBFLTN;
2958 : break;
2959 0 : case SYBDATETIME:
2960 : case SYBDATETIME4:
2961 0 : return SYBDATETIMN;
2962 : break;
2963 2 : case SYBBIT:
2964 2 : return SYBBITN;
2965 : break;
2966 0 : case SYBMONEY:
2967 : case SYBMONEY4:
2968 0 : return SYBMONEYN;
2969 : break;
2970 0 : case SYBTIME:
2971 0 : return SYBTIMEN;
2972 : break;
2973 0 : case SYBDATE:
2974 0 : return SYBDATEN;
2975 : break;
2976 : default:
2977 : break;
2978 : }
2979 22 : return srctype;
2980 : }
2981 :
2982 : static void
2983 : two_digit(char *out, int num)
2984 : {
2985 458 : if (num < 1)
2986 : num = 1;
2987 458 : if (num > 31)
2988 : num = 31;
2989 482 : out[0] = num < 10 ? ' ' : num/10 + '0';
2990 482 : out[1] = num%10 + '0';
2991 : }
2992 :
2993 : /**
2994 : * format a date string according to an "extended" strftime(3) formatting definition.
2995 : * @param buf output buffer
2996 : * @param maxsize size of buffer in bytes (space include terminator)
2997 : * @param format format string passed to strftime(3), except that %z represents fraction of seconds.
2998 : * @param dr date to convert
2999 : * @param prec second fraction precision (0-7).
3000 : * @return length of string returned, 0 for error
3001 : */
3002 : size_t
3003 1628 : tds_strftime(char *buf, size_t maxsize, const char *format, const TDSDATEREC * dr, int prec)
3004 : {
3005 : struct tm tm;
3006 :
3007 : size_t length;
3008 : char *our_format;
3009 : char *pz;
3010 1628 : bool z_found = false;
3011 :
3012 1628 : assert(buf);
3013 1628 : assert(format);
3014 1628 : assert(dr);
3015 1628 : assert(0 <= dr->decimicrosecond && dr->decimicrosecond < 10000000);
3016 1628 : if (prec < 0 || prec > 7)
3017 0 : prec = 3;
3018 :
3019 1628 : tm.tm_sec = dr->second;
3020 1628 : tm.tm_min = dr->minute;
3021 1628 : tm.tm_hour = dr->hour;
3022 1628 : tm.tm_mday = dr->day;
3023 1628 : tm.tm_mon = dr->month;
3024 1628 : tm.tm_year = dr->year - 1900;
3025 1628 : tm.tm_wday = dr->weekday;
3026 1628 : tm.tm_yday = dr->dayofyear;
3027 1628 : tm.tm_isdst = 0;
3028 : #ifdef HAVE_STRUCT_TM_TM_ZONE
3029 1628 : tm.tm_zone = NULL;
3030 : #elif defined(HAVE_STRUCT_TM___TM_ZONE)
3031 : tm.__tm_zone = NULL;
3032 : #endif
3033 :
3034 : /* more characters are required because we replace %z with up to 7 digits */
3035 1628 : our_format = tds_new(char, strlen(format) + 1 + 5 + 1);
3036 1628 : if (!our_format)
3037 : return 0;
3038 :
3039 1628 : strcpy(our_format, format);
3040 :
3041 19870 : for (pz = our_format; *pz; ) {
3042 16614 : if (*pz++ != '%')
3043 7206 : continue;
3044 :
3045 9408 : switch (*pz) {
3046 8 : case 0:
3047 8 : *pz++ = '%';
3048 8 : *pz = 0;
3049 8 : continue;
3050 : case '%':
3051 : /* escaped, do not treat as format on next iteration */
3052 : break;
3053 458 : case 'e':
3054 : /* not portable: day of month, single digit preceded by a blank */
3055 : /* not supported on old Windows versions */
3056 458 : two_digit(pz-1, dr->day);
3057 : break;
3058 24 : case 'l':
3059 : /* not portable: 12-hour, single digit preceded by a blank */
3060 : /* not supported on: SCO Unix, AIX, HP-UX, Windows
3061 : * supported on: *BSD, MacOS, Linux, Solaris */
3062 24 : two_digit(pz-1, (dr->hour + 11u) % 12u + 1);
3063 : break;
3064 1130 : case 'z':
3065 : /*
3066 : * Look for "%z" in the format string. If found, replace it with dr->milliseconds.
3067 : * For example, if milliseconds is 124, the format string
3068 : * "%b %d %Y %H:%M:%S.%z" would become
3069 : * "%b %d %Y %H:%M:%S.124".
3070 : */
3071 1130 : if (z_found)
3072 : break;
3073 1130 : z_found = true;
3074 :
3075 1130 : --pz;
3076 2144 : if (prec || pz <= our_format || pz[-1] != '.') {
3077 : char buf[12];
3078 1014 : sprintf(buf, "%07d", dr->decimicrosecond);
3079 1014 : memcpy(pz, buf, prec);
3080 1014 : strcpy(pz + prec, format + (pz - our_format) + 2);
3081 1014 : pz += prec;
3082 : } else {
3083 116 : strcpy(pz - 1, format + (pz - our_format) + 2);
3084 116 : pz--;
3085 : }
3086 1130 : continue;
3087 : }
3088 8270 : ++pz;
3089 : }
3090 :
3091 1628 : length = strftime(buf, maxsize, our_format, &tm);
3092 :
3093 1628 : free(our_format);
3094 :
3095 1628 : return length;
3096 : }
3097 :
3098 : #if 0
3099 : static TDS_UINT
3100 : utf16len(const utf16_t * s)
3101 : {
3102 : const utf16_t *p = s;
3103 :
3104 : while (*p++)
3105 : continue;
3106 : return p - s;
3107 : }
3108 : #endif
3109 :
3110 : #include "tds_willconvert.h"
3111 :
3112 : /**
3113 : * Test if a conversion is possible
3114 : * @param srctype source type
3115 : * @param desttype destination type
3116 : * @return 0 if not convertible
3117 : */
3118 : unsigned char
3119 1290584 : tds_willconvert(int srctype, int desttype)
3120 : {
3121 : TDS_TINYINT cat_from, cat_to;
3122 : TDS_UINT yn;
3123 :
3124 1290584 : tdsdump_log(TDS_DBG_FUNC, "tds_willconvert(%d, %d)\n", srctype, desttype);
3125 :
3126 : /* they must be from 0 to 255 */
3127 1290584 : if (((srctype|desttype) & ~0xff) != 0)
3128 : return 0;
3129 :
3130 1290584 : cat_from = type2category[srctype];
3131 1290584 : cat_to = type2category[desttype];
3132 1290584 : yn = category_conversion[cat_from];
3133 :
3134 1290584 : yn = (yn >> cat_to) & 1;
3135 :
3136 1290584 : tdsdump_log(TDS_DBG_FUNC, "tds_willconvert(%d, %d) returns %s\n",
3137 : srctype, desttype, yn? "yes":"no");
3138 1290584 : return yn;
3139 : }
3140 :
3141 : #if 0
3142 : select day(d) as day, datepart(dw, d) as weekday, datepart(week, d) as week, d as 'date' from #t order by d
3143 : day weekday week date
3144 : ----------- ----------- ----------- ----------
3145 : 1 5 1 2009-01-01 Thursday
3146 : 2 6 1 2009-01-02 Friday
3147 : 3 7 1 2009-01-03 Saturday
3148 : 4 1 2 2009-01-04 Sunday
3149 : 5 2 2 2009-01-05
3150 : 6 3 2 2009-01-06
3151 : 7 4 2 2009-01-07
3152 : 8 5 2 2009-01-08
3153 : 9 6 2 2009-01-09
3154 : 10 7 2 2009-01-10
3155 : 11 1 3 2009-01-11
3156 : 12 2 3 2009-01-12
3157 : 13 3 3 2009-01-13
3158 : 14 4 3 2009-01-14
3159 : 15 5 3 2009-01-15
3160 : 16 6 3 2009-01-16
3161 : 17 7 3 2009-01-17
3162 : 18 1 4 2009-01-18
3163 : 19 2 4 2009-01-19
3164 : 20 3 4 2009-01-20
3165 : 21 4 4 2009-01-21
3166 : 22 5 4 2009-01-22
3167 : 23 6 4 2009-01-23
3168 : 24 7 4 2009-01-24
3169 : 25 1 5 2009-01-25
3170 : 26 2 5 2009-01-26
3171 : 27 3 5 2009-01-27
3172 : 28 4 5 2009-01-28
3173 : 29 5 5 2009-01-29
3174 : 30 6 5 2009-01-30
3175 : 31 7 5 2009-01-31
3176 : #endif
3177 : /**
3178 : * Convert from db date format to a structured date format
3179 : * @param datetype source date type. SYBDATETIME or SYBDATETIME4
3180 : * @param di source date
3181 : * @param dr destination date
3182 : * @return TDS_FAIL or TDS_SUCCESS
3183 : */
3184 : TDSRET
3185 3810 : tds_datecrack(TDS_INT datetype, const void *di, TDSDATEREC * dr)
3186 : {
3187 : int dt_days;
3188 : unsigned int dt_time;
3189 :
3190 3810 : int years, months, days, ydays, wday, hours, mins, secs, dms, tzone = 0;
3191 : int l, n, i, j;
3192 :
3193 3810 : memset(dr, 0, sizeof(*dr));
3194 :
3195 3810 : if (datetype == SYBMSDATE || datetype == SYBMSTIME
3196 3810 : || datetype == SYBMSDATETIME2 || datetype == SYBMSDATETIMEOFFSET) {
3197 2850 : const TDS_DATETIMEALL *dta = (const TDS_DATETIMEALL *) di;
3198 2850 : dt_days = (datetype == SYBMSTIME) ? 0 : dta->date;
3199 2850 : if (datetype == SYBMSDATE) {
3200 : dms = 0;
3201 : secs = 0;
3202 : dt_time = 0;
3203 : } else {
3204 2668 : dms = dta->time % 10000000u;
3205 2668 : dt_time = (unsigned int) (dta->time / 10000000u);
3206 2668 : secs = dt_time % 60;
3207 2668 : dt_time = dt_time / 60;
3208 : }
3209 2850 : if (datetype == SYBMSDATETIMEOFFSET) {
3210 96 : --dt_days;
3211 96 : dt_time = dt_time + 1440 + dta->offset;
3212 96 : dt_days += dt_time / 1440;
3213 96 : dt_time %= 1440;
3214 96 : tzone = dta->offset;
3215 : }
3216 960 : } else if (datetype == SYBDATETIME) {
3217 650 : const TDS_DATETIME *dt = (const TDS_DATETIME *) di;
3218 650 : dt_time = dt->dttime;
3219 650 : dms = ((dt_time % 300) * 1000 + 150) / 300 * 10000u;
3220 650 : dt_time = dt_time / 300;
3221 650 : secs = dt_time % 60;
3222 650 : dt_time = dt_time / 60;
3223 650 : dt_days = dt->dtdays;
3224 310 : } else if (datetype == SYBDATETIME4) {
3225 112 : const TDS_DATETIME4 *dt4 = (const TDS_DATETIME4 *) di;
3226 112 : secs = 0;
3227 112 : dms = 0;
3228 112 : dt_days = dt4->days;
3229 112 : dt_time = dt4->minutes;
3230 198 : } else if (datetype == SYBDATE) {
3231 74 : dt_days = *((const TDS_DATE *) di);
3232 74 : dms = 0;
3233 74 : secs = 0;
3234 74 : dt_time = 0;
3235 124 : } else if (datetype == SYBTIME) {
3236 76 : dt_time = *((const TDS_TIME *) di);
3237 76 : dms = ((dt_time % 300) * 1000 + 150) / 300 * 10000u;
3238 76 : dt_time = dt_time / 300;
3239 76 : secs = dt_time % 60;
3240 76 : dt_time = dt_time / 60;
3241 76 : dt_days = 0;
3242 48 : } else if (datetype == SYB5BIGTIME) {
3243 24 : TDS_UINT8 bigtime = *((const TDS_BIGTIME *) di);
3244 24 : dt_days = 0;
3245 24 : dms = bigtime % 1000000u * 10u;
3246 24 : dt_time = (bigtime / 1000000u) % 86400u;
3247 24 : secs = dt_time % 60;
3248 24 : dt_time = dt_time / 60u;
3249 24 : } else if (datetype == SYB5BIGDATETIME) {
3250 24 : TDS_UINT8 bigdatetime = *((const TDS_BIGDATETIME*) di);
3251 24 : dms = bigdatetime % 1000000u * 10u;
3252 24 : bigdatetime /= 1000000u;
3253 24 : secs = bigdatetime % 60u;
3254 24 : bigdatetime /= 60u;
3255 24 : dt_time = bigdatetime % (24u*60u);
3256 24 : dt_days = bigdatetime / (24u*60u) - BIGDATETIME_BIAS;
3257 : } else {
3258 : return TDS_FAIL;
3259 : }
3260 :
3261 : /*
3262 : * -53690 is minimun (1753-1-1) (Gregorian calendar start in 1732)
3263 : * 2958463 is maximun (9999-12-31)
3264 : */
3265 3810 : l = dt_days + (146038 + 146097*4);
3266 3810 : wday = (l + 4) % 7;
3267 3810 : n = (4 * l) / 146097; /* n century */
3268 3810 : l = l - (146097 * n + 3) / 4; /* days from xx00-02-28 (y-m-d) */
3269 3810 : i = (4000 * (l + 1)) / 1461001; /* years from xx00-02-28 */
3270 3810 : l = l - (1461 * i) / 4; /* year days from xx00-02-28 */
3271 3810 : ydays = l >= 306 ? l - 305 : l + 60;
3272 3810 : l += 31;
3273 3810 : j = (80 * l) / 2447;
3274 3810 : days = l - (2447 * j) / 80;
3275 3810 : l = j / 11;
3276 3810 : months = j + 1 - 12 * l;
3277 3810 : years = 100 * (n - 1) + i + l;
3278 3810 : if (l == 0 && (years & 3) == 0 && (years % 100 != 0 || years % 400 == 0))
3279 496 : ++ydays;
3280 :
3281 3810 : hours = dt_time / 60;
3282 3810 : mins = dt_time % 60;
3283 :
3284 3810 : dr->year = years;
3285 3810 : dr->month = months;
3286 3810 : dr->quarter = months / 3;
3287 3810 : dr->day = days;
3288 3810 : dr->dayofyear = ydays;
3289 3810 : dr->weekday = wday;
3290 3810 : dr->hour = hours;
3291 3810 : dr->minute = mins;
3292 3810 : dr->second = secs;
3293 3810 : dr->decimicrosecond = dms;
3294 3810 : dr->timezone = tzone;
3295 3810 : return TDS_SUCCESS;
3296 : }
3297 :
3298 : /**
3299 : * \brief convert a number in string to TDS_INT
3300 : *
3301 : * \return TDS_CONVERT_* or failure code on error
3302 : * \remarks Sybase's char->int conversion tolerates embedded blanks,
3303 : * such that "convert( int, ' - 13 ' )" works.
3304 : * If we find blanks, we copy the string to a temporary buffer,
3305 : * skipping the blanks.
3306 : * We return the results of atoi() with a clean string.
3307 : *
3308 : * n.b. it is possible to embed all sorts of non-printable characters, but we
3309 : * only check for spaces. at this time, no one on the project has tested anything else.
3310 : */
3311 : static TDS_INT
3312 387528 : string_to_int(const char *buf, const char *pend, TDS_INT * res)
3313 : {
3314 : bool negative;
3315 : unsigned int num; /* we use unsigned here for best overflow check */
3316 : size_t digits, decimals;
3317 :
3318 387528 : buf = parse_numeric(buf, pend, &negative, &digits, &decimals);
3319 387528 : if (!buf)
3320 : return TDS_CONVERT_SYNTAX;
3321 :
3322 : num = 0;
3323 2424896 : for (; digits; --digits, ++buf) {
3324 : /* add a digit to number and check for overflow */
3325 : /* NOTE I didn't forget a digit, I check overflow before multiply to prevent overflow */
3326 2566776 : if (num > 214748364u)
3327 : return TDS_CONVERT_OVERFLOW;
3328 2424896 : num = num * 10u + (*buf - '0');
3329 : }
3330 :
3331 : /* check for overflow and convert unsigned to signed */
3332 245208 : if (negative) {
3333 110754 : if (num > 2147483648u)
3334 : return TDS_CONVERT_OVERFLOW;
3335 109186 : *res = 0 - num;
3336 : } else {
3337 134454 : if (num >= 2147483648u)
3338 : return TDS_CONVERT_OVERFLOW;
3339 131966 : *res = num;
3340 : }
3341 :
3342 : return sizeof(TDS_INT);
3343 : }
3344 :
3345 : /**
3346 : * \brief convert a number in string to TDS_INT8
3347 : *
3348 : * \return TDS_CONVERT_* or failure code on error
3349 : */
3350 : static TDS_INT /* copied from string_ti_int and modified */
3351 363008 : parse_int8(const char *buf, const char *pend, TDS_UINT8 * res, bool * p_negative)
3352 : {
3353 : TDS_UINT8 num;
3354 : size_t digits, decimals;
3355 :
3356 363008 : buf = parse_numeric(buf, pend, p_negative, &digits, &decimals);
3357 363008 : if (!buf)
3358 : return TDS_CONVERT_SYNTAX;
3359 :
3360 : num = 0;
3361 3326664 : for (; digits; --digits, ++buf) {
3362 : /* add a digit to number and check for overflow */
3363 3335720 : TDS_UINT8 prev = num;
3364 3335720 : if (num > (((TDS_UINT8) 1u) << 63) / 5u)
3365 : return TDS_CONVERT_OVERFLOW;
3366 3330104 : num = num * 10u + (*buf - '0');
3367 3330104 : if (num < prev)
3368 : return TDS_CONVERT_OVERFLOW;
3369 : }
3370 :
3371 353656 : *res = num;
3372 353656 : return sizeof(TDS_INT8);
3373 : }
3374 :
3375 : /**
3376 : * \brief convert a number in string to TDS_INT8
3377 : *
3378 : * \return TDS_CONVERT_* or failure code on error
3379 : */
3380 : static TDS_INT /* copied from string_ti_int and modified */
3381 285608 : string_to_int8(const char *buf, const char *pend, TDS_INT8 * res)
3382 : {
3383 : TDS_UINT8 num;
3384 : TDS_INT parse_res;
3385 : bool negative;
3386 :
3387 285608 : parse_res = parse_int8(buf, pend, &num, &negative);
3388 285608 : if (parse_res < 0)
3389 : return parse_res;
3390 :
3391 : /* check for overflow and convert unsigned to signed */
3392 279376 : if (negative) {
3393 127856 : if (num > (((TDS_UINT8) 1) << 63))
3394 : return TDS_CONVERT_OVERFLOW;
3395 119336 : *res = 0 - num;
3396 : } else {
3397 151520 : if (num >= (((TDS_UINT8) 1) << 63))
3398 : return TDS_CONVERT_OVERFLOW;
3399 141856 : *res = num;
3400 : }
3401 : return sizeof(TDS_INT8);
3402 : }
3403 :
3404 : /**
3405 : * \brief convert a number in string to TDS_UINT8
3406 : *
3407 : * \return TDS_CONVERT_* or failure code on error
3408 : */
3409 : static TDS_INT /* copied from string_to_int8 and modified */
3410 77400 : string_to_uint8(const char *buf, const char *pend, TDS_UINT8 * res)
3411 : {
3412 : TDS_UINT8 num;
3413 : TDS_INT parse_res;
3414 : bool negative;
3415 :
3416 77400 : parse_res = parse_int8(buf, pend, &num, &negative);
3417 77400 : if (parse_res < 0)
3418 : return parse_res;
3419 :
3420 : /* check for overflow */
3421 74280 : if (negative && num)
3422 : return TDS_CONVERT_OVERFLOW;
3423 :
3424 40120 : *res = num;
3425 40120 : return sizeof(TDS_UINT8);
3426 : }
3427 :
3428 : /**
3429 : * Parse a string for numbers.
3430 : *
3431 : * Syntax can be something like " *[+-] *[0-9]*\.[0-9]* *".
3432 : *
3433 : * The function ignore all spaces. It strips leading zeroes which could
3434 : * possibly lead to overflow.
3435 : * The function returns a pointer to the integer part followed by *p_digits
3436 : * digits followed by a dot followed by *p_decimals digits (dot and
3437 : * fractional digits are optional, in this case *p_decimals is 0).
3438 : *
3439 : * @param buf start of string
3440 : * @param pend pointer to string end
3441 : * @param p_negative store if number is negative
3442 : * @param p_digits store number of integer digits
3443 : * @param p_decimals store number of fractional digits
3444 : * @return pointer to first not zero digit. If NULL this indicate a syntax
3445 : * error.
3446 : */
3447 : static const char *
3448 994784 : parse_numeric(const char *buf, const char *pend, bool *p_negative, size_t *p_digits, size_t *p_decimals)
3449 : {
3450 : enum { blank = ' ' };
3451 : #define SKIP_IF(cond) while (p != pend && (cond)) ++p;
3452 : const char *p, *start;
3453 994784 : bool negative = false;
3454 :
3455 994784 : *p_decimals = 0;
3456 994784 : p = buf;
3457 :
3458 : /* ignore leading spaces */
3459 994784 : SKIP_IF(*p == blank);
3460 994784 : if (p == pend) {
3461 400 : *p_negative = false;
3462 400 : *p_digits = 0;
3463 400 : return p;
3464 : }
3465 :
3466 : /* check for sign */
3467 994384 : switch (*p) {
3468 455490 : case '-':
3469 455490 : negative = true;
3470 : /* fall thru */
3471 455626 : case '+':
3472 : /* skip spaces between sign and number */
3473 455626 : ++p;
3474 455626 : SKIP_IF(*p == blank);
3475 : break;
3476 : }
3477 994384 : *p_negative = negative;
3478 :
3479 : /* a digit must be present */
3480 994384 : if (p == pend)
3481 : return NULL;
3482 :
3483 : /*
3484 : * skip leading zeroes
3485 : * Not skipping them cause numbers like "000000000000" to
3486 : * appear like overflow
3487 : */
3488 7840 : SKIP_IF(*p == '0');
3489 :
3490 : start = p;
3491 8673376 : SKIP_IF(TDS_ISDIGIT(*p));
3492 994256 : *p_digits = p - start;
3493 :
3494 : /* parse decimal part */
3495 994256 : if (p != pend && *p == '.') {
3496 2976 : const char *decimals_start = ++p;
3497 2976 : SKIP_IF(TDS_ISDIGIT(*p));
3498 2976 : *p_decimals = p - decimals_start;
3499 : }
3500 :
3501 : /* check for trailing spaces */
3502 466 : SKIP_IF(*p == blank);
3503 994256 : if (p != pend)
3504 : return NULL;
3505 :
3506 993616 : return start;
3507 : }
3508 :
3509 : static TDS_INT
3510 143672 : string_to_float(const TDS_CHAR * src, TDS_UINT srclen, int desttype, CONV_RESULT * cr)
3511 : {
3512 : char tmpstr[128];
3513 : char *end;
3514 : double res;
3515 :
3516 : /* ignore leading spaces */
3517 287344 : while (srclen > 0 && src[0] == ' ')
3518 0 : ++src, --srclen;
3519 :
3520 : /* ignore trailing blanks and nulls */
3521 143672 : while (srclen > 0 && (src[srclen - 1] == ' ' || src[srclen - 1] == '\0'))
3522 : --srclen;
3523 :
3524 143672 : if (srclen >= sizeof(tmpstr))
3525 : return TDS_CONVERT_OVERFLOW;
3526 :
3527 143672 : memcpy(tmpstr, src, srclen);
3528 143672 : tmpstr[srclen] = 0;
3529 :
3530 143672 : errno = 0;
3531 143672 : res = strtod(tmpstr, &end);
3532 143672 : if (errno == ERANGE)
3533 : return TDS_CONVERT_OVERFLOW;
3534 143672 : if (end != tmpstr + srclen)
3535 : return TDS_CONVERT_SYNTAX;
3536 :
3537 143672 : if (desttype == SYBREAL) {
3538 : /* FIXME check overflows */
3539 71832 : cr->r = (TDS_REAL)res;
3540 71832 : return sizeof(TDS_REAL);
3541 : }
3542 71840 : cr->f = res;
3543 71840 : return sizeof(TDS_FLOAT);
3544 : }
3545 :
3546 : /** @} */
|