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

📄 convert.c

📁 在Linux/Unix下面访问WINDOWS SQLSERVER 的ODBC驱动程序
💻 C
📖 第 1 页 / 共 5 页
字号:
/* 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 intstring_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));	mytime.tm_mday = 1;	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 != NULL) {		tdsdump_log(TDS_DBG_INFO1, "string_to_datetime: current_state = %d\n", current_state);		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)) {				tdsdump_log(TDS_DBG_INFO1, "string_to_datetime: is_alphabetic\n");				if (store_monthname(tok, t) >= 0) {					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)) {				tdsdump_log(TDS_DBG_INFO1, "string_to_datetime: is_numeric\n");				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)) {				tdsdump_log(TDS_DBG_INFO1, "string_to_datetime: is_numeric_dateformat\n");				store_numeric_date(tok, t);				current_state = GOING_IN_BLIND;			} else if (is_dd_mon_yyyy(tok)) {				tdsdump_log(TDS_DBG_INFO1, "string_to_datetime: is_dd_mon_yyyy\n");				store_dd_mon_yyy_date(tok, t);				current_state = GOING_IN_BLIND;			} else if (is_timeformat(tok)) {				tdsdump_log(TDS_DBG_INFO1, "string_to_datetime: is_timeformat\n");				store_time(tok, t);				current_state = GOING_IN_BLIND;			} else {				tdsdump_log(TDS_DBG_INFO1, "string_to_datetime: string_garbled\n");				current_state = STRING_GARBLED;			}			break;	/* end of GOING_IN_BLIND */		case DOING_ALPHABETIC_DATE:			if (is_alphabetic(tok)) {				if (!monthdone && store_monthname(tok, t) >= 0) {					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 (store_monthname(tok, t) >= 0) {					store_mday(last_token, t);					mdaydone++;					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");			free(in);			return TDS_CONVERT_SYNTAX;		}		tok = strtok_r(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 + 150) / 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 intstringz_to_numeric(const char *instr, CONV_RESULT * cr){	return string_to_numeric(instr, instr + strlen(instr), cr);}static intstring_to_numeric(const char *instr, const char *pend, CONV_RESULT * cr){	char mynumber[(MAXPRECISION + 7) / 8 * 8 + 8];	/* num packaged 8 digit, see below for detail */	TDS_UINT packed_num[(MAXPRECISION + 7) / 8];	char *ptr;	const char *pstr;	int old_digits_left, digits_left, digit_found = 0;	int i = 0;	int j = 0;	int bytes, places;	unsigned char sign;	/* 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;	}	sign = 0;	if (*pstr == '-' || *pstr == '+') {	/* deal with a leading sign */		if (*pstr == '-')			sign = 1;		pstr++;	}	cr->n.array[0] = sign;	/* 	 * skip leading zeroes 	 * Not skipping them cause numbers like "000000000000" to 	 * appear like overflow	 */	for (; pstr != pend && *pstr == '0'; ++pstr)		digit_found = 1;	/* 	 * Having disposed of any sign and leading blanks, 	 * vet the digit string, counting places before and after 	 * the decimal point.  Dispense with trailing blanks, if any.  	 */	ptr = mynumber;	for (i = 0; i < 8; ++i)		*ptr++ = '0';	places = 0;	old_digits_left = 0;	digits_left = cr->n.precision - cr->n.scale;	for (; pstr != pend; ++pstr) {			/* deal with the rest */		if (*pstr >= '0' && *pstr <= '9') {	/* it's a number */			/* copy digit to destination */			if (--digits_left >= 0)				*ptr++ = *pstr;			digit_found = 1;		} else if (*pstr == '.') {			/* found a decimal point */			if (places)				/* found a decimal point previously: return error */				return TDS_CONVERT_SYNTAX;			old_digits_left = digits_left;			digits_left = cr->n.scale;			places = 1;		} else if (*pstr == ' ') {			for (; pstr != pend && *pstr == ' '; ++pstr) ; /* skip contiguous blanks */			if (pstr == pend)				break;				/* success: found only trailing blanks */			return TDS_CONVERT_SYNTAX;		/* bzzt: found something after the blank(s) */		} else {         				/* first invalid character */			return TDS_CONVERT_SYNTAX;		}	}	/* no digits? no number! */	if (!digit_found)		return TDS_CONVERT_SYNTAX;	if (!places) {		old_digits_left = digits_left;		digits_left = cr->n.scale;	}	/* too many digits, error */	if (old_digits_left < 0)		return TDS_CONVERT_OVERFLOW;	/* fill up decimal digits */	while (--digits_left >= 0)		*ptr++ = '0';	/*	 * Packaged number explanation: 	 * We package 8 decimal digits in one number.  	 * Because 10^8 = 5^8 * 2^8 = 5^8 * 256, dividing 10^8 by 256 leaves no remainder.	 * We can thus split it into bytes in an optimized way.	 */	/* transform to packaged one */	j = -1;	ptr -= 8;	do {		TDS_UINT n = *ptr++;		for (i = 1; i < 8; ++i)			n = n * 10 + *ptr++;		/* fix packet number and store */		packed_num[++j] = n - ((TDS_UINT) '0' * 11111111lu);		ptr -= 16;	} while (ptr > mynumber);	memset(cr->n.array + 1, 0, sizeof(cr->n.array) - 1);	bytes = tds_numeric_bytes_per_prec[cr->n.precision];	while (j > 0 && !packed_num[j])		--j;	for (;;) {		char is_zero = 1;		TDS_UINT carry = 0;		i = j;		if (!packed_num[j])			--j;		do {			TDS_UINT tmp = packed_num[i];			if (tmp)				is_zero = 0;			/* divide for 256 for find another byte */			/*			 * carry * (25u*25u*25u*25u) = carry * 10^8 / 256u			 * using unsigned number is just an optimization			 * compiler can translate division to a shift and remainder 			 * to a binary AND			 */			packed_num[i] = carry * (25u * 25u * 25u * 25u) + tmp / 256u;			carry = tmp % 256u;		} while(--i >= 0);		if (is_zero)			break;		/*		 * source number is limited to 38 decimal digit		 * 10^39-1 < 2^128 (16 byte) so this cannot make an overflow		 */		cr->n.array[--bytes] = carry;	}	return sizeof(TDS_NUMERIC);}static intis_numeric_dateformat(const char *t){	const char *instr;	int ret = 1;	int slashes = 0;	int hyphens = 0;	int periods = 0;	int digits = 0;	for (instr = t; *instr; instr++) {		if (!isdigit((unsigned char) *instr) && *instr != '/' && *instr != '-' && *instr != '.') {			ret = 0;			break;		}		if (*instr == '/')			slashes++;		else if (*instr == '-')			hyphens++;		else if (*instr == '.')			periods++;		else			digits++;	}	if (hyphens + slashes + periods != 2)		ret = 0;	if (hyphens == 1 || slashes == 1 || periods == 1)		ret = 0;	if (digits < 4 || digits > 8)		ret = 0;	return (ret);}/* This function will check if an alphanumeric string *//* holds a date in any of the following formats :     *//*    DD-MON-YYYY *//*    DD-MON-YY   *//*    DDMONYY     *//*    DDMONYYYY   */static intis_dd_mon_yyyy(char *t){	char *instr;	char month[4];	instr = t;	if (!isdigit((unsigned char) *instr))		return (0);	instr++;	if (!isdigit((unsigned char) *instr))		return (0);	instr++;	if (*instr == '-') {		instr++;		strncpy(month, instr, 3);		month[3] = '\0';		if (!is_monthname(month))			return (0);		instr += 3;		if (*instr != '-')			return (0);		instr++;		if (!isdigit((unsigned char) *instr))			return (0);		instr++;		if (!isdigit((unsigned char) *instr))			return (0);		instr++;		if (*instr) {			if (!isdigit((unsigned char) *instr))				return (0);			instr++;			if (!isdigit((unsigned char) *instr))				return (0);		}	} else {		strncpy(month, instr, 3);		month[3] = '\0';		if (!is_monthname(month))			return (0);		instr += 3;		if (!isdigit((unsigned char) *instr))			return (0);		instr++;		if (!isdigit((unsigned char) *instr))			return (0);		instr++;		if (*instr) {			if (!isdigit((unsigned char) *instr))				return (0);			instr++;			if (!isdigit((unsigned char) *instr))				return (0);		}	}	return (1);}static intis_ampm(const char *datestr){	int ret = 0;	if (strcasecmp(datestr, "am") == 0)		ret = 1;	else if (strcasecmp(datestr, "pm") == 0)		ret = 1;	else		ret = 0;	return ret;}static intis_alphabetic(const char *datestr){	const char *s;	int ret = 1;	for (s = datestr; *s; s++) {		if (!isalpha((unsigned char) *s))

⌨️ 快捷键说明

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