⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 convert.c

📁 ncbi源码
💻 C
📖 第 1 页 / 共 5 页
字号:
/* * =========================================================================== * PRODUCTION $Log: convert.c,v $ * PRODUCTION Revision 1000.1  2003/11/17 22:20:23  gouriano * PRODUCTION PRODUCTION: UPGRADED [ORIGINAL] Dev-tree R1.2 * PRODUCTION * =========================================================================== *//* FreeTDS - Library of routines accessing Sybase and Microsoft databases * Copyright (C) 1998-1999  Brian Bruns * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Library General Public * License as published by the Free Software Foundation; either * version 2 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU * Library General Public License for more details. * * You should have received a copy of the GNU Library General Public * License along with this library; if not, write to the * Free Software Foundation, Inc., 59 Temple Place - Suite 330, * Boston, MA 02111-1307, USA. */#include <tds_config.h>#include "tdsutil.h"#include "tds.h"#include "tdsconvert.h"# include <time.h>#include <assert.h>#include <errno.h>#ifdef DMALLOC#include <dmalloc.h>#endif#include <string.h>#ifndef HAVE_ATOLLstatic long intatoll(const char *nptr){	return atol(nptr);}#endif#ifdef NCBI_FTDSextern const int g__numeric_bytes_per_prec[];extern char *tds_money_to_string(TDS_MONEY *money, char *s);#define TDS_VECTOR_SIZE(x) (sizeof(x)/sizeof(x[0]))#endifstatic char  software_version[]   = "$Id: convert.c,v 1000.1 2003/11/17 22:20:23 gouriano Exp $";static void *no_unused_var_warn[] = {software_version,                                     no_unused_var_warn};typedef unsigned short utf16_t;static TDS_INT tds_convert_int1(int srctype, const TDS_CHAR *src, int desttype, CONV_RESULT *cr);static TDS_INT tds_convert_int2(int srctype, const TDS_CHAR *src, int desttype, CONV_RESULT *cr);static TDS_INT tds_convert_int4(int srctype, const TDS_CHAR *src, int desttype, CONV_RESULT *cr);static TDS_INT tds_convert_int8(int srctype, const TDS_CHAR *src, int desttype, CONV_RESULT *cr);static int  string_to_datetime(const char *datestr, int desttype, CONV_RESULT *cr );#define test_alloc(x) {if ((x)==NULL) return TDS_CONVERT_NOMEM;}#define IS_TINYINT(x) ( 0 <= (x) && (x) <= 0xff )#define IS_SMALLINT(x) ( -32768 <= (x) && (x) <= 32767 )/* f77: I don't write -2147483648, some compiler seem to have some problem  * with this constant although is a valid 32bit value */#define IS_INT(x) ( (-2147483647l-1l) <= (x) && (x) <= 2147483647l )/** * \defgroup convert Conversion *//** \addtogroup convert *  \@{  *//** * convert a number in string to a TDSNUMERIC * @return sizeof(TDS_NUMERIC) on success, TDS_CONVERT_* failure code on failure  */static int string_to_numeric(const char *instr, const char *pend, CONV_RESULT *cr);/** * convert a zero terminated string to NUMERIC * @return sizeof(TDS_NUMERIC) on success, TDS_CONVERT_* failure code on failure  */static int stringz_to_numeric(const char *instr, CONV_RESULT *cr);/** * convert a number in string to TDS_INT  * @return TDS_CONVERT_* failure code if failure */static TDS_INT string_to_int(const char *buf,const char *pend,TDS_INT* res);#define TDS_CONVERT_NOAVAIL -2/** * convert a number in string to TDS_INT8 * @return TDS_CONVERT_* failure code if failure */static TDS_INT string_to_int8(const char *buf,const char *pend,TDS_INT8* res);static int store_hour(char *, char *, struct tds_time *);static int store_time(char *, struct tds_time * );static int store_yymmdd_date(char *, struct tds_time *);static int store_monthname(char *, struct tds_time *);static int store_numeric_date(char *, struct tds_time *);static int store_mday(char *, struct tds_time *);static int store_year(int,  struct tds_time *);/* static int days_this_year (int years); */static int is_timeformat(char *);static int is_numeric(char *);static int is_alphabetic(char *);static int is_ampm(char *);static int is_monthname(char *);static int is_numeric_dateformat(char *);#if 0static TDS_UINT utf16len(const utf16_t* s);static const char *tds_prtype(int token);#endif/** * Return type suitable for conversions (convert all nullable types to  * fixed type) * @param srctype type to convert * @param colsize size of type * @result type for conversion */int tds_get_conversion_type(int srctype, int colsize){	switch(srctype)	{	case SYBINTN:		switch(colsize) {		case 8: return SYBINT8;		case 4: return SYBINT4;		case 2: return SYBINT2;		case 1: return SYBINT1;		}		break;	case SYBFLTN:		switch(colsize) {		case 8:	return SYBFLT8;		case 4:	return SYBREAL;		}		break;	case SYBDATETIMN:		switch(colsize) {		case 8:	return SYBDATETIME;		case 4: return SYBDATETIME4;		}		break;	case SYBMONEYN:		switch(colsize) {		case 8: return SYBMONEY;		case 4: return SYBMONEY4;		}		break;	/* altough tds_conmvert handle SYBBITN other routine use this 	 * function to retrieve not variant type */	case SYBBITN:		return SYBBIT;		break;	}	return srctype;}/** * Copy a terminated string to result and return len or TDS_CONVERT_NOMEM */static TDS_INT string_to_result(const char* s,CONV_RESULT* cr){int len = strlen(s);	cr->c = (TDS_CHAR *) malloc(len + 1);	test_alloc(cr->c);	memcpy(cr->c, s, len + 1);	return len;}/** * Copy binary data to to result and return len or TDS_CONVERT_NOMEM */static TDS_INTbinary_to_result(const void* data,size_t len,CONV_RESULT* cr){	cr->ib = (TDS_CHAR *) malloc(len);	test_alloc(cr->ib);	memcpy(cr->ib, data, len);	return len;}/* TODO implement me *//*static TDS_INT tds_convert_ntext(int srctype,TDS_CHAR *src,TDS_UINT srclen,      int desttype, CONV_RESULT *cr){      return TDS_CONVERT_NOAVAIL;}*/static TDS_INT tds_convert_binary(int srctype, const TDS_UCHAR *src, TDS_INT srclen,	int desttype, CONV_RESULT *cr){int cplen;int s;char *c;char hex2[3];   switch(desttype) {      case SYBCHAR:      case SYBVARCHAR:      case SYBTEXT:	 /* NOTE: Do not prepend 0x to string.  	  * The libraries all expect a bare string, without a 0x prefix. 	  * Applications such as isql and query analyzer provide the "0x" prefix. */         /* 2 * source length + 1 for terminator */         cr->c = (TDS_CHAR *) malloc((srclen * 2) + 1);		test_alloc(cr->c);         c = cr->c;         for (s = 0; s < srclen; s++) {             sprintf(hex2, "%02x", src[s]);             *c++ = hex2[0];             *c++ = hex2[1];         }         *c = '\0';         return (srclen * 2);         break;      case SYBIMAGE:      case SYBBINARY:      case SYBVARBINARY:	 return binary_to_result(src, srclen, cr);         break;	case SYBINT1:	case SYBINT2:	case SYBINT4:	case SYBINT8:	case SYBMONEY4:	case SYBMONEY:	case SYBREAL:	case SYBFLT8:		cplen = get_size_by_type(desttype);		if (cplen <= srclen)			return binary_to_result(src, cplen, cr);		cr->ib = (TDS_CHAR *) malloc(cplen);		test_alloc(cr->ib);		memcpy(cr->ib, src, srclen);		memset(cr->ib+srclen, 0, cplen-srclen);		return cplen;		break;		/* conversions not allowed */	case SYBDATETIME4:	case SYBDATETIME:	case SYBDATETIMN:	/* TODO should we do some test for these types or work as ints ?? */	case SYBDECIMAL:	case SYBNUMERIC:	case SYBBIT:	case SYBBITN:	default:		return TDS_CONVERT_NOAVAIL;		break;   }#ifndef NCBI_FTDS   return TDS_CONVERT_FAIL;#endif}static TDS_INT tds_convert_char(int srctype, const TDS_CHAR *src, TDS_UINT srclen,	int desttype, CONV_RESULT *cr){int           i, j;unsigned char hex1;TDS_INT8     mymoney;TDS_INT      mymoney4;char         mynumber[39];const char *ptr, *pend;int point_found, places;TDS_INT tds_i;TDS_INT8 tds_i8;TDS_INT rc;      switch(desttype) {      case SYBCHAR:      case SYBVARCHAR:      case SYBTEXT:		 cr->c = (TDS_CHAR *) malloc(srclen + 1);		test_alloc(cr->c);		 memcpy(cr->c, src, srclen);		 cr->c[srclen] = 0;         return srclen; 		 break;	case SYBBINARY:	case SYBIMAGE:	case SYBVARBINARY:         /* skip leading "0x" or "0X" */         if (src[0] == '0' && ( src[1] == 'x' || src[1] == 'X' )) {            src += 2;            srclen -= 2;         }	/* ignore trailing blanks and nulls */	/* FIXME is good to ignore null ?? */	while( srclen > 0 && (src[srclen-1] == ' ' || src[srclen-1] == '\0') )		--srclen;         /* a binary string output will be half the length of */         /* the string which represents it in hexadecimal     */		/* if srclen if odd we must add a "0" before ... */	j = 0; /* number where to start converting */	if (srclen & 1) {		++srclen; j = 1; --src;	}        cr->ib = (TDS_CHAR *) malloc(srclen / 2);	test_alloc(cr->ib);#if 0         /* hey, I know this looks a bit cruddy,   */         /* and I'm sure it can all be done in one */         /* statement, so go on, make my day!      */         for ( i = 0, j = 0; i < srclen; i++, j++ ) {            inp = src[i];            if ( inp > 47 && inp < 58 )            /* '0' thru '9' */               hex1 = inp - 48;            else if ( inp > 96 && inp < 103 )      /* 'a' thru 'f' */                     hex1 = inp - 87;                 else if ( inp > 64 && inp < 71 )  /* 'A' thru 'F' */                          hex1 = inp - 55;                      else {                          fprintf(stderr,"error_handler:  Attempt to convert data stopped by syntax error in source field \n");                          return;                      }                  hex1 = hex1 << 4;                  i++;                  inp = src[i];            if ( inp > 47 && inp < 58 )            /* '0' thru '9' */               hex1 = hex1  | (inp - 48);            else if ( inp > 96 && inp < 103 )      /* 'a' thru 'f' */                     hex1 = hex1 | (inp - 87);                 else if ( inp > 64 && inp < 71 )  /* 'A' thru 'F' */                          hex1 =  hex1 | (inp - 55);                      else {                          fprintf(stderr,"error_handler:  Attempt to convert data stopped by syntax error in source field \n");                          return;                      }                  cr->ib[j] = hex1;         }#else		for ( i=srclen; --i >= j; ) {			hex1 = src[i];						if( '0' <= hex1 && hex1 <= '9' )				hex1 &= 0x0f;			else {				hex1 &= 0x20 ^ 0xff;	/* mask off 0x20 to ensure upper case */				if( 'A' <= hex1 && hex1 <= 'F' ) {					hex1 -= ('A'-10);				} else {					tdsdump_log(TDS_DBG_INFO1,"error_handler:  attempt to convert data stopped by syntax error in source field \n");					return TDS_CONVERT_SYNTAX;				}			}			assert( hex1 < 0x10 );						if( i & 1 ) 				cr->ib[i/2] = hex1;			else				cr->ib[i/2] |= hex1 << 4;		}#endif         return srclen / 2;         break;      case SYBINT1:		if ((rc = string_to_int(src, src + srclen, &tds_i)) < 0)			return rc;		if (!IS_TINYINT(tds_i))			return TDS_CONVERT_OVERFLOW;		cr->ti = tds_i;		return sizeof(TDS_TINYINT);         	break;      case SYBINT2:		if ((rc = string_to_int(src, src + srclen, &tds_i)) < 0)			return rc;		if (!IS_SMALLINT(tds_i))			return TDS_CONVERT_OVERFLOW;		cr->si = tds_i;		return sizeof(TDS_SMALLINT);         	break;      case SYBINT4:		if ((rc = string_to_int(src, src + srclen, &tds_i)) < 0)			return rc;		cr->i = tds_i;		return sizeof(TDS_INT);		break;	case SYBINT8:		if ((rc = string_to_int8(src, src + srclen, &tds_i8)) < 0)			return rc;		cr->bi = tds_i8;		return sizeof(TDS_INT8);		break;	case SYBFLT8:		cr->f = atof(src);		return sizeof(TDS_FLOAT);		break;      case SYBREAL:         	cr->r = atof(src);		return sizeof(TDS_REAL);         	break;      case SYBBIT:      case SYBBITN:		if ((rc = string_to_int(src, src + srclen, &tds_i)) < 0)			return TDS_CONVERT_OVERFLOW;		cr->ti = tds_i ? 1 : 0;		return sizeof(TDS_TINYINT);		break;      case SYBMONEY:      case SYBMONEY4:		/* TODO code similar to string_to_numeric... */		i           = 0;		places      = 0;		point_found = 0;		pend        = src + srclen;		/* skip leading blanks */		for (ptr = src; ptr != pend && *ptr == ' '; ++ptr);		switch ( ptr != pend ? *ptr : 0 ) {		case '-':			mynumber[i++] = '-';			/* fall through*/		case '+':			ptr++;			for (; ptr != pend && *ptr == ' '; ++ptr);			break;		}		for(; ptr != pend; ptr++)                      /* deal with the rest */		{			if (isdigit((unsigned char) *ptr) )                   /* it's a number */			{				/* no more than 4 decimal digits */				if (places < 4)					mynumber[i++] = *ptr;				/* assure not buffer overflow */				if (i==30) return TDS_CONVERT_OVERFLOW;				if (point_found) {                 /* if we passed a decimal point */					/* count digits after that point  */					++places;				}			}			else if (*ptr == '.')                /* found a decimal point */			{				if (point_found)             /* already had one. error */					return TDS_CONVERT_SYNTAX;				point_found = 1;			}			else                            /* first invalid character */				return TDS_CONVERT_SYNTAX;   /* lose the rest.          */		}		for ( j = places; j < 4; j++ )			mynumber[i++] = '0';		mynumber[i] = 0;	 /* FIXME overflow not handled */         if (desttype == SYBMONEY) {            mymoney = atoll(mynumber);            memcpy(&(cr->m), &mymoney, sizeof(TDS_MONEY) );             return sizeof(TDS_MONEY);         } else {            mymoney4 = atol(mynumber);            memcpy(&(cr->m4), &mymoney4, sizeof(TDS_MONEY4) );             return sizeof(TDS_MONEY4);         }         break;      case SYBDATETIME:		 return string_to_datetime(src, SYBDATETIME, cr);		 break;      case SYBDATETIME4:		 return string_to_datetime(src, SYBDATETIME4, cr);		 break;      case SYBNUMERIC:      case SYBDECIMAL:		return string_to_numeric(src, src+srclen, cr);		break;	 case SYBUNIQUE: {		unsigned n = 0;		char c;		 /* parse formats like XXXXXXXX-XXXX-XXXX-XXXXXXXXXXXXXXXX 

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -