convert.c
上传用户:yhdzpy8989
上传日期:2007-06-13
资源大小:13604k
文件大小:77k
源码类别:

生物技术

开发平台:

C/C++

  1. /*
  2.  * ===========================================================================
  3.  * PRODUCTION $Log: convert.c,v $
  4.  * PRODUCTION Revision 1000.1  2003/11/17 22:20:23  gouriano
  5.  * PRODUCTION PRODUCTION: UPGRADED [ORIGINAL] Dev-tree R1.2
  6.  * PRODUCTION
  7.  * ===========================================================================
  8.  */
  9. /* FreeTDS - Library of routines accessing Sybase and Microsoft databases
  10.  * Copyright (C) 1998-1999  Brian Bruns
  11.  *
  12.  * This library is free software; you can redistribute it and/or
  13.  * modify it under the terms of the GNU Library General Public
  14.  * License as published by the Free Software Foundation; either
  15.  * version 2 of the License, or (at your option) any later version.
  16.  *
  17.  * This library is distributed in the hope that it will be useful,
  18.  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  19.  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
  20.  * Library General Public License for more details.
  21.  *
  22.  * You should have received a copy of the GNU Library General Public
  23.  * License along with this library; if not, write to the
  24.  * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
  25.  * Boston, MA 02111-1307, USA.
  26.  */
  27. #include <tds_config.h>
  28. #include "tdsutil.h"
  29. #include "tds.h"
  30. #include "tdsconvert.h"
  31. # include <time.h>
  32. #include <assert.h>
  33. #include <errno.h>
  34. #ifdef DMALLOC
  35. #include <dmalloc.h>
  36. #endif
  37. #include <string.h>
  38. #ifndef HAVE_ATOLL
  39. static long int
  40. atoll(const char *nptr)
  41. {
  42. return atol(nptr);
  43. }
  44. #endif
  45. #ifdef NCBI_FTDS
  46. extern const int g__numeric_bytes_per_prec[];
  47. extern char *tds_money_to_string(TDS_MONEY *money, char *s);
  48. #define TDS_VECTOR_SIZE(x) (sizeof(x)/sizeof(x[0]))
  49. #endif
  50. static char  software_version[]   = "$Id: convert.c,v 1000.1 2003/11/17 22:20:23 gouriano Exp $";
  51. static void *no_unused_var_warn[] = {software_version,
  52.                                      no_unused_var_warn};
  53. typedef unsigned short utf16_t;
  54. static TDS_INT tds_convert_int1(int srctype, const TDS_CHAR *src, int desttype, CONV_RESULT *cr);
  55. static TDS_INT tds_convert_int2(int srctype, const TDS_CHAR *src, int desttype, CONV_RESULT *cr);
  56. static TDS_INT tds_convert_int4(int srctype, const TDS_CHAR *src, int desttype, CONV_RESULT *cr);
  57. static TDS_INT tds_convert_int8(int srctype, const TDS_CHAR *src, int desttype, CONV_RESULT *cr);
  58. static int  string_to_datetime(const char *datestr, int desttype, CONV_RESULT *cr );
  59. #define test_alloc(x) {if ((x)==NULL) return TDS_CONVERT_NOMEM;}
  60. #define IS_TINYINT(x) ( 0 <= (x) && (x) <= 0xff )
  61. #define IS_SMALLINT(x) ( -32768 <= (x) && (x) <= 32767 )
  62. /* f77: I don't write -2147483648, some compiler seem to have some problem 
  63.  * with this constant although is a valid 32bit value */
  64. #define IS_INT(x) ( (-2147483647l-1l) <= (x) && (x) <= 2147483647l )
  65. /**
  66.  * defgroup convert Conversion
  67.  */
  68. /** addtogroup convert
  69.  *  @{ 
  70.  */
  71. /**
  72.  * convert a number in string to a TDSNUMERIC
  73.  * @return sizeof(TDS_NUMERIC) on success, TDS_CONVERT_* failure code on failure 
  74.  */
  75. static int string_to_numeric(const char *instr, const char *pend, CONV_RESULT *cr);
  76. /**
  77.  * convert a zero terminated string to NUMERIC
  78.  * @return sizeof(TDS_NUMERIC) on success, TDS_CONVERT_* failure code on failure 
  79.  */
  80. static int stringz_to_numeric(const char *instr, CONV_RESULT *cr);
  81. /**
  82.  * convert a number in string to TDS_INT 
  83.  * @return TDS_CONVERT_* failure code if failure
  84.  */
  85. static TDS_INT string_to_int(const char *buf,const char *pend,TDS_INT* res);
  86. #define TDS_CONVERT_NOAVAIL -2
  87. /**
  88.  * convert a number in string to TDS_INT8
  89.  * @return TDS_CONVERT_* failure code if failure
  90.  */
  91. static TDS_INT string_to_int8(const char *buf,const char *pend,TDS_INT8* res);
  92. static int store_hour(char *, char *, struct tds_time *);
  93. static int store_time(char *, struct tds_time * );
  94. static int store_yymmdd_date(char *, struct tds_time *);
  95. static int store_monthname(char *, struct tds_time *);
  96. static int store_numeric_date(char *, struct tds_time *);
  97. static int store_mday(char *, struct tds_time *);
  98. static int store_year(int,  struct tds_time *);
  99. /* static int days_this_year (int years); */
  100. static int is_timeformat(char *);
  101. static int is_numeric(char *);
  102. static int is_alphabetic(char *);
  103. static int is_ampm(char *);
  104. static int is_monthname(char *);
  105. static int is_numeric_dateformat(char *);
  106. #if 0
  107. static TDS_UINT utf16len(const utf16_t* s);
  108. static const char *tds_prtype(int token);
  109. #endif
  110. /**
  111.  * Return type suitable for conversions (convert all nullable types to 
  112.  * fixed type)
  113.  * @param srctype type to convert
  114.  * @param colsize size of type
  115.  * @result type for conversion
  116.  */
  117. int tds_get_conversion_type(int srctype, int colsize)
  118. {
  119. switch(srctype)
  120. {
  121. case SYBINTN:
  122. switch(colsize) {
  123. case 8: return SYBINT8;
  124. case 4: return SYBINT4;
  125. case 2: return SYBINT2;
  126. case 1: return SYBINT1;
  127. }
  128. break;
  129. case SYBFLTN:
  130. switch(colsize) {
  131. case 8: return SYBFLT8;
  132. case 4: return SYBREAL;
  133. }
  134. break;
  135. case SYBDATETIMN:
  136. switch(colsize) {
  137. case 8: return SYBDATETIME;
  138. case 4: return SYBDATETIME4;
  139. }
  140. break;
  141. case SYBMONEYN:
  142. switch(colsize) {
  143. case 8: return SYBMONEY;
  144. case 4: return SYBMONEY4;
  145. }
  146. break;
  147. /* altough tds_conmvert handle SYBBITN other routine use this 
  148.  * function to retrieve not variant type */
  149. case SYBBITN:
  150. return SYBBIT;
  151. break;
  152. }
  153. return srctype;
  154. }
  155. /**
  156.  * Copy a terminated string to result and return len or TDS_CONVERT_NOMEM
  157.  */
  158. static TDS_INT 
  159. string_to_result(const char* s,CONV_RESULT* cr)
  160. {
  161. int len = strlen(s);
  162. cr->c = (TDS_CHAR *) malloc(len + 1);
  163. test_alloc(cr->c);
  164. memcpy(cr->c, s, len + 1);
  165. return len;
  166. }
  167. /**
  168.  * Copy binary data to to result and return len or TDS_CONVERT_NOMEM
  169.  */
  170. static TDS_INT
  171. binary_to_result(const void* data,size_t len,CONV_RESULT* cr)
  172. {
  173. cr->ib = (TDS_CHAR *) malloc(len);
  174. test_alloc(cr->ib);
  175. memcpy(cr->ib, data, len);
  176. return len;
  177. }
  178. /* TODO implement me */
  179. /*
  180. static TDS_INT 
  181. tds_convert_ntext(int srctype,TDS_CHAR *src,TDS_UINT srclen,
  182.       int desttype, CONV_RESULT *cr)
  183. {
  184.       return TDS_CONVERT_NOAVAIL;
  185. }
  186. */
  187. static TDS_INT 
  188. tds_convert_binary(int srctype, const TDS_UCHAR *src, TDS_INT srclen,
  189. int desttype, CONV_RESULT *cr)
  190. {
  191. int cplen;
  192. int s;
  193. char *c;
  194. char hex2[3];
  195.    switch(desttype) {
  196.       case SYBCHAR:
  197.       case SYBVARCHAR:
  198.       case SYBTEXT:
  199.  /* NOTE: Do not prepend 0x to string.  
  200.   * The libraries all expect a bare string, without a 0x prefix. 
  201.   * Applications such as isql and query analyzer provide the "0x" prefix. */
  202.          /* 2 * source length + 1 for terminator */
  203.          cr->c = (TDS_CHAR *) malloc((srclen * 2) + 1);
  204. test_alloc(cr->c);
  205.          c = cr->c;
  206.          for (s = 0; s < srclen; s++) {
  207.              sprintf(hex2, "%02x", src[s]);
  208.              *c++ = hex2[0];
  209.              *c++ = hex2[1];
  210.          }
  211.          *c = '';
  212.          return (srclen * 2);
  213.          break;
  214.       case SYBIMAGE:
  215.       case SYBBINARY:
  216.       case SYBVARBINARY:
  217.  return binary_to_result(src, srclen, cr);
  218.          break;
  219. case SYBINT1:
  220. case SYBINT2:
  221. case SYBINT4:
  222. case SYBINT8:
  223. case SYBMONEY4:
  224. case SYBMONEY:
  225. case SYBREAL:
  226. case SYBFLT8:
  227. cplen = get_size_by_type(desttype);
  228. if (cplen <= srclen)
  229. return binary_to_result(src, cplen, cr);
  230. cr->ib = (TDS_CHAR *) malloc(cplen);
  231. test_alloc(cr->ib);
  232. memcpy(cr->ib, src, srclen);
  233. memset(cr->ib+srclen, 0, cplen-srclen);
  234. return cplen;
  235. break;
  236. /* conversions not allowed */
  237. case SYBDATETIME4:
  238. case SYBDATETIME:
  239. case SYBDATETIMN:
  240. /* TODO should we do some test for these types or work as ints ?? */
  241. case SYBDECIMAL:
  242. case SYBNUMERIC:
  243. case SYBBIT:
  244. case SYBBITN:
  245. default:
  246. return TDS_CONVERT_NOAVAIL;
  247. break;
  248.    }
  249. #ifndef NCBI_FTDS
  250.    return TDS_CONVERT_FAIL;
  251. #endif
  252. }
  253. static TDS_INT 
  254. tds_convert_char(int srctype, const TDS_CHAR *src, TDS_UINT srclen,
  255. int desttype, CONV_RESULT *cr)
  256. {
  257. int           i, j;
  258. unsigned char hex1;
  259. TDS_INT8     mymoney;
  260. TDS_INT      mymoney4;
  261. char         mynumber[39];
  262. const char *ptr, *pend;
  263. int point_found, places;
  264. TDS_INT tds_i;
  265. TDS_INT8 tds_i8;
  266. TDS_INT rc;
  267.    
  268.    switch(desttype) {
  269.       case SYBCHAR:
  270.       case SYBVARCHAR:
  271.       case SYBTEXT:
  272.  cr->c = (TDS_CHAR *) malloc(srclen + 1);
  273. test_alloc(cr->c);
  274.  memcpy(cr->c, src, srclen);
  275.  cr->c[srclen] = 0;
  276.          return srclen; 
  277.  break;
  278. case SYBBINARY:
  279. case SYBIMAGE:
  280. case SYBVARBINARY:
  281.          /* skip leading "0x" or "0X" */
  282.          if (src[0] == '0' && ( src[1] == 'x' || src[1] == 'X' )) {
  283.             src += 2;
  284.             srclen -= 2;
  285.          }
  286. /* ignore trailing blanks and nulls */
  287. /* FIXME is good to ignore null ?? */
  288. while( srclen > 0 && (src[srclen-1] == ' ' || src[srclen-1] == '') )
  289. --srclen;
  290.          /* a binary string output will be half the length of */
  291.          /* the string which represents it in hexadecimal     */
  292. /* if srclen if odd we must add a "0" before ... */
  293. j = 0; /* number where to start converting */
  294. if (srclen & 1) {
  295. ++srclen; j = 1; --src;
  296. }
  297.         cr->ib = (TDS_CHAR *) malloc(srclen / 2);
  298. test_alloc(cr->ib);
  299. #if 0
  300.          /* hey, I know this looks a bit cruddy,   */
  301.          /* and I'm sure it can all be done in one */
  302.          /* statement, so go on, make my day!      */
  303.          for ( i = 0, j = 0; i < srclen; i++, j++ ) {
  304.             inp = src[i];
  305.             if ( inp > 47 && inp < 58 )            /* '0' thru '9' */
  306.                hex1 = inp - 48;
  307.             else if ( inp > 96 && inp < 103 )      /* 'a' thru 'f' */
  308.                      hex1 = inp - 87;
  309.                  else if ( inp > 64 && inp < 71 )  /* 'A' thru 'F' */
  310.                           hex1 = inp - 55;
  311.                       else {
  312.                           fprintf(stderr,"error_handler:  Attempt to convert data stopped by syntax error in source field n");
  313.                           return;
  314.                       }
  315.       
  316.             hex1 = hex1 << 4;
  317.       
  318.             i++;
  319.       
  320.             inp = src[i];
  321.             if ( inp > 47 && inp < 58 )            /* '0' thru '9' */
  322.                hex1 = hex1  | (inp - 48);
  323.             else if ( inp > 96 && inp < 103 )      /* 'a' thru 'f' */
  324.                      hex1 = hex1 | (inp - 87);
  325.                  else if ( inp > 64 && inp < 71 )  /* 'A' thru 'F' */
  326.                           hex1 =  hex1 | (inp - 55);
  327.                       else {
  328.                           fprintf(stderr,"error_handler:  Attempt to convert data stopped by syntax error in source field n");
  329.                           return;
  330.                       }
  331.       
  332.             cr->ib[j] = hex1;
  333.          }
  334. #else
  335. for ( i=srclen; --i >= j; ) {
  336. hex1 = src[i];
  337. if( '0' <= hex1 && hex1 <= '9' )
  338. hex1 &= 0x0f;
  339. else {
  340. hex1 &= 0x20 ^ 0xff; /* mask off 0x20 to ensure upper case */
  341. if( 'A' <= hex1 && hex1 <= 'F' ) {
  342. hex1 -= ('A'-10);
  343. } else {
  344. tdsdump_log(TDS_DBG_INFO1,"error_handler:  attempt to convert data stopped by syntax error in source field n");
  345. return TDS_CONVERT_SYNTAX;
  346. }
  347. }
  348. assert( hex1 < 0x10 );
  349. if( i & 1 ) 
  350. cr->ib[i/2] = hex1;
  351. else
  352. cr->ib[i/2] |= hex1 << 4;
  353. }
  354. #endif
  355.          return srclen / 2;
  356.          break;
  357.       case SYBINT1:
  358. if ((rc = string_to_int(src, src + srclen, &tds_i)) < 0)
  359. return rc;
  360. if (!IS_TINYINT(tds_i))
  361. return TDS_CONVERT_OVERFLOW;
  362. cr->ti = tds_i;
  363. return sizeof(TDS_TINYINT);
  364.           break;
  365.       case SYBINT2:
  366. if ((rc = string_to_int(src, src + srclen, &tds_i)) < 0)
  367. return rc;
  368. if (!IS_SMALLINT(tds_i))
  369. return TDS_CONVERT_OVERFLOW;
  370. cr->si = tds_i;
  371. return sizeof(TDS_SMALLINT);
  372.           break;
  373.       case SYBINT4:
  374. if ((rc = string_to_int(src, src + srclen, &tds_i)) < 0)
  375. return rc;
  376. cr->i = tds_i;
  377. return sizeof(TDS_INT);
  378. break;
  379. case SYBINT8:
  380. if ((rc = string_to_int8(src, src + srclen, &tds_i8)) < 0)
  381. return rc;
  382. cr->bi = tds_i8;
  383. return sizeof(TDS_INT8);
  384. break;
  385. case SYBFLT8:
  386. cr->f = atof(src);
  387. return sizeof(TDS_FLOAT);
  388. break;
  389.       case SYBREAL:
  390.           cr->r = atof(src);
  391. return sizeof(TDS_REAL);
  392.           break;
  393.       case SYBBIT:
  394.       case SYBBITN:
  395. if ((rc = string_to_int(src, src + srclen, &tds_i)) < 0)
  396. return TDS_CONVERT_OVERFLOW;
  397. cr->ti = tds_i ? 1 : 0;
  398. return sizeof(TDS_TINYINT);
  399. break;
  400.       case SYBMONEY:
  401.       case SYBMONEY4:
  402. /* TODO code similar to string_to_numeric... */
  403. i           = 0;
  404. places      = 0;
  405. point_found = 0;
  406. pend        = src + srclen;
  407. /* skip leading blanks */
  408. for (ptr = src; ptr != pend && *ptr == ' '; ++ptr);
  409. switch ( ptr != pend ? *ptr : 0 ) {
  410. case '-':
  411. mynumber[i++] = '-';
  412. /* fall through*/
  413. case '+':
  414. ptr++;
  415. for (; ptr != pend && *ptr == ' '; ++ptr);
  416. break;
  417. }
  418. for(; ptr != pend; ptr++)                      /* deal with the rest */
  419. {
  420. if (isdigit((unsigned char) *ptr) )                   /* it's a number */
  421. {
  422. /* no more than 4 decimal digits */
  423. if (places < 4)
  424. mynumber[i++] = *ptr;
  425. /* assure not buffer overflow */
  426. if (i==30) return TDS_CONVERT_OVERFLOW;
  427. if (point_found) {                 /* if we passed a decimal point */
  428. /* count digits after that point  */
  429. ++places;
  430. }
  431. }
  432. else if (*ptr == '.')                /* found a decimal point */
  433. {
  434. if (point_found)             /* already had one. error */
  435. return TDS_CONVERT_SYNTAX;
  436. point_found = 1;
  437. }
  438. else                            /* first invalid character */
  439. return TDS_CONVERT_SYNTAX;   /* lose the rest.          */
  440. }
  441. for ( j = places; j < 4; j++ )
  442. mynumber[i++] = '0';
  443. mynumber[i] = 0;
  444.  /* FIXME overflow not handled */
  445.          if (desttype == SYBMONEY) {
  446.             mymoney = atoll(mynumber);
  447.             memcpy(&(cr->m), &mymoney, sizeof(TDS_MONEY) ); 
  448.             return sizeof(TDS_MONEY);
  449.          } else {
  450.             mymoney4 = atol(mynumber);
  451.             memcpy(&(cr->m4), &mymoney4, sizeof(TDS_MONEY4) ); 
  452.             return sizeof(TDS_MONEY4);
  453.          }
  454.          break;
  455.       case SYBDATETIME:
  456.  return string_to_datetime(src, SYBDATETIME, cr);
  457.  break;
  458.       case SYBDATETIME4:
  459.  return string_to_datetime(src, SYBDATETIME4, cr);
  460.  break;
  461.       case SYBNUMERIC:
  462.       case SYBDECIMAL:
  463. return string_to_numeric(src, src+srclen, cr);
  464. break;
  465.  case SYBUNIQUE: {
  466. unsigned n = 0;
  467. char c;
  468.  /* parse formats like XXXXXXXX-XXXX-XXXX-XXXXXXXXXXXXXXXX 
  469.   * or {XXXXXXXX-XXXX-XXXX-XXXXXXXXXXXXXXXX} 
  470.   * SQL seem to ignore additional character... */
  471. if (srclen < (32+3)) return TDS_CONVERT_SYNTAX;
  472. if (src[0] == '{') {
  473. if (srclen < (32+5) || src[32+4] != '}')
  474. return TDS_CONVERT_SYNTAX;
  475. ++src;
  476. }
  477. if (src[8] != '-' || src[8+4+1] != '-' || src[16+2] != '-')
  478. return TDS_CONVERT_SYNTAX;
  479. /* test all characters and get value 
  480.  * first I tried using sscanf but it work if number terminate
  481.  * with less digits */
  482. for(i = 0; i < 32+3; ++i) {
  483. c = src[i];
  484. switch(i) {
  485. case 8:
  486. if (c!='-') return TDS_CONVERT_SYNTAX;
  487. cr->u.Data1 = n;
  488. n = 0;
  489. break;
  490. case 8+4+1:
  491. if (c!='-') return TDS_CONVERT_SYNTAX;
  492. cr->u.Data2 = n;
  493. n = 0;
  494. break;
  495. case 16+2:
  496. if (c!='-') return TDS_CONVERT_SYNTAX;
  497. cr->u.Data3 = n;
  498. n = 0;
  499. break;
  500. default:
  501. n = n << 4;
  502. if (c >= '0' && c <= '9') n += c-'0';
  503. else {
  504. c &= 0x20 ^ 0xff;
  505. if (c >= 'A' && c <= 'F')
  506. n += c-('A'-10);
  507. else return TDS_CONVERT_SYNTAX;
  508. }
  509. if (i>(16+2) && !(i&1)) {
  510. cr->u.Data4[(i>>1)-10] = n;
  511. n = 0;
  512. }
  513. }
  514. }
  515.  }
  516.  return sizeof(TDS_UNIQUE);
  517.  default:
  518. return TDS_CONVERT_NOAVAIL;
  519. break;
  520. } /* end switch */
  521. } /* tds_convert_char */
  522. static TDS_INT 
  523. tds_convert_bit(int srctype, const TDS_CHAR *src,
  524. int desttype, CONV_RESULT *cr)
  525. {
  526. int canonic = src[0] ? 1 : 0;
  527. switch(desttype) {
  528. case SYBCHAR:
  529. case SYBVARCHAR:
  530. case SYBTEXT:
  531. cr->c = (TDS_CHAR *) malloc(2);
  532. test_alloc(cr->c);
  533. cr->c[0] = '0' + canonic;
  534. cr->c[1] = 0;
  535. return 1;
  536. break;
  537. case SYBBINARY:
  538. case SYBIMAGE:
  539. case SYBVARBINARY:
  540. return binary_to_result(src,1,cr);
  541. break;
  542. case SYBINT1:
  543. cr->ti = canonic;
  544. return sizeof(TDS_TINYINT);
  545. break;
  546. case SYBINT2:
  547. cr->si = canonic;
  548. return sizeof(TDS_SMALLINT);
  549. break;
  550. case SYBINT4:
  551. cr->i = canonic;
  552. return sizeof(TDS_INT);
  553. break;
  554. case SYBINT8:
  555. cr->bi = canonic;
  556. return sizeof(TDS_INT8);
  557. break;
  558. case SYBFLT8:
  559. cr->f = canonic;
  560. return sizeof(TDS_FLOAT);
  561. break;
  562. case SYBREAL:
  563. cr->r = (TDS_REAL) canonic;
  564. return sizeof(TDS_REAL);
  565. break;
  566. case SYBBIT:
  567. case SYBBITN:
  568. cr->ti = src[0];
  569. return sizeof(TDS_TINYINT);
  570. break;
  571. case SYBMONEY:
  572. case SYBMONEY4:
  573. return tds_convert_int1( SYBINT1, (src[0])? "1" : "", desttype, cr);
  574. break;
  575. case SYBNUMERIC:
  576. case SYBDECIMAL:
  577. return stringz_to_numeric(canonic ? "1" : "0",cr);
  578. break;
  579. /* conversions not allowed */
  580. case SYBUNIQUE:
  581. case SYBDATETIME4:
  582. case SYBDATETIME:
  583. case SYBDATETIMN:
  584. default:
  585. return TDS_CONVERT_NOAVAIL;
  586. break;
  587. }
  588. #ifndef NCBI_FTDS
  589. return TDS_CONVERT_FAIL;
  590. #endif
  591. }
  592. static TDS_INT 
  593. tds_convert_int1(int srctype, const TDS_CHAR *src,
  594. int desttype, CONV_RESULT *cr)
  595. {
  596. TDS_TINYINT buf;
  597. TDS_CHAR tmp_str[5];
  598. memcpy(&buf, src, sizeof(buf));
  599. switch(desttype) {
  600. case SYBCHAR:
  601. case SYBTEXT:
  602. case SYBVARCHAR:
  603. sprintf(tmp_str,"%d",buf);
  604. return string_to_result(tmp_str,cr);
  605. break;
  606. case SYBBINARY:
  607. case SYBIMAGE:
  608. case SYBVARBINARY:
  609. return binary_to_result(src,1,cr);
  610. break;
  611. case SYBINT1:
  612. cr->ti = buf;
  613. return sizeof(TDS_TINYINT);
  614. break;
  615. case SYBINT2:
  616. cr->si = buf;
  617. return sizeof(TDS_SMALLINT);
  618. break;
  619. case SYBINT4:
  620. cr->i = buf;
  621. return sizeof(TDS_INT);
  622. break;
  623. case SYBINT8:
  624. cr->bi = buf;
  625. return sizeof(TDS_INT8);
  626. break;
  627. case SYBBIT:
  628. case SYBBITN:
  629. cr->ti = buf ? 1 : 0;
  630. return sizeof(TDS_TINYINT);
  631. break;
  632. case SYBFLT8:
  633. cr->f = buf;
  634. return sizeof(TDS_FLOAT);
  635. break;
  636. case SYBREAL:
  637. cr->r = buf;
  638. return sizeof(TDS_REAL);
  639. break;
  640. case SYBMONEY4:
  641. cr->m4.mny4 = buf * 10000;
  642. return sizeof(TDS_MONEY4);
  643. break;
  644. case SYBMONEY:
  645. cr->m.mny = buf * 10000;
  646. return sizeof(TDS_MONEY);
  647. break;
  648. case SYBNUMERIC:
  649. case SYBDECIMAL:
  650. sprintf(tmp_str,"%d",buf);
  651. return stringz_to_numeric(tmp_str,cr);
  652. break;
  653. /* conversions not allowed */
  654. case SYBUNIQUE:
  655. case SYBDATETIME4:
  656. case SYBDATETIME:
  657. case SYBDATETIMN:
  658. default:
  659. return TDS_CONVERT_NOAVAIL;
  660. break;
  661. }
  662. #ifndef NCBI_FTDS
  663. return TDS_CONVERT_FAIL;
  664. #endif
  665. }
  666. static TDS_INT 
  667. tds_convert_int2(int srctype, const TDS_CHAR *src,
  668. int desttype, CONV_RESULT *cr)
  669. {
  670. TDS_SMALLINT buf;
  671. TDS_CHAR tmp_str[16];
  672. memcpy(&buf,src,sizeof(buf));
  673. switch(desttype) {
  674. case SYBCHAR:
  675. case SYBTEXT:
  676. case SYBVARCHAR:
  677. sprintf(tmp_str,"%d",buf);
  678. return string_to_result(tmp_str,cr);
  679. break;
  680. case SYBBINARY:
  681. case SYBIMAGE:
  682. case SYBVARBINARY:
  683. return binary_to_result(src,2,cr);
  684. break;
  685. case SYBINT1:
  686. if (!IS_TINYINT(buf))
  687. return TDS_CONVERT_OVERFLOW;
  688. cr->ti = (TDS_TINYINT) buf;
  689. return sizeof(TDS_TINYINT);
  690. break;
  691. case SYBINT2:
  692. cr->si = buf;
  693. return sizeof(TDS_SMALLINT);
  694. break;
  695. case SYBINT4:
  696. cr->i = buf;
  697. return sizeof(TDS_INT);
  698. break;
  699. case SYBINT8:
  700. cr->bi = buf;
  701. return sizeof(TDS_INT8);
  702. break;
  703. case SYBBIT:
  704. case SYBBITN:
  705. cr->ti = buf ? 1 : 0;
  706. return sizeof(TDS_TINYINT);
  707. break;
  708. case SYBFLT8:
  709. cr->f = buf;
  710. return sizeof(TDS_FLOAT);
  711. break;
  712. case SYBREAL:
  713. cr->r = buf;
  714. return sizeof(TDS_REAL);
  715. break;
  716. case SYBMONEY4:
  717. cr->m4.mny4 = buf * 10000;
  718. return sizeof(TDS_MONEY4);
  719. break;
  720. case SYBMONEY:
  721. cr->m.mny = buf * 10000;
  722. return sizeof(TDS_MONEY);
  723. break;
  724. case SYBNUMERIC:
  725. case SYBDECIMAL:
  726. sprintf(tmp_str,"%d",buf);
  727. return stringz_to_numeric(tmp_str,cr);
  728. break;
  729. /* conversions not allowed */
  730. case SYBUNIQUE:
  731. case SYBDATETIME4:
  732. case SYBDATETIME:
  733. case SYBDATETIMN:
  734. default:
  735. return TDS_CONVERT_NOAVAIL;
  736. break;
  737. }
  738. #ifndef NCBI_FTDS
  739. return TDS_CONVERT_FAIL;
  740. #endif
  741. }
  742. static TDS_INT 
  743. tds_convert_int4(int srctype, const TDS_CHAR *src,
  744. int desttype, CONV_RESULT *cr)
  745. {
  746. TDS_INT buf;
  747. TDS_CHAR tmp_str[16];
  748. memcpy(&buf,src,sizeof(buf));
  749. switch(desttype) {
  750. case SYBCHAR:
  751. case SYBTEXT:
  752. case SYBVARCHAR:
  753. sprintf(tmp_str,"%d",buf);
  754. return string_to_result(tmp_str,cr);
  755. break;
  756. case SYBBINARY:
  757. case SYBIMAGE:
  758. case SYBVARBINARY:
  759. return binary_to_result(src,4,cr);
  760. break;
  761. case SYBINT1:
  762. if (!IS_TINYINT(buf))
  763. return TDS_CONVERT_OVERFLOW;
  764. cr->ti = buf;
  765. return sizeof(TDS_TINYINT);
  766. break;
  767. case SYBINT2:
  768. if (!IS_SMALLINT(buf))
  769. return TDS_CONVERT_OVERFLOW;
  770. cr->si = buf;
  771. return sizeof(TDS_SMALLINT);
  772. break;
  773. case SYBINT4:
  774. cr->i = buf;
  775. return sizeof(TDS_INT);
  776. break;
  777. case SYBINT8:
  778. cr->bi = buf;
  779. return sizeof(TDS_INT8);
  780. break;
  781. case SYBBIT:
  782. case SYBBITN:
  783. cr->ti = buf ? 1 : 0;
  784. return sizeof(TDS_TINYINT);
  785. break;
  786. case SYBFLT8:
  787. cr->f = buf;
  788. return sizeof(TDS_FLOAT);
  789. break;
  790. case SYBREAL:
  791. cr->r = (TDS_REAL) buf;
  792. return sizeof(TDS_REAL);
  793. break;
  794. case SYBMONEY4:
  795. if (buf > 214748 || buf < -214748)
  796. return TDS_CONVERT_OVERFLOW;
  797. cr->m4.mny4 = buf * 10000;
  798. return sizeof(TDS_MONEY4);
  799. break;
  800. case SYBMONEY:
  801. cr->m.mny = (TDS_INT8)buf * 10000;
  802. return sizeof(TDS_MONEY);
  803. break;
  804. case SYBNUMERIC:
  805. case SYBDECIMAL:
  806. sprintf(tmp_str,"%d",buf);
  807. return stringz_to_numeric(tmp_str,cr);
  808. break;
  809. /* conversions not allowed */
  810. case SYBUNIQUE:
  811. case SYBDATETIME4:
  812. case SYBDATETIME:
  813. case SYBDATETIMN:
  814. default:
  815. return TDS_CONVERT_NOAVAIL;
  816. break;
  817. }
  818. #ifndef NCBI_FTDS
  819. return TDS_CONVERT_FAIL;
  820. #endif
  821. }
  822. static TDS_INT 
  823. tds_convert_int8(int srctype, const TDS_CHAR *src,
  824. int desttype, CONV_RESULT *cr)
  825. {
  826. TDS_INT8 buf;
  827. TDS_CHAR tmp_str[24];
  828. memcpy(&buf,src,sizeof(buf));
  829. switch(desttype) {
  830. case SYBCHAR:
  831. case SYBTEXT:
  832. case SYBVARCHAR:
  833. /* TODO: fix for all platform */
  834. sprintf(tmp_str,"%lld",buf);
  835. return string_to_result(tmp_str,cr);
  836. break;
  837. case SYBBINARY:
  838. case SYBIMAGE:
  839. case SYBVARBINARY:
  840. return binary_to_result(src,8,cr);
  841. break;
  842. case SYBINT1:
  843. if (!IS_TINYINT(buf))
  844. return TDS_CONVERT_OVERFLOW;
  845. cr->ti = (TDS_TINYINT) buf;
  846. return sizeof(TDS_TINYINT);
  847. break;
  848. case SYBINT2:
  849. if (!IS_SMALLINT(buf))
  850. return TDS_CONVERT_OVERFLOW;
  851. cr->si = (TDS_SMALLINT) buf;
  852. return sizeof(TDS_SMALLINT);
  853. break;
  854. case SYBINT4:
  855. if (!IS_INT(buf))
  856. return TDS_CONVERT_OVERFLOW;
  857. cr->i = (TDS_INT) buf;
  858. return sizeof(TDS_INT);
  859. break;
  860. case SYBINT8:
  861. cr->bi = buf;
  862. return sizeof(TDS_INT8);
  863. break;
  864. case SYBBIT:
  865. case SYBBITN:
  866. cr->ti = buf ? 1 : 0;
  867. return sizeof(TDS_TINYINT);
  868. break;
  869. case SYBFLT8:
  870. cr->f = (TDS_FLOAT) buf;
  871. return sizeof(TDS_FLOAT);
  872. break;
  873. case SYBREAL:
  874. cr->r = (TDS_REAL) buf;
  875. return sizeof(TDS_REAL);
  876. break;
  877. case SYBMONEY4:
  878. if (buf > 214748 || buf < -214748)
  879. return TDS_CONVERT_OVERFLOW;
  880. cr->m4.mny4 = (TDS_INT) (buf * 10000);
  881. return sizeof(TDS_MONEY4);
  882. break;
  883. case SYBMONEY:
  884. /* TODO check overflow */
  885. cr->m.mny = buf * 10000;
  886. return sizeof(TDS_MONEY);
  887. break;
  888. case SYBNUMERIC:
  889. case SYBDECIMAL:
  890. /* TODO portability problem */
  891. sprintf(tmp_str,"%lld",buf);
  892. return stringz_to_numeric(tmp_str,cr);
  893. break;
  894. /* conversions not allowed */
  895. case SYBUNIQUE:
  896. case SYBDATETIME4:
  897. case SYBDATETIME:
  898. case SYBDATETIMN:
  899. default:
  900. return TDS_CONVERT_NOAVAIL;
  901. break;
  902. }
  903. #ifndef NCBI_FTDS
  904. return TDS_CONVERT_FAIL;
  905. #endif
  906. }
  907. static TDS_INT 
  908. tds_convert_numeric(int srctype, const TDS_NUMERIC *src, TDS_INT srclen,
  909. int desttype, CONV_RESULT *cr)
  910. {
  911. char tmpstr[MAXPRECISION];
  912. long i;
  913. switch(desttype) {
  914. case SYBCHAR:
  915. case SYBTEXT:
  916. case SYBVARCHAR:
  917. tds_numeric_to_string(src,tmpstr);
  918. return string_to_result(tmpstr,cr);
  919. break;
  920. case SYBBINARY:
  921. case SYBIMAGE:
  922. case SYBVARBINARY:
  923. return binary_to_result(src,sizeof(TDS_NUMERIC),cr);
  924. break;
  925. case SYBINT1:
  926. tds_numeric_to_string(src,tmpstr);
  927. /* TODO what happen if numeric is too big ?? */
  928. i = atoi(tmpstr);
  929. if (!IS_TINYINT(i))
  930. return TDS_CONVERT_OVERFLOW;
  931. cr->ti = (TDS_TINYINT) i;
  932. return sizeof(TDS_TINYINT);
  933. break;
  934. case SYBINT2:
  935. tds_numeric_to_string(src,tmpstr);
  936. i = atoi(tmpstr);
  937. if (!IS_SMALLINT(i))
  938. return TDS_CONVERT_OVERFLOW;
  939. cr->si = (TDS_SMALLINT) i;
  940. return sizeof(TDS_SMALLINT);
  941. break;
  942. case SYBINT4:
  943. tds_numeric_to_string(src,tmpstr);
  944. i = atoi(tmpstr);
  945. if (!IS_INT(i))
  946. return TDS_CONVERT_OVERFLOW;
  947. cr->i = i;
  948. return 4;
  949. break;
  950. case SYBINT8:
  951. tds_numeric_to_string(src,tmpstr);
  952. /* TODO check for overflow */
  953. cr->bi = atoll(tmpstr);
  954. return 8;
  955. break;
  956. case SYBBIT:
  957. case SYBBITN:
  958. cr->ti = 0;
  959. for(i=g__numeric_bytes_per_prec[src->precision]; --i > 0;)
  960. if (src->array[i] != 0) {
  961. cr->ti = 1;
  962. break;
  963. }
  964. return 1;
  965. break;
  966. case SYBNUMERIC:
  967. case SYBDECIMAL:
  968.             memcpy(&(cr->n), src, sizeof(TDS_NUMERIC));
  969.             return sizeof(TDS_NUMERIC);
  970.             break;
  971. case SYBFLT8:
  972.             tds_numeric_to_string(src,tmpstr);
  973.             cr->f = atof(tmpstr);
  974.             return 8;
  975.             break;
  976. case SYBREAL:
  977.             tds_numeric_to_string(src,tmpstr);
  978.             cr->r = atof(tmpstr);
  979.             return 4;
  980.             break;
  981.     /* TODO conversions to money */
  982. /* conversions not allowed */
  983. case SYBUNIQUE:
  984. case SYBDATETIME4:
  985. case SYBDATETIME:
  986. case SYBDATETIMN:
  987. default:
  988. return TDS_CONVERT_NOAVAIL;
  989. break;
  990. }
  991. #ifndef NCBI_FTDS
  992. return TDS_CONVERT_FAIL;
  993. #endif
  994. }
  995. static TDS_INT 
  996. tds_convert_money4(int srctype, const TDS_CHAR *src, int srclen,
  997. int desttype, CONV_RESULT *cr)
  998. {
  999. TDS_MONEY4 mny;
  1000. long dollars, fraction;
  1001. char tmp_str[33];
  1002. memcpy(&mny, src, sizeof(mny));
  1003. switch(desttype) {
  1004. case SYBCHAR:
  1005. case SYBTEXT:
  1006. case SYBVARCHAR:
  1007. /* FIXME should be rounded ??
  1008.  * see also all conversion to int and from money 
  1009.  * rounding with dollars = (mny.mny4 + 5000) /10000
  1010.  * can give arithmetic overflow solution should be
  1011.  * dollars = (mny.mny4/2 + 2500)/5000 */
  1012. dollars  = mny.mny4 / 10000;
  1013. fraction = mny.mny4 % 10000;
  1014. if (fraction < 0) { fraction = -fraction; }
  1015. /* TODO print 4 decimal digits ?? */
  1016. sprintf(tmp_str,"%ld.%02lu",dollars,fraction/100);
  1017. return string_to_result(tmp_str,cr);
  1018. break;
  1019. case SYBBINARY:
  1020. case SYBIMAGE:
  1021. case SYBVARBINARY:
  1022. return binary_to_result(src,sizeof(TDS_MONEY4),cr);
  1023. break;
  1024. case SYBINT1:
  1025. dollars  = mny.mny4 / 10000;
  1026. if (!IS_TINYINT(dollars))
  1027. return TDS_CONVERT_OVERFLOW;
  1028. cr->ti = (TDS_TINYINT) dollars;
  1029. return sizeof(TDS_TINYINT);
  1030. break;
  1031. case SYBINT2:
  1032. dollars  = mny.mny4 / 10000;
  1033. if (!IS_SMALLINT(dollars))
  1034. return TDS_CONVERT_OVERFLOW;
  1035. cr->si = (TDS_SMALLINT) dollars;
  1036. return sizeof(TDS_SMALLINT);
  1037. break;
  1038. case SYBINT4:
  1039. cr->i = mny.mny4 / 10000;
  1040. return sizeof(TDS_INT);
  1041. break;
  1042. case SYBINT8:
  1043. cr->bi = mny.mny4 / 10000;
  1044. return sizeof(TDS_INT8);
  1045. break;
  1046. case SYBBIT:
  1047. case SYBBITN:
  1048. cr->ti = mny.mny4 ? 1 : 0;
  1049. return sizeof(TDS_TINYINT);
  1050. break;
  1051. case SYBFLT8:
  1052. cr->f = ((TDS_FLOAT)mny.mny4) / 10000.0;
  1053. return sizeof(TDS_FLOAT);
  1054. break;
  1055. case SYBREAL:
  1056. cr->r = (TDS_REAL) (mny.mny4 / 10000.0);
  1057. return sizeof(TDS_REAL);
  1058. break;
  1059. case SYBMONEY:
  1060. cr->m.mny = (TDS_INT8)mny.mny4; 
  1061. return sizeof(TDS_MONEY);
  1062. break;
  1063. case SYBMONEY4:
  1064. memcpy(&(cr->m4), src, sizeof(TDS_MONEY4));
  1065. return sizeof(TDS_MONEY4);
  1066. break;
  1067. /* conversions not allowed */
  1068. case SYBUNIQUE:
  1069. case SYBDATETIME4:
  1070. case SYBDATETIME:
  1071. case SYBDATETIMN:
  1072. break;
  1073. case SYBDECIMAL:
  1074. case SYBNUMERIC:
  1075. dollars  = mny.mny4 / 10000;
  1076. fraction = mny.mny4 % 10000;
  1077. if (fraction < 0) { fraction = -fraction; }
  1078. sprintf(tmp_str,"%ld.%04lu",dollars,fraction);
  1079. return stringz_to_numeric(tmp_str,cr);
  1080. default:
  1081. return TDS_CONVERT_NOAVAIL;
  1082. break;
  1083. }
  1084. return TDS_CONVERT_FAIL;
  1085. }
  1086. static TDS_INT 
  1087. tds_convert_money(int srctype, const TDS_CHAR *src,
  1088. int desttype, CONV_RESULT *cr)
  1089. {
  1090. char *s;
  1091. TDS_INT8 mymoney,dollars;
  1092. char tmpstr [64];
  1093.     tdsdump_log(TDS_DBG_FUNC, "%L inside tds_convert_money()n");
  1094. #if defined(WORDS_BIGENDIAN) || !defined(HAVE_INT64)
  1095.     memcpy(&mymoney, src, sizeof(TDS_INT8)); 
  1096. #else
  1097.     memcpy(((char*)&mymoney)+4, src, 4);
  1098.     memcpy(&mymoney, src+4, 4);
  1099. #endif
  1100. # if (SIZEOF_LONG_LONG > 0)
  1101. tdsdump_log(TDS_DBG_FUNC, "%L mymoney = %lldn", mymoney);
  1102. # else
  1103. tdsdump_log(TDS_DBG_FUNC, "%L mymoney = %ldn", mymoney);
  1104. # endif
  1105. switch(desttype) {
  1106. case SYBCHAR:
  1107. case SYBVARCHAR:
  1108. case SYBTEXT:
  1109. s = tds_money_to_string((const TDS_MONEY *)src, tmpstr);
  1110. return string_to_result(s,cr);
  1111. break;
  1112. case SYBBINARY:
  1113. case SYBIMAGE:
  1114. case SYBVARBINARY:
  1115. return binary_to_result(src,sizeof(TDS_MONEY),cr);
  1116. break;
  1117. case SYBINT1:
  1118. dollars  = mymoney / 10000;
  1119. if (!IS_TINYINT(dollars))
  1120. return TDS_CONVERT_OVERFLOW;
  1121. cr->ti = (TDS_TINYINT) dollars;
  1122. return sizeof(TDS_TINYINT);
  1123. break;
  1124. case SYBINT2:
  1125. dollars  = mymoney / 10000;
  1126. if (!IS_SMALLINT(dollars))
  1127. return TDS_CONVERT_OVERFLOW;
  1128. cr->si = (TDS_SMALLINT) dollars;
  1129. return sizeof(TDS_SMALLINT);
  1130. break;
  1131. case SYBINT4:
  1132. dollars  = mymoney / 10000;
  1133. if (!IS_INT(dollars))
  1134. return TDS_CONVERT_OVERFLOW;
  1135. cr->i = (TDS_INT) dollars;
  1136. return sizeof(TDS_INT);
  1137. break;
  1138. case SYBINT8:
  1139. cr->bi = mymoney / 10000;
  1140. return sizeof(TDS_INT8);
  1141. break;
  1142. case SYBBIT:
  1143. case SYBBITN:
  1144. cr->ti = mymoney ? 1 : 0;
  1145. return sizeof(TDS_TINYINT);
  1146. break;
  1147. case SYBFLT8:
  1148. cr->f  = ((TDS_FLOAT)mymoney) / 10000.0;
  1149. return sizeof(TDS_FLOAT);
  1150. break;
  1151. case SYBREAL:
  1152. cr->r  = (TDS_REAL) (mymoney / 10000.0);
  1153. return sizeof(TDS_REAL);
  1154. break;
  1155. case SYBMONEY4:
  1156. if (!IS_INT(mymoney))
  1157. return TDS_CONVERT_OVERFLOW;
  1158. cr->m4.mny4 = (TDS_INT) mymoney;
  1159. return sizeof(TDS_MONEY4);
  1160. break;
  1161. case SYBMONEY:
  1162. cr->m.mny = mymoney;
  1163. return sizeof(TDS_MONEY);
  1164. break;
  1165. case SYBDECIMAL:
  1166. case SYBNUMERIC:
  1167. s = tds_money_to_string((const TDS_MONEY *)src, tmpstr);
  1168. return stringz_to_numeric(tmpstr,cr);
  1169. break;
  1170. /* conversions not allowed */
  1171. case SYBUNIQUE:
  1172. case SYBDATETIME4:
  1173. case SYBDATETIME:
  1174. case SYBDATETIMN:
  1175. default:
  1176. return TDS_CONVERT_NOAVAIL;
  1177. break;
  1178. }
  1179. #ifndef NCBI_FTDS
  1180. return TDS_CONVERT_FAIL;
  1181. #endif
  1182. }
  1183. static TDS_INT 
  1184. tds_convert_datetime(TDSCONTEXT *tds_ctx, int srctype, const TDS_CHAR *src,
  1185. int desttype, CONV_RESULT *cr)
  1186. {
  1187. unsigned int dt_days, dt_time;
  1188. char whole_date_string[30];
  1189. TDSDATEREC when;
  1190. switch(desttype) {
  1191. case SYBCHAR:
  1192. case SYBVARCHAR:
  1193. case SYBTEXT:
  1194. if (!src) {
  1195. cr->c = (TDS_CHAR *) malloc(1);
  1196. test_alloc(cr->c);
  1197. *(cr->c) = '';
  1198.                 return 0;
  1199. } else {
  1200. memset( &when, 0, sizeof(when) );
  1201.                 tds_datecrack (SYBDATETIME, src, &when);
  1202.                 tds_strftime  (whole_date_string, sizeof(whole_date_string), tds_ctx->locale->date_fmt, &when );
  1203. return string_to_result(whole_date_string,cr);
  1204. }
  1205. break;
  1206. case SYBBINARY:
  1207. case SYBIMAGE:
  1208. case SYBVARBINARY:
  1209. return binary_to_result(src,sizeof(TDS_DATETIME),cr);
  1210. break;
  1211. case SYBDATETIME:
  1212. memcpy(&dt_days, src, 4);
  1213. memcpy(&dt_time, src + 4, 4);
  1214. cr->dt.dtdays = dt_days;
  1215. cr->dt.dttime = dt_time;
  1216.             return sizeof(TDS_DATETIME);
  1217. break;
  1218. case SYBDATETIME4:
  1219. memcpy(&dt_days, src, 4);
  1220. memcpy(&dt_time, src + 4, 4);
  1221. cr->dt4.days    = dt_days;
  1222. cr->dt4.minutes = (dt_time / 300) / 60;
  1223.             return sizeof(TDS_DATETIME4);
  1224. break;
  1225. /* conversions not allowed */
  1226. case SYBUNIQUE:
  1227. case SYBBIT:
  1228. case SYBBITN:
  1229. case SYBINT1:
  1230. case SYBINT2:
  1231. case SYBINT4:
  1232. case SYBINT8:
  1233. case SYBMONEY4:
  1234. case SYBMONEY:
  1235. case SYBNUMERIC:
  1236. case SYBDECIMAL:
  1237. default:
  1238. return TDS_CONVERT_NOAVAIL;
  1239. break;
  1240. }
  1241. #ifndef NCBI_FTDS
  1242. return TDS_CONVERT_FAIL;
  1243. #endif
  1244. }
  1245. /*
  1246. static int days_this_year (int years)
  1247. {
  1248. int year;
  1249.    year = 1900 + years;
  1250.    if ((year % 4 == 0 && year % 100 != 0) || year % 400 == 0)
  1251.       return 366;
  1252.    else
  1253.       return 365;
  1254. }
  1255. */
  1256. static TDS_INT 
  1257. tds_convert_datetime4(TDSCONTEXT *tds_ctx, int srctype, const TDS_CHAR *src,
  1258. int desttype, CONV_RESULT *cr)
  1259. {
  1260. TDS_USMALLINT dt_days, dt_mins;
  1261. char whole_date_string[30];
  1262. TDSDATEREC when;
  1263. switch(desttype) {
  1264. case SYBCHAR:
  1265. case SYBVARCHAR:
  1266. case SYBTEXT:
  1267. if (!src) {
  1268. cr->c = (TDS_CHAR *) malloc(1);
  1269. test_alloc(cr->c);
  1270. *(cr->c) = '';
  1271.                 return 0;
  1272. } else {
  1273. memset( &when, 0, sizeof(when) );
  1274.                 tds_datecrack (SYBDATETIME4, src, &when);
  1275.                 tds_strftime  (whole_date_string, sizeof(whole_date_string), tds_ctx->locale->date_fmt, &when );
  1276. return string_to_result(whole_date_string,cr);
  1277. }
  1278. break;
  1279. case SYBBINARY:
  1280. case SYBIMAGE:
  1281. case SYBVARBINARY:
  1282. return binary_to_result(src,sizeof(TDS_DATETIME4),cr);
  1283. break;
  1284. case SYBDATETIME:
  1285. memcpy(&dt_days, src, 2);
  1286. memcpy(&dt_mins, src + 2, 2);
  1287. cr->dt.dtdays = dt_days;
  1288. cr->dt.dttime = (dt_mins * 60) * 300;
  1289.             return sizeof(TDS_DATETIME);
  1290. break;
  1291. case SYBDATETIME4:
  1292. memcpy(&dt_days, src, 2);
  1293. memcpy(&dt_mins, src + 2, 2);
  1294. cr->dt4.days    = dt_days;
  1295. cr->dt4.minutes = dt_mins;
  1296.             return sizeof(TDS_DATETIME4);
  1297. break;
  1298. /* conversions not allowed */
  1299. case SYBUNIQUE:
  1300. case SYBBIT:
  1301. case SYBBITN:
  1302. case SYBINT1:
  1303. case SYBINT2:
  1304. case SYBINT4:
  1305. case SYBINT8:
  1306. case SYBMONEY4:
  1307. case SYBMONEY:
  1308. case SYBNUMERIC:
  1309. case SYBDECIMAL:
  1310. default:
  1311. return TDS_CONVERT_NOAVAIL;
  1312. break;
  1313. }
  1314. #ifndef NCBI_FTDS
  1315. return TDS_CONVERT_FAIL;
  1316. #endif
  1317. }
  1318. static TDS_INT 
  1319. tds_convert_real(int srctype, const TDS_CHAR *src,
  1320. int desttype, CONV_RESULT *cr)
  1321. {
  1322. TDS_REAL the_value;
  1323. /* FIXME how many big should be this buffer ?? */
  1324. char tmp_str[128];
  1325. TDS_INT  mymoney4;
  1326. TDS_INT8 mymoney;
  1327.    memcpy(&the_value, src, 4);
  1328.    switch(desttype) {
  1329.       case SYBCHAR:
  1330.       case SYBTEXT:
  1331.       case SYBVARCHAR:
  1332.             sprintf(tmp_str,"%.7g", the_value);
  1333.     return string_to_result(tmp_str,cr);
  1334.             break;
  1335. case SYBBINARY:
  1336. case SYBIMAGE:
  1337. case SYBVARBINARY:
  1338. return binary_to_result(src,sizeof(TDS_REAL),cr);
  1339. break;
  1340. case SYBINT1:
  1341. if (!IS_TINYINT(the_value))
  1342. return TDS_CONVERT_OVERFLOW;
  1343. cr->ti = (TDS_TINYINT) the_value;
  1344. return sizeof(TDS_TINYINT);
  1345. break;
  1346. case SYBINT2:
  1347. if (!IS_SMALLINT(the_value))
  1348. return TDS_CONVERT_OVERFLOW;
  1349. cr->si = (TDS_SMALLINT) the_value;
  1350. return sizeof(TDS_SMALLINT);
  1351. break;
  1352. case SYBINT4:
  1353. if (!IS_INT(the_value))
  1354. return TDS_CONVERT_OVERFLOW;
  1355. cr->i = (TDS_INT) the_value;
  1356. return sizeof(TDS_INT);
  1357. break;
  1358. case SYBINT8:
  1359. /* TODO check overflow */
  1360. cr->bi = the_value;
  1361. return sizeof(TDS_INT8);
  1362. break;
  1363. case SYBBIT:
  1364. case SYBBITN:
  1365. cr->ti = the_value ? 1 : 0;
  1366. return sizeof(TDS_TINYINT);
  1367. break;
  1368. case SYBFLT8:
  1369. cr->f = the_value;
  1370. return sizeof(TDS_FLOAT);
  1371. break;
  1372. case SYBREAL:
  1373. cr->r = the_value;
  1374. return sizeof(TDS_REAL);
  1375. break;
  1376. case SYBMONEY:
  1377. /* TODO check overflow */
  1378. mymoney = the_value * 10000;
  1379. memcpy(&(cr->m), &mymoney, sizeof(TDS_MONEY));
  1380. return sizeof(TDS_MONEY);
  1381. break;
  1382. case SYBMONEY4:
  1383. /* TODO check overflow */
  1384. mymoney4 = the_value * 10000;
  1385. memcpy(&(cr->m4), &mymoney4, sizeof(TDS_MONEY4));
  1386. return sizeof(TDS_MONEY4);
  1387. break;
  1388. case SYBNUMERIC:
  1389. case SYBDECIMAL:
  1390. sprintf(tmp_str,"%.*f", cr->n.scale,  the_value);
  1391. return stringz_to_numeric(tmp_str, cr);
  1392. break;
  1393. /* not allowed */
  1394. case SYBUNIQUE:
  1395. case SYBDATETIME4:
  1396. case SYBDATETIME:
  1397. case SYBDATETIMN:
  1398. default:
  1399. return TDS_CONVERT_NOAVAIL;
  1400. break;
  1401. }
  1402. #ifndef NCBI_FTDS
  1403. return TDS_CONVERT_FAIL;
  1404. #endif
  1405. }
  1406. static TDS_INT 
  1407. tds_convert_flt8(int srctype, const TDS_CHAR *src,
  1408. int desttype, CONV_RESULT *cr)
  1409. {
  1410. TDS_FLOAT the_value;
  1411. char      tmp_str[25];
  1412.    memcpy(&the_value, src, 8);
  1413.    switch(desttype) {
  1414.       case SYBCHAR:
  1415.       case SYBVARCHAR:
  1416.       case SYBTEXT:
  1417.             sprintf(tmp_str,"%.15g", the_value);
  1418.     return string_to_result(tmp_str,cr);
  1419.             break;
  1420. case SYBBINARY:
  1421. case SYBIMAGE:
  1422. case SYBVARBINARY:
  1423. return binary_to_result(src,sizeof(TDS_FLOAT),cr);
  1424. break;
  1425. case SYBINT1:
  1426. if (!IS_TINYINT(the_value))
  1427. return TDS_CONVERT_OVERFLOW;
  1428. cr->ti = (TDS_TINYINT) the_value;
  1429. return sizeof(TDS_TINYINT);
  1430. break;
  1431. case SYBINT2:
  1432. if (!IS_SMALLINT(the_value))
  1433. return TDS_CONVERT_OVERFLOW;
  1434. cr->si = (TDS_SMALLINT) the_value;
  1435. return sizeof(TDS_SMALLINT);
  1436. break;
  1437. case SYBINT4:
  1438. if (!IS_INT(the_value))
  1439. return TDS_CONVERT_OVERFLOW;
  1440. cr->i = (TDS_INT) the_value;
  1441. return sizeof(TDS_INT);
  1442. break;
  1443. case SYBINT8:
  1444. /* TODO check overflow */
  1445. cr->bi = the_value;
  1446. return sizeof(TDS_INT8);
  1447. break;
  1448. case SYBBIT:
  1449. case SYBBITN:
  1450. cr->ti = the_value ? 1 : 0;
  1451. return sizeof(TDS_TINYINT);
  1452. break;
  1453.       case SYBMONEY:
  1454. /* TODO check overflow */
  1455.             cr->m.mny = (TDS_INT8)the_value * 10000.0;
  1456.             return sizeof(TDS_MONEY);
  1457.             break;
  1458.       case SYBMONEY4:
  1459. /* TODO check overflow */
  1460.             cr->m4.mny4 = the_value * 10000.0;
  1461.             return sizeof(TDS_MONEY4);
  1462.             break;
  1463. case SYBREAL:
  1464. cr->r = the_value;
  1465. return sizeof(TDS_REAL);
  1466. break;
  1467. case SYBFLT8:
  1468. cr->f = the_value;
  1469. return sizeof(TDS_FLOAT);
  1470. break;
  1471. case SYBNUMERIC:
  1472. case SYBDECIMAL:
  1473. sprintf(tmp_str,"%.15g", the_value);
  1474. return stringz_to_numeric(tmp_str, cr);
  1475. break;
  1476. /* not allowed */
  1477. case SYBUNIQUE:
  1478. case SYBDATETIME4:
  1479. case SYBDATETIME:
  1480. case SYBDATETIMN:
  1481. default:
  1482. return TDS_CONVERT_NOAVAIL;
  1483. break;
  1484. }
  1485. #ifndef NCBI_FTDS
  1486. return TDS_CONVERT_FAIL;
  1487. #endif
  1488. }
  1489. static TDS_INT
  1490. tds_convert_unique(int srctype, const TDS_CHAR *src, TDS_INT srclen,
  1491. int desttype, CONV_RESULT *cr)
  1492. {
  1493. /* Raw data is equivalent to structure and always aligned, so this cast 
  1494.    is portable */
  1495. const TDS_UNIQUE *u = (const TDS_UNIQUE *) src;
  1496. char buf[37];
  1497. switch(desttype) {
  1498.        case SYBCHAR:
  1499.        case SYBTEXT:
  1500.        case SYBVARCHAR:
  1501.     sprintf(buf,"%08X-%04X-%04X-%02X%02X-%02X%02X%02X%02X%02X%02X",
  1502.         (int)u->Data1,(int)u->Data2,(int)u->Data3,
  1503.          u->Data4[0], u->Data4[1],
  1504.          u->Data4[2], u->Data4[3], u->Data4[4],
  1505.          u->Data4[5], u->Data4[6], u->Data4[7]);
  1506. return string_to_result(buf,cr);
  1507.     break;
  1508. case SYBBINARY:
  1509. case SYBIMAGE:
  1510. case SYBVARBINARY:
  1511. return binary_to_result(src,sizeof(TDS_UNIQUE),cr);
  1512. break;
  1513.     case SYBUNIQUE:
  1514. /* Here we can copy raw to structure because we adjust
  1515.    byte order in tds_swap_datatype */
  1516. memcpy (&(cr->u), src, sizeof(TDS_UNIQUE));
  1517. return sizeof(TDS_UNIQUE);
  1518. break;
  1519. /* no not warning for not convertible types */
  1520. case SYBBIT:
  1521. case SYBBITN:
  1522. case SYBINT1:
  1523. case SYBINT2:
  1524. case SYBINT4:
  1525. case SYBINT8:
  1526. case SYBMONEY4:
  1527. case SYBMONEY:
  1528. case SYBDATETIME4:
  1529. case SYBDATETIME:
  1530. case SYBDATETIMN:
  1531. case SYBREAL:
  1532. case SYBFLT8:
  1533. default:
  1534. return TDS_CONVERT_NOAVAIL;
  1535. break;
  1536. }
  1537. #ifndef NCBI_FTDS
  1538. return TDS_CONVERT_FAIL;
  1539. #endif
  1540. }
  1541. /**
  1542.  * tds_convert
  1543.  * convert a type to another.
  1544.  * If you convert to SYBDECIMAL/SYBNUMERIC you MUST initialize precision 
  1545.  * and scale of cr.
  1546.  * Do not expect string to be zero terminated. Databases support zero inside
  1547.  * string. Doing strlen on result may result on data loss or even core.
  1548.  * Use memcpy to copy destination using length returned.
  1549.  * This function do not handle NULL, srclen should be >0, if not undefinited 
  1550.  * behaviour...
  1551.  * @param tds_ctx  context (used in conversion to data and to return messages)
  1552.  * @param srctype  type of source
  1553.  * @param src      pointer to source data to convert
  1554.  * @param srclen   length in bytes of source (not counting terminator or strings)
  1555.  * @param desttype type of destination
  1556.  * @param cr       structure to hold result
  1557.  * @return length of result or TDS_CONVERT_* failure code on failure. All TDS_CONVERT_* constants are <0.
  1558.  */
  1559. TDS_INT 
  1560. tds_convert(TDSCONTEXT *tds_ctx, int srctype, const TDS_CHAR *src,
  1561. TDS_UINT srclen, int desttype, CONV_RESULT *cr)
  1562. {
  1563. TDS_INT length = 0;
  1564. switch (srctype) {
  1565. case SYBCHAR:
  1566. case SYBVARCHAR:
  1567. case SYBTEXT:
  1568. length = tds_convert_char(srctype, src, srclen, desttype, cr);
  1569. break;
  1570. case SYBMONEY4:
  1571. length = tds_convert_money4(srctype,src, srclen, desttype, cr);
  1572. break;
  1573. case SYBMONEY:
  1574. length = tds_convert_money(srctype, src, desttype, cr);
  1575. break;
  1576. case SYBNUMERIC:
  1577. case SYBDECIMAL:
  1578. length = tds_convert_numeric(srctype, (const TDS_NUMERIC *) src, srclen, desttype, cr);
  1579. break;
  1580. case SYBBIT:
  1581. case SYBBITN:
  1582. length = tds_convert_bit(srctype, src, desttype, cr);
  1583. break;
  1584. case SYBINT1:
  1585. length = tds_convert_int1(srctype, src, desttype, cr);
  1586. break;
  1587. case SYBINT2:
  1588. length = tds_convert_int2(srctype, src, desttype, cr);
  1589. break;
  1590. case SYBINT4:
  1591. length = tds_convert_int4(srctype, src, desttype, cr);
  1592. break;
  1593. case SYBINT8:
  1594. length = tds_convert_int8(srctype, src, desttype, cr);
  1595. break;
  1596. case SYBREAL:
  1597. length = tds_convert_real(srctype, src, desttype, cr);
  1598. break;
  1599. case SYBFLT8:
  1600. length = tds_convert_flt8(srctype, src, desttype, cr);
  1601. break;
  1602. case SYBDATETIME:
  1603. length = tds_convert_datetime(tds_ctx, srctype, src,
  1604. desttype, cr);
  1605. break;
  1606. case SYBDATETIME4:
  1607. length = tds_convert_datetime4(tds_ctx, srctype, src,
  1608. desttype, cr);
  1609. break;
  1610. case SYBIMAGE:
  1611. case SYBBINARY:
  1612. case SYBVARBINARY:
  1613. length = tds_convert_binary(srctype,
  1614. (const TDS_UCHAR *) src, srclen, desttype, cr);
  1615. break;
  1616. case SYBUNIQUE:
  1617. length = tds_convert_unique(srctype, src, srclen,
  1618. desttype, cr);
  1619. break;
  1620. case SYBNVARCHAR:
  1621. case SYBNTEXT:
  1622. default:
  1623. return TDS_CONVERT_NOAVAIL;
  1624. break;
  1625. }
  1626. /* fix MONEY case */
  1627. #if !defined(WORDS_BIGENDIAN) && defined(HAVE_INT64)
  1628. if (length > 0 && desttype == SYBMONEY) {
  1629. cr->m.mny = 
  1630. ((TDS_UINT8)cr->m.mny) >> 32 | (cr->m.mny << 32);
  1631. }
  1632. #endif
  1633. return length;
  1634. }
  1635. static int string_to_datetime(const char *instr, int desttype, CONV_RESULT *cr)
  1636. {
  1637. enum states { GOING_IN_BLIND,
  1638.               PUT_NUMERIC_IN_CONTEXT,
  1639.               DOING_ALPHABETIC_DATE,
  1640.               STRING_GARBLED };
  1641. char *in;
  1642. char *tok;
  1643. char *lasts;
  1644. char last_token[32];
  1645. int   monthdone = 0;
  1646. int   yeardone  = 0;
  1647. int   mdaydone  = 0;
  1648. struct tds_time mytime;
  1649. struct tds_time *t;
  1650. unsigned int dt_time;
  1651. TDS_INT      dt_days;
  1652. int          i;
  1653. int current_state;
  1654. memset(&mytime, '', sizeof(struct tds_time));
  1655. t = &mytime;
  1656. in = (char *)malloc(strlen(instr)+1);
  1657. test_alloc(in);
  1658. strcpy (in , instr );
  1659. tok = strtok_r(in, " ,", &lasts);
  1660. current_state = GOING_IN_BLIND;
  1661. while (tok != (char *) NULL) {
  1662. switch (current_state) {
  1663. case GOING_IN_BLIND :
  1664. /* If we have no idea of current context, then if we have */
  1665. /* encountered a purely alphabetic string, it MUST be an  */
  1666. /* alphabetic month name or prefix...                     */
  1667. if (is_alphabetic(tok)) {
  1668. if (is_monthname(tok)) {
  1669. store_monthname(tok, t);
  1670. monthdone++;
  1671. current_state = DOING_ALPHABETIC_DATE;
  1672. } else {
  1673. current_state = STRING_GARBLED;
  1674. }
  1675. }
  1676.               /* ...whereas if it is numeric, it could be a number of   */
  1677.               /* things...                                              */
  1678.               else if (is_numeric(tok)) {
  1679.                       switch(strlen(tok)) {
  1680.                          /* in this context a 4 character numeric can   */
  1681.                          /* ONLY be the year part of an alphabetic date */
  1682.                          case 4:
  1683.                             store_year(atoi(tok), t);
  1684.                             yeardone++;
  1685.                             current_state = DOING_ALPHABETIC_DATE;
  1686.                             break;
  1687.                          /* whereas these could be the hour part of a   */
  1688.                          /* time specification ( 4 PM ) or the leading  */
  1689.                          /* day part of an alphabetic date ( 15 Jan )   */
  1690.                          case 2:
  1691.                          case 1:
  1692.                             strcpy(last_token, tok);
  1693.                             current_state = PUT_NUMERIC_IN_CONTEXT;
  1694.                             break;
  1695.                          /* this must be a [YY]YYMMDD date             */
  1696.                          case 6:
  1697.                          case 8:
  1698.                             if (store_yymmdd_date(tok, t))
  1699.                                current_state = GOING_IN_BLIND;
  1700.                             else
  1701.                                current_state = STRING_GARBLED;
  1702.                             break;
  1703.                          /* anything else is nonsense...               */
  1704.                          default:
  1705.                             current_state = STRING_GARBLED;
  1706.                             break;
  1707.                       }
  1708.                    }
  1709.                    /* it could be [M]M/[D]D/[YY]YY format              */
  1710.                    else if (is_numeric_dateformat(tok)) {
  1711.                             store_numeric_date(tok, t);
  1712.                             current_state = GOING_IN_BLIND;
  1713.                    } else if (is_timeformat(tok)) {
  1714.                                 store_time(tok, t);
  1715.                                 current_state = GOING_IN_BLIND;
  1716.                    } else {
  1717.                                  current_state = STRING_GARBLED;
  1718.  }
  1719.               break;   /* end of GOING_IN_BLIND */                               
  1720.            case DOING_ALPHABETIC_DATE:
  1721.               if (is_alphabetic(tok)) {
  1722.                  if (!monthdone && is_monthname(tok)) {
  1723.                      store_monthname(tok, t);
  1724.                      monthdone++;
  1725.                      if (monthdone && yeardone && mdaydone )
  1726.                         current_state = GOING_IN_BLIND;
  1727.                      else
  1728.                         current_state = DOING_ALPHABETIC_DATE;
  1729.                  } else {
  1730.                      current_state = STRING_GARBLED;
  1731.   }
  1732.               } else if (is_numeric(tok)) {
  1733.                       if (mdaydone && yeardone)
  1734.                           current_state = STRING_GARBLED;
  1735.                       else switch(strlen(tok)) {
  1736.                               case 4:
  1737.                                  store_year(atoi(tok), t);
  1738.                                  yeardone++;
  1739.                                  if (monthdone && yeardone && mdaydone )
  1740.                                     current_state = GOING_IN_BLIND;
  1741.                                  else
  1742.                                     current_state = DOING_ALPHABETIC_DATE;
  1743.                                  break;
  1744.                               case 2:
  1745.                               case 1:
  1746.                                  if (!mdaydone) {
  1747.                                     store_mday(tok, t);
  1748.                                     mdaydone++;
  1749.                                     if (monthdone && yeardone && mdaydone )
  1750.                                        current_state = GOING_IN_BLIND;
  1751.                                     else
  1752.                                        current_state = DOING_ALPHABETIC_DATE;
  1753.                                  } else {
  1754.                                     store_year(atoi(tok), t);
  1755.                                     yeardone++;
  1756.                                     if (monthdone && yeardone && mdaydone )
  1757.                                        current_state = GOING_IN_BLIND;
  1758.                                     else
  1759.                                        current_state = DOING_ALPHABETIC_DATE;
  1760.                                  }
  1761.                                  break;
  1762.                               default:
  1763.                                  current_state = STRING_GARBLED;
  1764.                            }
  1765.                    } else {
  1766.                      current_state = STRING_GARBLED;
  1767.  }
  1768.               break;   /* end of DOING_ALPHABETIC_DATE */                        
  1769.            case PUT_NUMERIC_IN_CONTEXT:
  1770.               if (is_alphabetic(tok)) {
  1771.                  if (is_monthname(tok)) {
  1772.                      store_mday(last_token, t);
  1773.                      mdaydone++;
  1774.                      store_monthname(tok, t);
  1775.                      monthdone++;
  1776.                      if (monthdone && yeardone && mdaydone )
  1777.                         current_state = GOING_IN_BLIND;
  1778.                      else
  1779.                         current_state = DOING_ALPHABETIC_DATE;
  1780.                  } else if (is_ampm(tok)) {
  1781.                      store_hour(last_token, tok, t);
  1782.                      current_state = GOING_IN_BLIND;
  1783.                  } else {
  1784.                          current_state = STRING_GARBLED;
  1785.   }
  1786.               } else if (is_numeric(tok)) {
  1787.                       switch(strlen(tok)) {
  1788.                          case 4:
  1789.                          case 2:
  1790.                            store_mday(last_token, t);
  1791.                            mdaydone++;
  1792.                            store_year(atoi(tok), t);
  1793.                            yeardone++;
  1794.                            if (monthdone && yeardone && mdaydone )
  1795.                               current_state = GOING_IN_BLIND;
  1796.                            else
  1797.                               current_state = DOING_ALPHABETIC_DATE;
  1798.                            break;
  1799.                          default:
  1800.                            current_state = STRING_GARBLED;
  1801.                        }
  1802.                 } else {
  1803.                    current_state = STRING_GARBLED;
  1804.  }
  1805.               break;   /* end of PUT_NUMERIC_IN_CONTEXT */                       
  1806.            case STRING_GARBLED:
  1807.                 
  1808.               tdsdump_log(TDS_DBG_INFO1,"error_handler:  Attempt to convert data stopped by syntax error in source field n");
  1809.               return TDS_CONVERT_SYNTAX;
  1810.         }
  1811.         tok = strtok_r((char *)NULL, " ,", &lasts);
  1812.     }
  1813. i = (t->tm_mon - 13) / 12;
  1814. dt_days = 1461 * ( t->tm_year + 300 + i ) / 4 +
  1815. (367 * ( t->tm_mon - 1 - 12*i ) ) / 12 -
  1816. (3 * ( ( t->tm_year + 400 + i ) / 100 ) ) / 4 +
  1817. t->tm_mday - 109544;
  1818. free(in);
  1819. /* TODO check for overflow */
  1820. if ( desttype == SYBDATETIME ) {
  1821. cr->dt.dtdays = dt_days;
  1822. dt_time = (t->tm_hour * 60 + t->tm_min ) * 60 + t->tm_sec;
  1823. cr->dt.dttime = dt_time * 300 + (t->tm_ms * 300 / 1000);
  1824. return sizeof(TDS_DATETIME);
  1825. } else {
  1826. /* SYBDATETIME4 */ 
  1827. cr->dt4.days = dt_days;
  1828. cr->dt4.minutes = t->tm_hour * 60 + t->tm_min;
  1829. return sizeof(TDS_DATETIME4);
  1830. }
  1831. }
  1832. static int 
  1833. stringz_to_numeric(const char *instr, CONV_RESULT *cr)
  1834. {
  1835. return string_to_numeric(instr,instr+strlen(instr),cr);
  1836. }
  1837. static int 
  1838. string_to_numeric(const char *instr, const char *pend, CONV_RESULT *cr)
  1839. {
  1840. char  mynumber[(MAXPRECISION+7)/8*8];
  1841. /* num packaged 8 digit, see below for detail */
  1842. TDS_UINT packed_num[TDS_VECTOR_SIZE(mynumber)/8];
  1843. char *ptr;
  1844. const char *pdigits;
  1845. const char* pstr;
  1846. TDS_UINT  carry = 0;
  1847. char  not_zero = 1;
  1848. int  i = 0;
  1849. int  j = 0;
  1850. short int bytes, places, point_found, sign, digits;
  1851.   sign        = 0;
  1852.   point_found = 0;
  1853.   places      = 0;
  1854. /* FIXME: application can pass invalid value for precision and scale ?? */
  1855. if (cr->n.precision > 77)
  1856. return TDS_CONVERT_FAIL;
  1857. if (cr->n.precision == 0)
  1858. cr->n.precision = 77; /* assume max precision */
  1859.   if ( cr->n.scale > cr->n.precision )
  1860. return TDS_CONVERT_FAIL;
  1861.   /* skip leading blanks */
  1862.   for (pstr = instr;; ++pstr)
  1863.   {
  1864.    if (pstr == pend) return TDS_CONVERT_SYNTAX;
  1865.    if (*pstr != ' ') break;
  1866.   }
  1867.   if ( *pstr == '-' || *pstr == '+' )         /* deal with a leading sign */
  1868.   {
  1869.      if (*pstr == '-')
  1870.         sign = 1;
  1871.      pstr++;
  1872.   }
  1873.   digits = 0;
  1874.   pdigits = pstr;
  1875.   for(; pstr != pend; ++pstr)             /* deal with the rest */
  1876.   {
  1877.      if (isdigit((unsigned char) *pstr))  /* its a number */
  1878.      {  
  1879.         if (point_found)                  /* if we passed a decimal point */
  1880.            ++places;                      /* count digits after that point  */
  1881.         else
  1882.            ++digits;                      /* count digits before point  */
  1883.      }
  1884.      else if (*pstr == '.')               /* found a decimal point */
  1885.           {
  1886.              if (point_found)             /* already had one. return error */
  1887.                 return TDS_CONVERT_SYNTAX;
  1888.              point_found = 1;
  1889.           }
  1890.           else                            /* first invalid character */
  1891.              return TDS_CONVERT_SYNTAX;   /* return error. */
  1892.   }
  1893.   /* no digits? no number!*/
  1894.   if (!digits)
  1895.    return TDS_CONVERT_SYNTAX;
  1896. /* truncate decimal digits */
  1897. if ( places > cr->n.scale)
  1898. places = cr->n.scale;
  1899.   /* too digits, error */
  1900.   if ( (digits+cr->n.scale) > cr->n.precision)
  1901.   return TDS_CONVERT_OVERFLOW;
  1902.   /* TODO: this can be optimized in a single step */
  1903.   /* scale specified, pad out number with zeroes to the scale...  */
  1904.   ptr = mynumber+sizeof(mynumber)-(cr->n.scale-places);
  1905.   memset(ptr,48,cr->n.scale-places);
  1906.   ptr -= places;
  1907.   /* copy number without point */
  1908.   memcpy(ptr,pdigits+digits+1,places);
  1909.   ptr -= digits;
  1910.   memcpy(ptr,pdigits,digits);
  1911.   memset(mynumber,48,ptr-mynumber);
  1912.   /* transform ASCII string into a numeric array */
  1913.   for (ptr = mynumber; ptr != mynumber+sizeof(mynumber); ++ptr)
  1914.    *ptr -= 48;
  1915.   /*
  1916.    * Packaged number explanation
  1917.    * I package 8 decimal digit in one number
  1918.    * This because 10^8 = 5^8 * 2^8 = 5^8 * 256
  1919.    * So dividing 10^8 for 256 make no remainder
  1920.    * So I can split for bytes in an optmized way
  1921.    */
  1922.  
  1923. /* transform to packaged one */
  1924. for(j=0; j<TDS_VECTOR_SIZE(packed_num); ++j)
  1925. {
  1926. TDS_UINT n = mynumber[j*8];
  1927. for(i=1;i<8;++i)
  1928. n = n * 10 + mynumber[j*8+i];
  1929. packed_num[j] = n;
  1930. }
  1931. memset(cr->n.array,0,sizeof(cr->n.array));
  1932. cr->n.array[0] =  sign;
  1933. bytes = g__numeric_bytes_per_prec[cr->n.precision];
  1934. while (not_zero)
  1935. {
  1936. not_zero = 0;
  1937. carry = 0;
  1938. for (i = 0; i < TDS_VECTOR_SIZE(packed_num); ++i)
  1939. {
  1940. TDS_UINT tmp;
  1941. if (packed_num[i] > 0)
  1942. not_zero = 1;
  1943. /* divide for 256 for find another byte */
  1944. tmp = packed_num[i];
  1945. /* carry * (25u*25u*25u*25u) = carry * 10^8 / 256u
  1946.  * using unsigned number is just an optimization
  1947.  * compiler can translate division to a shift and remainder 
  1948.  * to a binary and
  1949.  */
  1950. packed_num[i] = carry * (25u*25u*25u*25u) + packed_num[i] / 256u;
  1951. carry = tmp % 256u;
  1952. if ( i == (TDS_VECTOR_SIZE(packed_num) - 1) && not_zero)
  1953. {
  1954. /* source number is limited to 38 decimal digit
  1955.  * 10^39-1 < 2^128 (16 byte) so this cannot make an overflow
  1956.  */
  1957. cr->n.array[--bytes] = carry;
  1958. }
  1959. }
  1960. }
  1961. return sizeof(TDS_NUMERIC);
  1962. }
  1963. static int is_numeric_dateformat(char *t)
  1964. {
  1965. char *instr ;
  1966. int   ret   = 1;
  1967. int   slashes  = 0;
  1968. int   hyphens  = 0;
  1969. int   periods  = 0;
  1970. int   digits   = 0;
  1971.     for (instr = t; *instr; instr++ )
  1972.     {
  1973.         if (!isdigit((unsigned char) *instr) && *instr != '/' && *instr != '-' && *instr != '.' )
  1974.         {
  1975.             ret = 0;
  1976.             break;
  1977.         }
  1978.         if (*instr == '/' ) slashes++;
  1979.         else if (*instr == '-' ) hyphens++;
  1980.              else if (*instr == '.' ) periods++;
  1981.                   else digits++;
  1982.        
  1983.     }
  1984.     if (hyphens + slashes + periods != 2)
  1985.        ret = 0;
  1986.     if (hyphens == 1 || slashes == 1 || periods == 1)
  1987.        ret = 0;
  1988.     if (digits < 4 || digits > 8)
  1989.        ret = 0;
  1990.     return(ret);
  1991. }
  1992. static int is_monthname(char *datestr)
  1993. {
  1994. int ret = 0;
  1995.     if (strlen(datestr) == 3)
  1996.     {
  1997.        if (strcasecmp(datestr,"jan") == 0) ret = 1;
  1998.        else if (strcasecmp(datestr,"feb") == 0) ret = 1;
  1999.        else if (strcasecmp(datestr,"mar") == 0) ret = 1;
  2000.        else if (strcasecmp(datestr,"apr") == 0) ret = 1;
  2001.        else if (strcasecmp(datestr,"may") == 0) ret = 1;
  2002.        else if (strcasecmp(datestr,"jun") == 0) ret = 1;
  2003.        else if (strcasecmp(datestr,"jul") == 0) ret = 1;
  2004.        else if (strcasecmp(datestr,"aug") == 0) ret = 1;
  2005.        else if (strcasecmp(datestr,"sep") == 0) ret = 1;
  2006.        else if (strcasecmp(datestr,"oct") == 0) ret = 1;
  2007.        else if (strcasecmp(datestr,"nov") == 0) ret = 1;
  2008.        else if (strcasecmp(datestr,"dec") == 0) ret = 1;
  2009.        else ret = 0;
  2010.     }
  2011.     else
  2012.     {
  2013.        if (strcasecmp(datestr,"january") == 0) ret = 1;
  2014.        else if (strcasecmp(datestr,"february") == 0) ret = 1;
  2015.        else if (strcasecmp(datestr,"march") == 0) ret = 1;
  2016.        else if (strcasecmp(datestr,"april") == 0) ret = 1;
  2017.        else if (strcasecmp(datestr,"june") == 0) ret = 1;
  2018.        else if (strcasecmp(datestr,"july") == 0) ret = 1;
  2019.        else if (strcasecmp(datestr,"august") == 0) ret = 1;
  2020.        else if (strcasecmp(datestr,"september") == 0) ret = 1;
  2021.        else if (strcasecmp(datestr,"october") == 0) ret = 1;
  2022.        else if (strcasecmp(datestr,"november") == 0) ret = 1;
  2023.        else if (strcasecmp(datestr,"december") == 0) ret = 1;
  2024.        else ret = 0;
  2025.     }
  2026.     return(ret);
  2027. }
  2028. static int is_ampm(char *datestr)
  2029. {
  2030. int ret = 0;
  2031.     if (strcasecmp(datestr,"am") == 0) ret = 1;
  2032.     else if (strcasecmp(datestr,"pm") == 0) ret = 1;
  2033.     else ret = 0;
  2034.     return(ret);
  2035. }
  2036. static int is_alphabetic(char *datestr)
  2037. {
  2038. char *s;
  2039. int  ret = 1;
  2040.     for (s = datestr; *s; s++) {
  2041.         if (!isalpha((unsigned char) *s))
  2042.            ret = 0; 
  2043.     }
  2044.     return(ret);
  2045. }
  2046. static int is_numeric(char *datestr)
  2047. {
  2048. char *s;
  2049. int  ret = 1;
  2050.     for (s = datestr; *s; s++) {
  2051.         if (!isdigit((unsigned char) *s))
  2052.            ret = 0; 
  2053.     }
  2054.     return(ret);
  2055. }
  2056. static int is_timeformat(char *datestr)
  2057. {
  2058. char *s;
  2059. int  ret = 1;
  2060.     for (s = datestr; *s; s++) 
  2061.     {
  2062.         if (!isdigit((unsigned char) *s) && *s != ':' && *s != '.' )
  2063.           break;
  2064.     }
  2065.     if ( *s )
  2066.     {
  2067.        if (strcasecmp(s, "am" ) != 0 && strcasecmp(s, "pm" ) != 0 )
  2068.           ret = 0; 
  2069.     }
  2070.     
  2071.     return(ret);
  2072. }
  2073. static int store_year(int year , struct tds_time *t)
  2074. {
  2075.     if ( year <= 0 )
  2076.        return 0; 
  2077.     if ( year < 100 )
  2078.     {
  2079.        if (year > 49)
  2080.           t->tm_year = year;
  2081.        else
  2082.           t->tm_year = 100 + year ;
  2083.        return (1);
  2084.     }
  2085.     if ( year < 1753 )
  2086.        return (0);
  2087.     if ( year <= 9999 )
  2088.     {
  2089.        t->tm_year = year - 1900;
  2090.        return (1);
  2091.     }
  2092.     return (0);
  2093. }
  2094. static int store_mday(char *datestr , struct tds_time *t)
  2095. {
  2096. int  mday = 0;
  2097.     mday = atoi(datestr);
  2098.     if ( mday > 0 && mday < 32 )
  2099.     {
  2100.        t->tm_mday = mday;
  2101.        return (1);
  2102.     }
  2103.     else
  2104.        return 0; 
  2105. }
  2106. static int store_numeric_date(char *datestr , struct tds_time *t)
  2107. {
  2108. int   TDS_MONTH = 0;
  2109. int   TDS_DAY   = 0;
  2110. int   TDS_YEAR  = 0;
  2111. int  state;
  2112. char last_char = 0; 
  2113. char *s;
  2114. int  month = 0, year = 0, mday = 0;
  2115.     /* Its YYYY-MM-DD format */
  2116.     if ( strlen(datestr) == 10 && *(datestr + 4) == '-' && *(datestr + 7) == '-' ) {
  2117.        TDS_YEAR  = 0;
  2118.        TDS_MONTH = 1;
  2119.        TDS_DAY   = 2;
  2120.        state     = TDS_YEAR;
  2121.        
  2122.     }
  2123.     /* else we assume MDY */
  2124.     else {
  2125.        TDS_MONTH = 0;
  2126.        TDS_DAY   = 1;
  2127.        TDS_YEAR  = 2;
  2128.        state     = TDS_MONTH;
  2129.     }
  2130.     for (s = datestr; *s; s++) {
  2131.         if (!isdigit((unsigned char) *s) && isdigit((unsigned char) last_char)) {
  2132.             state++;
  2133.         } else {
  2134.             if (state == TDS_MONTH)
  2135.                 month = (month * 10) + (*s - '0');
  2136.             if (state ==  TDS_DAY)
  2137.                 mday = (mday * 10) + (*s - '0');
  2138.             if (state ==  TDS_YEAR)
  2139.                 year = (year * 10) + (*s - '0');
  2140.         }
  2141.         last_char = *s;
  2142.     }
  2143.     if ( month > 0 && month < 13 )
  2144.        t->tm_mon = month - 1;
  2145.     else
  2146.        return 0; 
  2147.     if ( mday > 0 && mday < 32 )
  2148.        t->tm_mday = mday;
  2149.     else
  2150.        return 0; 
  2151.     return store_year(year, t);
  2152. }
  2153. static int store_monthname(char *datestr , struct tds_time *t)
  2154. {
  2155. int ret = 0;
  2156.     if (strlen(datestr) == 3)
  2157.     {
  2158.        if (strcasecmp(datestr,"jan") == 0) t->tm_mon = 0;
  2159.        else if (strcasecmp(datestr,"feb") == 0) t->tm_mon = 1;
  2160.        else if (strcasecmp(datestr,"mar") == 0) t->tm_mon = 2;
  2161.        else if (strcasecmp(datestr,"apr") == 0) t->tm_mon = 3;
  2162.        else if (strcasecmp(datestr,"may") == 0) t->tm_mon = 4;
  2163.        else if (strcasecmp(datestr,"jun") == 0) t->tm_mon = 5;
  2164.        else if (strcasecmp(datestr,"jul") == 0) t->tm_mon = 6;
  2165.        else if (strcasecmp(datestr,"aug") == 0) t->tm_mon = 7;
  2166.        else if (strcasecmp(datestr,"sep") == 0) t->tm_mon = 8;
  2167.        else if (strcasecmp(datestr,"oct") == 0) t->tm_mon = 9;
  2168.        else if (strcasecmp(datestr,"nov") == 0) t->tm_mon = 10;
  2169.        else if (strcasecmp(datestr,"dec") == 0) t->tm_mon = 11;
  2170.        else ret = 0;
  2171.     }
  2172.     else
  2173.     {
  2174.        if (strcasecmp(datestr,"january") == 0) t->tm_mon = 0;
  2175.        else if (strcasecmp(datestr,"february") == 0) t->tm_mon = 1;
  2176.        else if (strcasecmp(datestr,"march") == 0) t->tm_mon = 2;
  2177.        else if (strcasecmp(datestr,"april") == 0) t->tm_mon = 3;
  2178.        else if (strcasecmp(datestr,"june") == 0) t->tm_mon = 5;
  2179.        else if (strcasecmp(datestr,"july") == 0) t->tm_mon = 6;
  2180.        else if (strcasecmp(datestr,"august") == 0) t->tm_mon = 7;
  2181.        else if (strcasecmp(datestr,"september") == 0) t->tm_mon = 8;
  2182.        else if (strcasecmp(datestr,"october") == 0) t->tm_mon = 9;
  2183.        else if (strcasecmp(datestr,"november") == 0) t->tm_mon = 10;
  2184.        else if (strcasecmp(datestr,"december") == 0) t->tm_mon = 11;
  2185.        else ret = 0;
  2186.     }
  2187.     return(ret);
  2188. }
  2189. static int store_yymmdd_date(char *datestr , struct tds_time *t)
  2190. {
  2191. int  month = 0, year = 0, mday = 0;
  2192. int wholedate;
  2193.     wholedate = atoi(datestr);
  2194.     year  = wholedate / 10000 ;
  2195.     month = ( wholedate - (year * 10000) ) / 100 ; 
  2196.     mday  = ( wholedate - (year * 10000) - (month * 100) );
  2197.     if ( month > 0 && month < 13 )
  2198.        t->tm_mon = month - 1;
  2199.     else
  2200.        return 0; 
  2201.     if ( mday > 0 && mday < 32 )
  2202.        t->tm_mday = mday;
  2203.     else
  2204.        return 0; 
  2205.     return (store_year(year, t));
  2206. }
  2207. static int store_time(char *datestr , struct tds_time *t)
  2208. {
  2209. enum {TDS_HOURS, 
  2210.       TDS_MINUTES, 
  2211.       TDS_SECONDS,
  2212.       TDS_FRACTIONS};
  2213. int  state = TDS_HOURS;
  2214. char last_sep = '';
  2215. char *s;
  2216. int hours = 0, minutes = 0, seconds = 0, millisecs = 0;
  2217. int ret = 1;
  2218. int ms_len = 0;
  2219.     for (s = datestr; 
  2220.          *s && strchr("apmAPM" , (int) *s) == (char *)NULL; 
  2221.          s++) 
  2222.     {
  2223.         if ( *s == ':' || *s == '.' ) {
  2224.             last_sep = *s;
  2225.             state++;
  2226.         } else switch(state) {
  2227.             case TDS_HOURS:
  2228.                 hours = (hours * 10) + (*s - '0');
  2229.                 break;
  2230.             case TDS_MINUTES:
  2231.                 minutes = (minutes * 10) + (*s - '0');
  2232.                 break;
  2233.             case TDS_SECONDS:
  2234.                 seconds = (seconds * 10) + (*s - '0');
  2235.                 break;
  2236.             case TDS_FRACTIONS:
  2237.                 millisecs = (millisecs * 10) + (*s - '0');
  2238.                 ms_len++;
  2239.                 break;
  2240.         }
  2241.     }
  2242.     if (*s)
  2243.     {
  2244.        if(strcasecmp(s,"am") == 0)
  2245.        {
  2246.           if (hours == 12)
  2247.               hours = 0;
  2248.           t->tm_hour = hours;
  2249.        }
  2250.        if(strcasecmp(s,"pm") == 0)
  2251.        {
  2252.           if (hours == 0)
  2253.               ret = 0;
  2254.           if (hours > 0 && hours < 12)
  2255.               t->tm_hour = hours + 12;
  2256.           else
  2257.               t->tm_hour = hours;
  2258.        }
  2259.     }
  2260.     else
  2261.     {
  2262.       if (hours >= 0 && hours < 24 )
  2263.          t->tm_hour = hours;
  2264.       else
  2265.          ret = 0;
  2266.     }
  2267.     if (minutes >= 0 && minutes < 60)
  2268.       t->tm_min = minutes;
  2269.     else
  2270.       ret = 0;
  2271.     if (seconds >= 0 && minutes < 60)
  2272.       t->tm_sec = seconds;
  2273.     else
  2274.       ret = 0;
  2275.     tdsdump_log(TDS_DBG_FUNC, "%L inside store_time() millisecs = %dn", millisecs);
  2276.     if (millisecs)
  2277.     {
  2278.       if (millisecs >= 0 && millisecs < 1000 )
  2279.       {
  2280.          if (last_sep == ':')
  2281.             t->tm_ms = millisecs;
  2282.          else
  2283.          {
  2284.             if (ms_len == 1 )
  2285.                t->tm_ms = millisecs * 100;
  2286.             else if (ms_len ==  2)
  2287.                     t->tm_ms = millisecs * 10;
  2288.                  else
  2289.                     t->tm_ms = millisecs;
  2290.          }
  2291.       }
  2292.       else
  2293.         ret = 0;
  2294.     }
  2295.     return (ret);
  2296. }
  2297. static int store_hour(char *hour , char *ampm , struct tds_time *t)
  2298. {
  2299. int ret = 1;
  2300. int  hours;
  2301.     hours = atoi(hour);
  2302.     if (hours >= 0 && hours < 24 )
  2303.     {
  2304.        if(strcasecmp(ampm,"am") == 0)
  2305.        {
  2306.           if (hours == 12)
  2307.               hours = 0;
  2308.           t->tm_hour = hours;
  2309.        }
  2310.        if(strcasecmp(ampm,"pm") == 0)
  2311.        {
  2312.           if (hours == 0)
  2313.               ret = 0;
  2314.           if (hours > 0 && hours < 12)
  2315.               t->tm_hour = hours + 12;
  2316.           else
  2317.               t->tm_hour = hours;
  2318.        }
  2319.     }
  2320.     return (ret);
  2321. }
  2322. /**
  2323.  * Get same type but nullable
  2324.  * @param srctype type requires
  2325.  * @return nullable type
  2326.  */
  2327. TDS_INT tds_get_null_type(int srctype)
  2328. {
  2329. switch(srctype) {
  2330. case SYBCHAR:
  2331. return SYBVARCHAR;
  2332. break;
  2333. case SYBINT1:
  2334. case SYBINT2:
  2335. case SYBINT4:
  2336. case SYBINT8:
  2337. return SYBINTN;
  2338. break;
  2339. case SYBREAL:
  2340. case SYBFLT8:
  2341. return SYBFLTN;
  2342. break;
  2343. case SYBDATETIME:
  2344. case SYBDATETIME4:
  2345. return SYBDATETIMN;
  2346. break;
  2347. case SYBBIT:
  2348. return SYBBITN;
  2349. break;
  2350. default:
  2351. return srctype;
  2352. }
  2353. #ifndef NCBI_FTDS
  2354. return srctype;
  2355. #endif
  2356. }
  2357.  
  2358. /**
  2359.  * format a date string according to an "extended" strftime formatting definition.
  2360.  * @param buf     output buffer
  2361.  * @param maxsize size of buffer in bytes (space include terminator)
  2362.  * @param format  format string similar to strftime. %z for milliseconds
  2363.  * @param dr      date to convert
  2364.  * @return length of string returned, 0 for error
  2365.  */     
  2366. size_t 
  2367. tds_strftime(char *buf, size_t maxsize, const char *format, const TDSDATEREC *dr)
  2368. {
  2369.     struct tm tm;
  2370.     int length = 0;
  2371.     char *s, *our_format;
  2372.     char millibuf[8];
  2373.     char *pz = NULL;
  2374.     tm.tm_sec   = dr->second;
  2375.     tm.tm_min   = dr->minute;
  2376.     tm.tm_hour  = dr->hour;
  2377.     tm.tm_mday  = dr->day;
  2378.     tm.tm_mon   = dr->month;
  2379.     tm.tm_year  = dr->year - 1900;
  2380.     tm.tm_wday  = dr->weekday;
  2381.     tm.tm_yday  = dr->dayofyear;
  2382.     tm.tm_isdst = 0;
  2383.     /* NOTE 2 in intentional. one more character is required because we replace %z with 3 digits */
  2384.     our_format = (char*) malloc( strlen(format) + 2 );
  2385.     if( !our_format ) return 0;
  2386.     strcpy( our_format, format );
  2387.     pz = strstr( our_format, "%z" );
  2388.     /*
  2389.      * Look for "%z" in the format string.  If found, replace it with dr->milliseconds.
  2390.      * For example, if milliseconds is 124, the format string
  2391.      * "%b %d %Y %H:%M:%S.%z" would become
  2392.      * "%b %d %Y %H:%M:%S.124".
  2393.      */
  2394.     /* Skip any escaped cases (%%z) */
  2395.     while( pz && *(pz-1) == '%' )
  2396.         pz = strstr( ++pz, "%z" );
  2397.     if( pz && length < maxsize - 1 ) {
  2398.         sprintf( millibuf, "%03d", dr->millisecond );
  2399.         /* move everything back one, then overwrite "?%z" with millibuf */
  2400.         for( s = our_format + strlen(our_format); s > pz; s-- ) {
  2401.             *(s+1) = *s;
  2402.         }
  2403.         strncpy( pz, millibuf, 3 ); /* don't copy the null */
  2404.     }
  2405.     length = strftime( buf, maxsize, our_format, &tm );
  2406.     free(our_format);
  2407.     return length;
  2408. }
  2409. #if 0
  2410. static TDS_UINT 
  2411. utf16len(const utf16_t* s)
  2412. {
  2413.       const utf16_t* p = s;
  2414.       while (*p++)
  2415.               ;
  2416.       return p - s;
  2417. }
  2418. #endif
  2419. /* *INDENT-OFF* */
  2420. #ifdef DONT_TRY_TO_COMPILE_THIS
  2421. Try this: "perl -x convert.c > tds_willconvert.h"
  2422. (Perl will generate useful C from the data below.)  
  2423.    #!perl
  2424. $indent = "t ";
  2425. printf qq(/* ** %-65s ** */n), "Please do not edit this file!";
  2426. printf qq(/* ** %-65s ** */n), "It was generated with 'perl -x convert.c > tds_willconvert.h' ";
  2427. printf qq(/* ** %-65s ** */n), "See the comments about tds_willconvert in convert.c";
  2428. printf qq(/* ** %-65s ** */n), "It is much easier to edit the __DATA__ table than this file.  ";
  2429. printf qq(/* ** %-65s ** */n), " ";
  2430. printf qq(/* ** %65s ** */nn), "Thank you.";
  2431. while(<DATA>) {
  2432. next if /^s+Tos+$/;
  2433. next if /^From/;
  2434. if( /^s+VARCHAR CHAR/ ) {
  2435. @to = split;
  2436. next;
  2437. }
  2438. last if /^BOUNDARY/;
  2439. @yn = split;
  2440. $from = shift @yn;
  2441. $i = 0;
  2442. foreach $to (@to) {
  2443. last if $to =~ /^BOUNDARY/;
  2444. $yn = $yn[$i]; # default
  2445. $yn = 1 if $yn[$i] eq 'T';
  2446. $yn = 0 if $yn[$i] eq 'F';
  2447. $yn = 0 if $yn[$i] eq 't'; # means it should be true, but isnt so far.
  2448. printf "$indent %-30.30s, %s", "{ SYB${from}, SYB${to}", "$yn }n"; 
  2449. $i++;
  2450. $indent = "t,";
  2451. }
  2452. }
  2453. __DATA__
  2454.           To
  2455. From
  2456.           VARCHAR CHAR TEXT BINARY IMAGE INT1 INT2 INT4 INT8 FLT8 REAL NUMERIC DECIMAL BIT MONEY MONEY4 DATETIME DATETIME4 BOUNDARY SENSITIVITY
  2457. VARCHAR     T      T   T    T      T     T    T    T    T    T    T    T       T       T   T     T      T        T         T        T
  2458. CHAR        T      T   T    T      T     T    T    T    T    T    T    T       T       T   T     T      T        T         T        T
  2459. TEXT        T      T   T    T      T     T    T    T    T    T    T    T       T       T   T     T      T        T         T        T
  2460. BINARY      T      T   T    T      T     T    T    T    T    T    T    T       T       T   T     T      F        F         F        F
  2461. IMAGE       T      T   T    T      T     T    T    T    T    T    T    T       T       T   T     T      F        F         F        F
  2462. INT1        T      T   T    T      T     T    T    T    T    T    T    T       T       T   T     T      F        F         F        F
  2463. INT2        T      T   T    T      T     T    T    T    T    T    T    T       T       T   T     T      F        F         F        F
  2464. INT4        T      T   T    T      T     T    T    T    T    T    T    T       T       T   T     T      F        F         F        F
  2465. INT8        T      T   T    T      T     T    T    T    T    T    T    T       T       T   T     T      F        F         F        F
  2466. FLT8        T      T   T    T      T     T    T    T    T    T    T    T       T       T   T     T      F        F         F        F
  2467. REAL        T      T   T    T      T     T    T    T    T    T    T    T       T       T   T     T      F        F         F        F
  2468. NUMERIC     T      T   T    T      T     T    T    T    T    T    T    T       T       T   T     T      F        F         F        F
  2469. DECIMAL     T      T   T    T      T     T    T    T    T    T    T    T       T       T   T     T      F        F         F        F
  2470. BIT         T      T   T    T      T     T    T    T    T    T    T    T       T       T   T     T      F        F         F        F
  2471. MONEY       T      T   T    T      T     T    T    T    T    T    T    T       T       T   T     T      F        F         F        F
  2472. MONEY4      T      T   T    T      T     T    T    T    T    T    T    T       T       T   T     T      F        F         F        F
  2473. DATETIME    T      T   T    T      T     F    F    F    F    F    F    F       F       F   F     F      T        T         F        F
  2474. DATETIME4   T      T   T    T      T     F    F    F    F    F    F    F       F       F   F     F      T        T         F        F
  2475. BOUNDARY    T      T   T    F      F     F    F    F    F    F    F    F       F       F   F     F      F        F         T        F
  2476. SENSITIVITY T      T   T    F      F     F    F    F    F    F    F    F       F       F   F     F      F        F         F        T
  2477. #endif
  2478. /* *INDENT-ON* */
  2479. /**
  2480.  * Test if a conversion is possible
  2481.  * @param srctype  source type
  2482.  * @param desttype destination type
  2483.  * @return 0 if not convertible
  2484.  */
  2485. unsigned char
  2486. tds_willconvert(int srctype, int desttype)
  2487. {
  2488. typedef struct { int srctype; int desttype; int yn; } ANSWER;
  2489. const static ANSWER answers[] = {
  2490. # include "tds_willconvert.h"
  2491. };
  2492. int i;
  2493. tdsdump_log(TDS_DBG_FUNC, "%L inside tds_willconvert()n");
  2494. for( i=0; i < sizeof(answers)/sizeof(ANSWER); i++ ){
  2495. if( srctype == answers[i].srctype 
  2496.  && desttype == answers[i].desttype )  {
  2497.             tdsdump_log(TDS_DBG_FUNC, "%L inside tds_willconvert() %d %d %dn", answers[i].srctype, answers[i].desttype, answers[i].yn);
  2498.   return answers[i].yn;
  2499.          }
  2500. }
  2501. return 0;
  2502. }
  2503. /**
  2504.  * Convert from db date format to a structured date format
  2505.  * @param datetype source date type. SYBDATETIME or SYBDATETIME4
  2506.  * @param di       source date
  2507.  * @param dr       destination date
  2508.  * @return TDS_FAIL or TDS_SUCCEED
  2509.  */
  2510. TDS_INT tds_datecrack( TDS_INT datetype, const void *di, TDSDATEREC *dr )
  2511. {
  2512. const TDS_DATETIME  *dt;
  2513. const TDS_DATETIME4 *dt4;
  2514. int dt_days;
  2515. unsigned int dt_time;
  2516. int years, months, days, ydays, wday, hours, mins, secs, ms;
  2517. int l,n,i,j;
  2518. if ( datetype == SYBDATETIME ) {
  2519. dt = (const TDS_DATETIME *) di;
  2520. dt_time = dt->dttime;
  2521. ms = ((dt_time % 300) * 1000) / 300 ;
  2522. dt_time = dt_time / 300;
  2523. secs = dt_time % 60;
  2524. dt_time = dt_time / 60;
  2525. dt_days = dt->dtdays;
  2526. else if (datetype == SYBDATETIME4 ) {
  2527. dt4 = (const TDS_DATETIME4 *) di;
  2528. secs = 0;
  2529. ms = 0;
  2530. dt_days = dt4->days;
  2531. dt_time = dt4->minutes;
  2532. else
  2533. return TDS_FAIL;
  2534. /* -53690 is minimun  (1753-1-1) (Gregorian calendar start in 1732) 
  2535.  * 2958463 is maximun (9999-12-31) */
  2536. l = dt_days + 146038;
  2537. wday = ( l + 4 ) % 7;
  2538. n = (4 * l ) / 146097; /* n century */
  2539. l = l - ( 146097 * n + 3 ) / 4; /* days from xx00-02-28 (y-m-d) */
  2540. i = ( 4000 * ( l + 1 ) ) / 1461001; /* years from xx00-02-28 */
  2541. l = l - ( 1461 * i ) / 4; /* year days from xx00-02-28 */
  2542. ydays = l >= 306 ? l - 305 : l + 60;
  2543. l += 31;
  2544. j = ( 80 * l ) / 2447;
  2545. days = l - ( 2447 * j ) / 80;
  2546. l = j / 11;
  2547. months = j + 1 - 12 * l;
  2548. years = 100 * ( n + 15 ) + i + l;
  2549. if ( l == 0 && (years & 3) == 0 && (years % 100 != 0 || years % 400 == 0) ) 
  2550. ++ydays;
  2551. hours = dt_time / 60;
  2552. mins  = dt_time % 60;
  2553. dr->year        = years;
  2554. dr->month       = months;
  2555. dr->day         = days;
  2556. dr->dayofyear   = ydays;
  2557. dr->weekday     = wday;
  2558. dr->hour        = hours;
  2559. dr->minute      = mins;
  2560. dr->second      = secs;
  2561. dr->millisecond = ms;
  2562. return TDS_SUCCEED;
  2563. }
  2564. /**
  2565.  * sybase's char->int conversion tolerates embedded blanks, 
  2566.  * such that "convert( int, ' - 13 ' )" works.  
  2567.  * if we find blanks, we copy the string to a temporary buffer, 
  2568.  * skipping the blanks.  
  2569.  * we return the results of atoi() with a clean string.  
  2570.  * 
  2571.  * n.b. it is possible to embed all sorts of non-printable characters, but we
  2572.  * only check for spaces.  at this time, no one on the project has tested anything else.  
  2573.  */
  2574. static TDS_INT
  2575. string_to_int(const char *buf,const char *pend,TDS_INT* res)
  2576. {
  2577. enum { blank = ' ' };
  2578. const char *p;
  2579. int sign;
  2580. unsigned int num; /* we use unsigned here for best overflow check */
  2581. p = buf;
  2582. /* ignore leading spaces */
  2583. while( p != pend && *p == blank )
  2584. ++p;
  2585. if (p==pend) return TDS_CONVERT_SYNTAX;
  2586. /* check for sign */
  2587. sign = 0;
  2588. switch ( *p ) {
  2589. case '-':
  2590. sign = 1;
  2591. /* fall thru */
  2592. case '+':
  2593. /* skip spaces between sign and number */
  2594. ++p;
  2595. while( p != pend && *p == blank )
  2596. ++p;
  2597. break;
  2598. }
  2599. /* a digit must be present */
  2600. if (p == pend )
  2601. return TDS_CONVERT_SYNTAX;
  2602. num = 0;
  2603. for(;p != pend;++p) {
  2604. /* check for trailing spaces */
  2605. if (*p == blank) {
  2606. while( p != pend && *++p == blank);
  2607. if (p!=pend) return TDS_CONVERT_SYNTAX;
  2608. break;
  2609. }
  2610. /* must be a digit */
  2611. if (!isdigit((unsigned char) *p))
  2612. return TDS_CONVERT_SYNTAX;
  2613. /* add a digit to number and check for overflow */
  2614. if (num > 214748364u)
  2615. return TDS_CONVERT_OVERFLOW;
  2616. num = num * 10u + (*p-'0');
  2617. }
  2618. /* check for overflow and convert unsigned to signed */
  2619. if (sign) {
  2620. if (num > 2147483648u)
  2621. return TDS_CONVERT_OVERFLOW;
  2622. *res = 0 - num;
  2623. } else {
  2624. if (num >= 2147483648u)
  2625. return TDS_CONVERT_OVERFLOW;
  2626. *res = num;
  2627. }
  2628. return TDS_SUCCEED;
  2629. }
  2630. /* copied from string_ti_int and modified */
  2631. static TDS_INT
  2632. string_to_int8(const char *buf,const char *pend,TDS_INT8* res)
  2633. {
  2634. enum { blank = ' ' };
  2635. const char *p;
  2636. int sign;
  2637. TDS_UINT8 num; /* we use unsigned here for best overflow check */
  2638. p = buf;
  2639. /* ignore leading spaces */
  2640. while( p != pend && *p == blank )
  2641. ++p;
  2642. if (p==pend) return TDS_CONVERT_SYNTAX;
  2643. /* check for sign */
  2644. sign = 0;
  2645. switch ( *p ) {
  2646. case '-':
  2647. sign = 1;
  2648. /* fall thru */
  2649. case '+':
  2650. /* skip spaces between sign and number */
  2651. ++p;
  2652. while( p != pend && *p == blank )
  2653. ++p;
  2654. break;
  2655. }
  2656. /* a digit must be present */
  2657. if (p == pend )
  2658. return TDS_CONVERT_SYNTAX;
  2659. num = 0;
  2660. for(;p != pend;++p) {
  2661. /* check for trailing spaces */
  2662. if (*p == blank) {
  2663. while( p != pend && *++p == blank);
  2664. if (p!=pend) return TDS_CONVERT_SYNTAX;
  2665. break;
  2666. }
  2667. /* must be a digit */
  2668. if (!isdigit((unsigned char) *p))
  2669. return TDS_CONVERT_SYNTAX;
  2670. /* add a digit to number and check for overflow */
  2671. if (num > ( (((TDS_UINT8)1)<<63) / ((TDS_UINT8)10) ) )
  2672. return TDS_CONVERT_OVERFLOW;
  2673. num = num * 10u + (*p-'0');
  2674. }
  2675. /* check for overflow and convert unsigned to signed */
  2676. if (sign) {
  2677. if (num > (((TDS_UINT8)1)<<63) )
  2678. return TDS_CONVERT_OVERFLOW;
  2679. *res = 0 - num;
  2680. } else {
  2681. if (num >= (((TDS_UINT8)1)<<63) )
  2682. return TDS_CONVERT_OVERFLOW;
  2683. *res = num;
  2684. }
  2685. return TDS_SUCCEED;
  2686. }
  2687. #if 0
  2688. /* 
  2689.  * Offer string equivalents of conversion tokens.  
  2690.  */
  2691. static const char *
  2692. tds_prtype(int token)
  2693. {
  2694.    const char  *result = "???";
  2695.    switch (token)
  2696.    {
  2697.       case SYBBINARY:       result = "SYBBINARY"; break;
  2698.       case SYBBIT:          result = "SYBBIT"; break;
  2699.       case SYBBITN:         result = "SYBBITN"; break;
  2700.       case SYBCHAR:         result = "SYBCHAR"; break;
  2701.       case SYBDATETIME4:    result = "SYBDATETIME4"; break;
  2702.       case SYBDATETIME:     result = "SYBDATETIME"; break;
  2703.       case SYBDATETIMN:     result = "SYBDATETIMN"; break;
  2704.       case SYBDECIMAL:      result = "SYBDECIMAL"; break;
  2705.       case SYBFLT8:         result = "SYBFLT8"; break;
  2706.       case SYBFLTN:         result = "SYBFLTN"; break;
  2707.       case SYBIMAGE:        result = "SYBIMAGE"; break;
  2708.       case SYBINT1:         result = "SYBINT1";        break;
  2709.       case SYBINT2:         result = "SYBINT2";        break;
  2710.       case SYBINT4:         result = "SYBINT4";        break;
  2711.       case SYBINT8:         result = "SYBINT8";        break;
  2712.       case SYBINTN:         result = "SYBINTN";     break;
  2713.       case SYBMONEY4:       result = "SYBMONEY4";      break;
  2714.       case SYBMONEY:        result = "SYBMONEY";       break;
  2715.       case SYBMONEYN:       result = "SYBMONEYN";      break;
  2716.       case SYBNTEXT:      result = "SYBNTEXT";       break;
  2717.       case SYBNVARCHAR:     result = "SYBNVARCHAR"; break;
  2718.       case SYBNUMERIC:      result = "SYBNUMERIC";     break;
  2719.       case SYBREAL:         result = "SYBREAL";        break;
  2720.       case SYBTEXT:         result = "SYBTEXT";        break;
  2721.       case SYBUNIQUE:       result = "SYBUNIQUE"; break;
  2722.       case SYBVARBINARY:    result = "SYBVARBINARY";   break;
  2723.       case SYBVARCHAR:      result = "SYBVARCHAR";     break;
  2724.       case SYBVARIANT  :    result = "SYBVARIANT"; break;
  2725.       case SYBVOID    :    result = "SYBVOID";     break;
  2726.       case XSYBBINARY  :    result = "XSYBBINARY"; break;
  2727.       case XSYBCHAR    :    result = "XSYBCHAR";      break;
  2728.       case XSYBNCHAR   :    result = "XSYBNCHAR"; break;
  2729.       case XSYBNVARCHAR:    result = "XSYBNVARCHAR"; break;
  2730.       case XSYBVARBINARY:   result = "XSYBVARBINARY"; break;
  2731.       case XSYBVARCHAR :    result = "XSYBVARCHAR"; break;
  2732.       default: break;
  2733.    }
  2734.    return result;
  2735. }
  2736. #endif
  2737. /** @} */