[Python-checkins] r46770 - sandbox/trunk/decimal-c/_decimal.c
mateusz.rukowicz
python-checkins at python.org
Fri Jun 9 13:05:33 CEST 2006
Author: mateusz.rukowicz
Date: Fri Jun 9 13:05:33 2006
New Revision: 46770
Modified:
sandbox/trunk/decimal-c/_decimal.c
Log:
Redo of _decimal_fromliteral, now it results in normalized Decimal.
Modified: sandbox/trunk/decimal-c/_decimal.c
==============================================================================
--- sandbox/trunk/decimal-c/_decimal.c (original)
+++ sandbox/trunk/decimal-c/_decimal.c Fri Jun 9 13:05:33 2006
@@ -2671,105 +2671,223 @@
static decimalobject *
_decimal_fromliteral(PyTypeObject *type, char *str, long len, contextobject *ctx)
{
- long ipos = 0; /* start of integral digits */
- long dpos = -1; /* decimal point location */
- long dend = len; /* end of integral/decimal digits (last digit+1) */
- char *p = str;
- char sign = 0;
- decimalobject *new;
- long exp = 0, i, ndigits;
+ char sign;
+ long exp = 0;
+ long ndigits;
+ long zero = 0; /* if zero */
+ long digits_after_dot = 0;
+ char *p = str;
+ char *first_digit = 0;
+ char *dot = 0;
+ char *e = 0;
+ char *c;
+ long i;
+ decimalobject *new;
- /* optional sign */
- if (*p == '+') {
- ++p;
- ipos = 1;
- } else if (*p == '-') {
- ++p;
- ipos = 1;
- sign = 1;
- }
+ if(*p == '+')
+ p++;
+ else if(*p == '-')
+ {
+ p++;
+ sign = 1;
+ }
+
+ if(*p == 'e' || *p == 'E') /* no digits befor E */
+ goto err;
+
+ /* now at *p is our integer with (possibly) dot */
+
+ for(c = p; c - str < len; c++)
+ {
+ if(!isdigit(*c))
+ {
+ if(*c == 'e' || *c == 'E')
+ {
+ if(e)
+ goto err; /* we should have only one e */
+ e = c;
+ }
+
+ else if(*c == '.')
+ {
+ if(dot)
+ goto err;
+ dot = c;
+ }
+
+ else if(*c == '-' || *c == '+') /* we should have sign only after e */
+ {
+ if(c - e != 1)
+ goto err;
+ }
+ else /* we shouldn't have anything else */
+ goto err;
+ }
+ else
+ {
+ if(dot)
+ digits_after_dot ++;
+
+ if(!first_digit && *c != '0')
+ {
+ if(!e) /* it's digit of exponent */
+ first_digit = c;
+ }
+ }
+ } /* we now are pretty sure, that string is properly formated */
+ if(!first_digit)
+ {
+ zero = 1;
+ ndigits = 1;
+ }
+ else /* let's count digits */
+ {
+ ndigits = 0;
+ for(c = first_digit; c - str < len; c++)
+ {
+ if(isdigit(*c))
+ ndigits ++;
+ else
+ if(*c == 'e' || *c == 'E')
+ break;
+
+ assert(isdigit(*c) || *c == '.');
+ }
+ }
+
+ if(e) /* pretty obvious */
+ exp = atol(e+1);
+ exp -= digits_after_dot;
+
+ new = _new_decimalobj(type, ndigits, sign, exp);
+
+ for(i = 0; i<new->limb_count ;i++)
+ new->limbs[i] = 0;
+
+ if(!first_digit) /* we are 0 */
+ {
+ new->limbs[0] = 0;
+ return new;
+ }
+
+ long mult = 1; /* now we just read integer till '\0' or 'e'/'E', dont care about '.' */
+ long limb = 0;
+
+ for(c = p; c - str < len; c++)
+ {
+ if(*c == 'e' || *c == 'E') break;
+ if(!isdigit(*c)) continue;
- do {
- if (*p == '.') {
- dpos = p-str;
- } else if (*p == 'e' || *p == 'E') {
- dend = p-str;
- if (dend == ipos || (dpos >= 0 && dend == ipos+1))
+ assert(limb < new->limb_count);
+ new->limbs[limb] += mult * (*c - '0');
+
+ if(mult == BASE)
+ {
+ limb ++;
+ mult = 1;
+ }
+ }
+
+ return new;
+// long ipos = 0; /* start of integral digits */
+// long dpos = -1; /* decimal point location */
+// long dend = len; /* end of integral/decimal digits (last digit+1) */
+// char *p = str;
+// char sign = 0;
+// decimalobject *new;
+// long exp = 0, i, ndigits;
+
+ /* optional sign */
+// if (*p == '+') {
+// ++p;
+// ipos = 1;
+// } else if (*p == '-') {
+// ++p;
+// ipos = 1;
+// sign = 1;
+// }
+
+// do {
+// if (*p == '.') {
+// dpos = p-str;
+// } else if (*p == 'e' || *p == 'E') {
+// dend = p-str;
+// if (dend == ipos || (dpos >= 0 && dend == ipos+1))
/* no digits between sign and E */
- goto err;
- ++p;
- break;
- } else if (!isdigit(*p)) {
- goto err;
- }
- } while (*++p);
+// goto err;
+// ++p;
+// break;
+// } else if (!isdigit(*p)) {
+// goto err;
+// }
+// } while (*++p);
/* exponential part or end of string */
- if (*p == 0) {
- if (ipos == dpos && dpos == dend-1)
+// if (*p == 0) {
+// if (ipos == dpos && dpos == dend-1)
/* no digits at all */
- goto err;
- goto calculate;
- } else if (*p == '-' || *p == '+') {
- ++p;
- }
+// goto err;
+// goto calculate;
+// } else if (*p == '-' || *p == '+') {
+// ++p;
+// }
- do {
+// do {
/* optional exponential digits */
- if (!isdigit(*p))
- goto err;
- } while (*++p);
-
- calculate:
- if (dend < len)
- exp = atol(str + dend + 1);
- if (dpos >= 0)
+// if (!isdigit(*p))
+// goto err;
+// } while (*++p);
+
+// calculate:
+// if (dend < len)
+// exp = atol(str + dend + 1);
+// if (dpos >= 0)
/* specified fractional digits, reduce exp */
- exp -= dend - dpos - 1;
+// exp -= dend - dpos - 1;
/* If it's not a zero, strip leading 0s */
- for (p = str+ipos; p-str < dend; ++p) {
- if (*p != '0') {
+// for (p = str+ipos; p-str < dend; ++p) {
+// if (*p != '0') {
/* first nonzero digit */
- ipos = (p-str);
- goto finish;
- }
- }
+// ipos = (p-str);
+// goto finish;
+// }
+// }
/* it's a zero */
- dend = (dpos == ipos ? ipos+2 : ipos+1);
+// dend = (dpos == ipos ? ipos+2 : ipos+1);
- finish:
- ndigits = dend - ipos - (dpos<0 ? 0 : 1);
- new = _new_decimalobj(type, ndigits, sign, exp);
- if (!new)
- return NULL;
- i = 0;
- for (p = str+ipos; p-str < dend; ++p) {
- if (*p == '.') continue;
- new->digits[i] = *p - 48;
- i++;
- }
+// finish:
+// ndigits = dend - ipos - (dpos<0 ? 0 : 1);
+// new = _new_decimalobj(type, ndigits, sign, exp);
+// if (!new)
+// return NULL;
+// i = 0;
+// for (p = str+ipos; p-str < dend; ++p) {
+// if (*p == '.') continue;
+// new->digits[i] = *p - 48;
+// i++;
+// }
- long mult = 1;
- long limb = 0;
- for(i=0;i<new -> limb_count; i++)
- new->limbs[i] = 0;
+// long mult = 1;
+// long limb = 0;
+// for(i=0;i<new -> limb_count; i++)
+// new->limbs[i] = 0;
- for(i = dend - 1; i>= ipos; i--)
- {
- if(str[i] == '.') continue;
- assert(limb < new->limb_count);
- new->limbs[limb] += mult * (str[i] - '0');
-
- mult *= 10;
- if(mult == BASE)
- {
- mult = 1;
- limb ++;
- }
- }
+// for(i = dend - 1; i>= ipos; i--)
+// {
+// if(str[i] == '.') continue;
+// assert(limb < new->limb_count);
+// new->limbs[limb] += mult * (str[i] - '0');
+//
+// mult *= 10;
+// if(mult == BASE)
+// {
+// mult = 1;
+// limb ++;
+// }
+// }
- return new;
+ // return new;
err:
return handle_ConversionSyntax(type, ctx, "invalid literal for Decimal");
More information about the Python-checkins
mailing list