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

📄 convert.c

📁 ncbi源码
💻 C
📖 第 1 页 / 共 5 页
字号:
			return sizeof(TDS_REAL);			break;		case SYBFLT8:			cr->f = the_value;			return sizeof(TDS_FLOAT);			break;		case SYBNUMERIC:		case SYBDECIMAL:			sprintf(tmp_str,"%.15g", the_value);			return stringz_to_numeric(tmp_str, cr);			break;	/* not allowed */	case SYBUNIQUE:	case SYBDATETIME4:	case SYBDATETIME:	case SYBDATETIMN:	default:		return TDS_CONVERT_NOAVAIL;		break;	}#ifndef NCBI_FTDS	return TDS_CONVERT_FAIL;#endif}static TDS_INTtds_convert_unique(int srctype, const TDS_CHAR *src, TDS_INT srclen,	int desttype, CONV_RESULT *cr){/* Raw data is equivalent to structure and always aligned, so this cast    is portable */const TDS_UNIQUE *u = (const TDS_UNIQUE *) src;char buf[37];	switch(desttype) {   	   case SYBCHAR:   	   case SYBTEXT:   	   case SYBVARCHAR:		    sprintf(buf,"%08X-%04X-%04X-%02X%02X-%02X%02X%02X%02X%02X%02X",			        (int)u->Data1,(int)u->Data2,(int)u->Data3,        			u->Data4[0], u->Data4[1],        			u->Data4[2], u->Data4[3], u->Data4[4],        			u->Data4[5], u->Data4[6], u->Data4[7]);			return string_to_result(buf,cr);   			break;		case SYBBINARY:		case SYBIMAGE:		case SYBVARBINARY:			return binary_to_result(src,sizeof(TDS_UNIQUE),cr);			break;   		case SYBUNIQUE:			/* Here we can copy raw to structure because we adjust			   byte order in tds_swap_datatype */			memcpy (&(cr->u), src, sizeof(TDS_UNIQUE));			return sizeof(TDS_UNIQUE);			break;		/* no not warning for not convertible types */		case SYBBIT:		case SYBBITN:		case SYBINT1:		case SYBINT2:		case SYBINT4:		case SYBINT8:		case SYBMONEY4:		case SYBMONEY:		case SYBDATETIME4:		case SYBDATETIME:		case SYBDATETIMN:		case SYBREAL:		case SYBFLT8:		default:			return TDS_CONVERT_NOAVAIL;			break;	}#ifndef NCBI_FTDS	return TDS_CONVERT_FAIL;#endif}/** * tds_convert * convert a type to another. * If you convert to SYBDECIMAL/SYBNUMERIC you MUST initialize precision  * and scale of cr. * Do not expect string to be zero terminated. Databases support zero inside * string. Doing strlen on result may result on data loss or even core. * Use memcpy to copy destination using length returned. * This function do not handle NULL, srclen should be >0, if not undefinited  * behaviour... * @param tds_ctx  context (used in conversion to data and to return messages) * @param srctype  type of source * @param src      pointer to source data to convert * @param srclen   length in bytes of source (not counting terminator or strings) * @param desttype type of destination * @param cr       structure to hold result * @return length of result or TDS_CONVERT_* failure code on failure. All TDS_CONVERT_* constants are <0. */TDS_INT tds_convert(TDSCONTEXT *tds_ctx, int srctype, const TDS_CHAR *src,		TDS_UINT srclen, int desttype, CONV_RESULT *cr){TDS_INT length = 0;	switch (srctype) {		case SYBCHAR:		case SYBVARCHAR:		case SYBTEXT:			length = tds_convert_char(srctype, src, srclen, desttype, cr);			break;		case SYBMONEY4:			length = tds_convert_money4(srctype,src, srclen, desttype, cr);			break;		case SYBMONEY:			length = tds_convert_money(srctype, src, desttype, cr);			break;		case SYBNUMERIC:		case SYBDECIMAL:			length = tds_convert_numeric(srctype, (const TDS_NUMERIC *) src, srclen, desttype, cr);			break;		case SYBBIT:		case SYBBITN:			length = tds_convert_bit(srctype, src, desttype, cr);			break;		case SYBINT1:			length = tds_convert_int1(srctype, src, desttype, cr);			break;		case SYBINT2:			length = tds_convert_int2(srctype, src, desttype, cr);			break;		case SYBINT4:			length = tds_convert_int4(srctype, src, desttype, cr);			break;		case SYBINT8:			length = tds_convert_int8(srctype, src, desttype, cr);			break;		case SYBREAL:			length = tds_convert_real(srctype, src, desttype, cr);			break;		case SYBFLT8:			length = tds_convert_flt8(srctype, src, desttype, cr);			break;		case SYBDATETIME:			length = tds_convert_datetime(tds_ctx, srctype, src,					desttype, cr);			break;		case SYBDATETIME4:			length = tds_convert_datetime4(tds_ctx, srctype, src,					desttype, cr);			break;		case SYBIMAGE:		case SYBBINARY:		case SYBVARBINARY:			length = tds_convert_binary(srctype,				(const TDS_UCHAR *) src, srclen, desttype, cr);			break;		case SYBUNIQUE:			length = tds_convert_unique(srctype, src, srclen,					desttype, cr);			break;		case SYBNVARCHAR:		case SYBNTEXT:		default:			return TDS_CONVERT_NOAVAIL;			break;	}/* fix MONEY case */#if !defined(WORDS_BIGENDIAN) && defined(HAVE_INT64)	if (length > 0 && desttype == SYBMONEY) {		cr->m.mny = 			((TDS_UINT8)cr->m.mny) >> 32 | (cr->m.mny << 32);	}#endif	return length;}static int string_to_datetime(const char *instr, int desttype, CONV_RESULT *cr){enum states { GOING_IN_BLIND,              PUT_NUMERIC_IN_CONTEXT,              DOING_ALPHABETIC_DATE,              STRING_GARBLED };char *in;char *tok;char *lasts;char last_token[32];int   monthdone = 0;int   yeardone  = 0;int   mdaydone  = 0;struct tds_time mytime;struct tds_time *t;unsigned int dt_time;TDS_INT      dt_days;int          i;int current_state;	memset(&mytime, '\0', sizeof(struct tds_time));	t = &mytime;	in = (char *)malloc(strlen(instr)+1);	test_alloc(in);	strcpy (in , instr );	tok = strtok_r(in, " ,", &lasts);	current_state = GOING_IN_BLIND;	while (tok != (char *) NULL) {		switch (current_state) {			case GOING_IN_BLIND :				/* If we have no idea of current context, then if we have */				/* encountered a purely alphabetic string, it MUST be an  */				/* alphabetic month name or prefix...                     */				if (is_alphabetic(tok)) {					if (is_monthname(tok)) {						store_monthname(tok, t);						monthdone++;						current_state = DOING_ALPHABETIC_DATE;					} else {						current_state = STRING_GARBLED;					}				}              /* ...whereas if it is numeric, it could be a number of   */              /* things...                                              */              else if (is_numeric(tok)) {                      switch(strlen(tok)) {                         /* in this context a 4 character numeric can   */                         /* ONLY be the year part of an alphabetic date */                         case 4:                            store_year(atoi(tok), t);                            yeardone++;                            current_state = DOING_ALPHABETIC_DATE;                            break;                         /* whereas these could be the hour part of a   */                         /* time specification ( 4 PM ) or the leading  */                         /* day part of an alphabetic date ( 15 Jan )   */                         case 2:                         case 1:                            strcpy(last_token, tok);                            current_state = PUT_NUMERIC_IN_CONTEXT;                            break;                         /* this must be a [YY]YYMMDD date             */                         case 6:                         case 8:                            if (store_yymmdd_date(tok, t))                               current_state = GOING_IN_BLIND;                            else                               current_state = STRING_GARBLED;                            break;                         /* anything else is nonsense...               */                         default:                            current_state = STRING_GARBLED;                            break;                      }                   }                   /* it could be [M]M/[D]D/[YY]YY format              */                   else if (is_numeric_dateformat(tok)) {                            store_numeric_date(tok, t);                            current_state = GOING_IN_BLIND;                   } else if (is_timeformat(tok)) {                                store_time(tok, t);                                current_state = GOING_IN_BLIND;                   } else {                                 current_state = STRING_GARBLED;						 }              break;   /* end of GOING_IN_BLIND */                                          case DOING_ALPHABETIC_DATE:              if (is_alphabetic(tok)) {                 if (!monthdone && is_monthname(tok)) {                     store_monthname(tok, t);                     monthdone++;                     if (monthdone && yeardone && mdaydone )                        current_state = GOING_IN_BLIND;                     else                        current_state = DOING_ALPHABETIC_DATE;                 } else {                     current_state = STRING_GARBLED;					  }              } else if (is_numeric(tok)) {                      if (mdaydone && yeardone)                          current_state = STRING_GARBLED;                      else switch(strlen(tok)) {                              case 4:                                 store_year(atoi(tok), t);                                 yeardone++;                                 if (monthdone && yeardone && mdaydone )                                    current_state = GOING_IN_BLIND;                                 else                                    current_state = DOING_ALPHABETIC_DATE;                                 break;                              case 2:                              case 1:                                 if (!mdaydone) {                                    store_mday(tok, t);                                    mdaydone++;                                    if (monthdone && yeardone && mdaydone )                                       current_state = GOING_IN_BLIND;                                    else                                       current_state = DOING_ALPHABETIC_DATE;                                 } else {                                    store_year(atoi(tok), t);                                    yeardone++;                                    if (monthdone && yeardone && mdaydone )                                       current_state = GOING_IN_BLIND;                                    else                                       current_state = DOING_ALPHABETIC_DATE;                                 }                                 break;                              default:                                 current_state = STRING_GARBLED;                           }                   } else {                     current_state = STRING_GARBLED;						 }              break;   /* end of DOING_ALPHABETIC_DATE */                                   case PUT_NUMERIC_IN_CONTEXT:              if (is_alphabetic(tok)) {                 if (is_monthname(tok)) {                     store_mday(last_token, t);                     mdaydone++;                     store_monthname(tok, t);                     monthdone++;                     if (monthdone && yeardone && mdaydone )                        current_state = GOING_IN_BLIND;                     else                        current_state = DOING_ALPHABETIC_DATE;                 } else if (is_ampm(tok)) {                     store_hour(last_token, tok, t);                     current_state = GOING_IN_BLIND;                 } else {                         current_state = STRING_GARBLED;					  }              } else if (is_numeric(tok)) {                      switch(strlen(tok)) {                         case 4:                         case 2:                           store_mday(last_token, t);                           mdaydone++;                           store_year(atoi(tok), t);                           yeardone++;                           if (monthdone && yeardone && mdaydone )                              current_state = GOING_IN_BLIND;                           else                              current_state = DOING_ALPHABETIC_DATE;                           break;                         default:                           current_state = STRING_GARBLED;                       }                } else {                   current_state = STRING_GARBLED;					 }              break;   /* end of PUT_NUMERIC_IN_CONTEXT */                                  case STRING_GARBLED:                              tdsdump_log(TDS_DBG_INFO1,"error_handler:  Attempt to convert data stopped by syntax error in source field \n");              return TDS_CONVERT_SYNTAX;        }        tok = strtok_r((char *)NULL, " ,", &lasts);    }	i = (t->tm_mon - 13) / 12;	dt_days = 1461 * ( t->tm_year + 300 + i ) / 4 +		(367 * ( t->tm_mon - 1 - 12*i ) ) / 12 -		(3 * ( ( t->tm_year + 400 + i ) / 100 ) ) / 4 +		t->tm_mday - 109544;	free(in);	/* TODO check for overflow */	if ( desttype == SYBDATETIME ) {		cr->dt.dtdays = dt_days;		dt_time = (t->tm_hour * 60 + t->tm_min ) * 60 + t->tm_sec;		cr->dt.dttime = dt_time * 300 + (t->tm_ms * 300 / 1000);		return sizeof(TDS_DATETIME);	} else {		/* SYBDATETIME4 */ 		cr->dt4.days = dt_days;		cr->dt4.minutes = t->tm_hour * 60 + t->tm_min;		return sizeof(TDS_DATETIME4);	}}static int stringz_to_numeric(const char *instr, CONV_RESULT *cr){	return string_to_numeric(instr,instr+strlen(instr),cr);}static int string_to_numeric(const char *instr, const char *pend, CONV_RESULT *cr){char  mynumber[(MAXPRECISION+7)/8*8];/* num packaged 8 digit, see below for detail */TDS_UINT packed_num[TDS_VECTOR_SIZE(mynumber)/8];char *ptr;const char *pdigits;const char* pstr;TDS_UINT  carry = 0;char  not_zero = 1;int  i = 0;int  j = 0;short int bytes, places, point_found, sign, digits;  sign        = 0;  point_found = 0;  places      = 0;	/* FIXME: application can pass invalid value for precision and scale ?? */	if (cr->n.precision > 77)		return TDS_CONVERT_FAIL;	if (cr->n.precision == 0)		cr->n.precision = 77; /* assume max precision */  if ( cr->n.scale > cr->n.precision )	return TDS_CONVERT_FAIL;  /* skip leading blanks */  for (pstr = instr;; ++pstr)  {  	if (pstr == pend) return TDS_CONVERT_SYNTAX;  	if (*pstr != ' ') break;  }  if ( *pstr == '-' || *pstr == '+' )         /* deal with a leading sign */  {     if (*pstr == '-')        sign = 1;     pstr++;  }  digits = 0;  pdigits = pstr;  for(; pstr != pend; ++pstr)             /* deal with the rest */  {     if (isdigit((unsigned char) *pstr))  /* its a number */     {          if (point_found)                  /* if we passed a decimal point */           ++places;                      /* count digits after that point  */        else           ++digits;                      /* count digits before point  */     }     else if (*pstr == '.')               /* found a decimal point */          {             if (point_found)             /* already had one. return error */                return TDS_CONVERT_SYNTAX;             point_found = 1;          }          else                            /* first invalid character */             return TDS_CONVERT_SYNTAX;   /* return error. */  }  /* no digits? no number!*/  if (!digits)  	return TDS_CONVERT_SYNTAX;	/* truncate decimal digits */	if ( places > cr->n.scale)		places = cr->n.scale;  /* too digits, error */  if ( (digits+cr->n.scale) > cr->n.precision) 	return TDS_CONVERT_OVERFLOW;  /* TODO: this can be optimized in a single step */  /* scale specified, pad out number with zeroes to the scale...  */  ptr = mynumber+sizeof(mynumber)-(cr->n.scale-places);  memset(ptr,48,cr->n.scale-places);  ptr -= places;  /* copy number without point */  memcpy(ptr,pdigits+digits+1,places);  ptr -= digits;  memcpy(ptr,pdigits,digits);  memset(mynumber,48,ptr-mynumber);  /* transform ASCII string into a numeric array */  for (ptr = mynumber; ptr != mynumber+sizeof(mynumber); ++ptr)  	*ptr -= 48;  /*   * Packaged number explanation   * I package 8 decimal digit in one number

⌨️ 快捷键说明

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