[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