freetds AT lists.ibiblio.org
Subject: FreeTDS Development Group
List archive
RE: [ freetds-Patches-580072 ] Rewritten string_to_numeric
- From: ZIGLIO Frediano <Frediano.Ziglio AT vodafoneomnitel.it>
- To: "Freetds (E-mail)" <freetds AT franklin.metalab.unc.edu>
- Subject: RE: [ freetds-Patches-580072 ] Rewritten string_to_numeric
- Date: Thu, 11 Jul 2002 14:58:35 +0200
Just for ML discussion I report new function
static int
string_to_numeric(const char *instr, const char *pend, DBANY *any)
{
char mynumber[40];
/* num packaged 8 digit, see below for detail */
TDS_UINT packed_num[5];
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 (any->n.precision > 38)
return 1;
if (any->n.precision == 0)
any->n.precision = 38; /* assume max precision */
if ( any->n.scale > any->n.precision )
return 1;
/* skip leading blanks */
for (pstr = instr;; ++ptr)
{
if (pstr == pend) return 1;
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(*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 1;
if (any->n.scale == 0) /* no scale...lose the rest */
break; /* FIXME: check other characters */
point_found = 1;
}
else /* first invalid character */
return 1; /* return error. */
}
/* no digits? no number!*/
if (!digits)
return 1;
/* truncate decimal digits */
if ( any->n.scale > 0 && places > any->n.scale)
places = any->n.scale;
/* too digits, error */
if ( (digits+any->n.scale) > any->n.precision)
return 1;
/* FIXME: this can be optimized in a single step */
/* scale specified, pad out number with zeroes to the scale... */
ptr = mynumber+40-(any->n.scale-places);
memset(ptr,48,any->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+40; ++ptr)
*ptr -= 48;
/*
* Packaged number explanation
* I package 8 decimal digit in one number
* This because 10^8 = 5^8 * 2^8 = 5^8 * 256
* So dividing 10^8 for 256 make no remainder
* So I can split for bytes in an optmized way
*/
/* transform to packaged one */
for(j=0;j<5;++j)
{
TDS_UINT n = mynumber[j*8];
for(i=1;i<8;++i)
{
n = n * 10 + mynumber[j*8+i];
}
packed_num[j] = n;
}
memset(any->n.array,0,sizeof(any->n.array));
any->n.array[0] = sign;
bytes = 1;
while (not_zero)
{
not_zero = 0;
carry = 0;
for (i = 0; i < 5; ++i)
{
TDS_UINT tmp;
if (packed_num[i] > 0)
not_zero = 1;
/* divide for 256 for find another byte */
tmp = packed_num[i];
/* 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) + packed_num[i] / 256u;
carry = tmp % 256u;
if ( i == 4 && not_zero)
{
/* source number is limited to 38 decimal digit
* 10^39-1 < 2^128 (16 byte) so this cannot make an overflow
*/
any->n.array[bytes] = carry;
++bytes;
}
}
}
return 0;
}
freddy77
=================================
"STRICTLY PERSONAL AND CONFIDENTIAL
This message may contain confidential and proprietary material for the sole
use of the intended recipient. Any review or distribution by others is
strictly prohibited. If you are not the intended recipient please contact
the sender and delete all copies.
The contents of this message that do not relate to the official business of
our company shall be understood as neither given nor endorsed by it."
=================================
-
[ freetds-Patches-580072 ] Rewritten string_to_numeric,
noreply, 07/11/2002
- <Possible follow-up(s)>
- RE: [ freetds-Patches-580072 ] Rewritten string_to_numeric, ZIGLIO Frediano, 07/11/2002
Archive powered by MHonArc 2.6.24.