Skip to Content.
Sympa Menu

freetds - RE: [ freetds-Patches-580072 ] Rewritten string_to_numeric

freetds AT lists.ibiblio.org

Subject: FreeTDS Development Group

List archive

Chronological Thread  
  • 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."

=================================




Archive powered by MHonArc 2.6.24.

Top of Page