LCOV - code coverage report
Current view: top level - src/tds - convert.c (source / functions) Hit Total Coverage
Test: FreeTDS coverage Lines: 1524 1625 93.8 %
Date: 2026-03-02 06:50:21 Functions: 50 52 96.2 %

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

Generated by: LCOV version 1.13