Index: zend_strtod.c =================================================================== RCS file: /repository/ZendEngine2/zend_strtod.c,v retrieving revision 1.23 diff -u -r1.23 zend_strtod.c --- zend_strtod.c 15 Apr 2006 12:54:26 -0000 1.23 +++ zend_strtod.c 25 Nov 2006 10:45:02 -0000 @@ -1801,19 +1801,85 @@ /* UTODO: someone can reimplement this using the code above, if they really want to. */ ZEND_API double zend_u_strtod(const UChar *nptr, UChar **endptr) { - double value = 0.0; - int32_t num_conv = 0, num_read = 0; + const UChar *u = nptr, *nstart; + UChar c = *u; + int any = 0; - num_conv = u_sscanf(nptr, "%f%n", &value, &num_read); - if (num_conv != EOF) { - if (endptr != 0) { - *endptr = (UChar *)nptr + num_read; + while (u_isspace(c)) { + c = *++u; + } + nstart = u; + + if (c == 0x2D /*'-'*/ || c == 0x2B /*'+'*/) { + c = *++u; + } + + while (c >= 0x30 /*'0'*/ && c <= 0x39 /*'9'*/) { + any = 1; + c = *++u; + } + + if (c == 0x2E /*'.'*/) { + c = *++u; + while (c >= 0x30 /*'0'*/ && c <= 0x39 /*'9'*/) { + any = 1; + c = *++u; } - return value; - } else { - if (endptr != 0) { - *endptr = (UChar *)nptr; + } + + if ((c == 0x65 /*'e'*/ || c == 0x45 /*'E'*/) && any) { + const UChar *e = u; + int any_exp = 0; + + c = *++u; + if (c == 0x2D /*'-'*/ || c == 0x2B /*'+'*/) { + c = *++u; + } + + while (c >= 0x30 /*'0'*/ && c <= 0x39 /*'9'*/) { + any_exp = 1; + c = *++u; + } + + if (!any_exp) { + u = e; } - return 0; } + + if (any) { + char buf[64], *numbuf, *bufpos; + int length = u - nstart; + double value; + + if (length < sizeof(buf)) { + numbuf = buf; + } else { + numbuf = (char *) do_alloca(length + 1); + } + + bufpos = numbuf; + + while (nstart < u) { + *bufpos++ = (char) *nstart++; + } + + *bufpos = '\0'; + value = zend_strtod(numbuf, NULL); + + if (numbuf != buf) { + free_alloca(numbuf); + } + + if (endptr != NULL) { + *endptr = (UChar *)u; + } + + return value; + } + + if (endptr != NULL) { + *endptr = (UChar *)nptr; + } + + return 0; }