From: Antony Dovgal Date: Wed, 6 Dec 2006 12:25:29 +0000 (+0000) Subject: add zend_u_strtod() implementation by Matt Wilmas X-Git-Tag: RELEASE_1_0_0RC1~795 X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=b8ad51752673664992be18b4903c9c01f750be08;p=php add zend_u_strtod() implementation by Matt Wilmas major speedup when using floats in Unicode mode also fixes several problems with the current code --- diff --git a/Zend/zend_strtod.c b/Zend/zend_strtod.c index 696e124fa9..3dfdab571f 100644 --- a/Zend/zend_strtod.c +++ b/Zend/zend_strtod.c @@ -2560,24 +2560,89 @@ ret: return result; } -/* 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; } /*