Skip to content

Commit d28f6e6

Browse files
committed
Move php_gcvt to zend_gcvt
Also move PHP_DOUBLE_MAX_LENGTH to ZEND_DOUBLE_MAX_LENGTH.
1 parent 7c9ac47 commit d28f6e6

File tree

11 files changed

+126
-123
lines changed

11 files changed

+126
-123
lines changed

Zend/zend_strtod.c

+99
Original file line numberDiff line numberDiff line change
@@ -4507,6 +4507,105 @@ ZEND_API double zend_bin_strtod(const char *str, const char **endptr)
45074507
return value;
45084508
}
45094509

4510+
ZEND_API char *zend_gcvt(double value, int ndigit, char dec_point, char exponent, char *buf)
4511+
{
4512+
char *digits, *dst, *src;
4513+
int i, decpt;
4514+
bool sign;
4515+
int mode = ndigit >= 0 ? 2 : 0;
4516+
4517+
if (mode == 0) {
4518+
ndigit = 17;
4519+
}
4520+
digits = zend_dtoa(value, mode, ndigit, &decpt, &sign, NULL);
4521+
if (decpt == 9999) {
4522+
/*
4523+
* Infinity or NaN, convert to inf or nan with sign.
4524+
* We assume the buffer is at least ndigit long.
4525+
*/
4526+
snprintf(buf, ndigit + 1, "%s%s", (sign && *digits == 'I') ? "-" : "", *digits == 'I' ? "INF" : "NAN");
4527+
zend_freedtoa(digits);
4528+
return (buf);
4529+
}
4530+
4531+
dst = buf;
4532+
if (sign) {
4533+
*dst++ = '-';
4534+
}
4535+
4536+
if ((decpt >= 0 && decpt > ndigit) || decpt < -3) { /* use E-style */
4537+
/* exponential format (e.g. 1.2345e+13) */
4538+
if (--decpt < 0) {
4539+
sign = 1;
4540+
decpt = -decpt;
4541+
} else {
4542+
sign = 0;
4543+
}
4544+
src = digits;
4545+
*dst++ = *src++;
4546+
*dst++ = dec_point;
4547+
if (*src == '\0') {
4548+
*dst++ = '0';
4549+
} else {
4550+
do {
4551+
*dst++ = *src++;
4552+
} while (*src != '\0');
4553+
}
4554+
*dst++ = exponent;
4555+
if (sign) {
4556+
*dst++ = '-';
4557+
} else {
4558+
*dst++ = '+';
4559+
}
4560+
if (decpt < 10) {
4561+
*dst++ = '0' + decpt;
4562+
*dst = '\0';
4563+
} else {
4564+
/* XXX - optimize */
4565+
int n;
4566+
for (n = decpt, i = 0; (n /= 10) != 0; i++);
4567+
dst[i + 1] = '\0';
4568+
while (decpt != 0) {
4569+
dst[i--] = '0' + decpt % 10;
4570+
decpt /= 10;
4571+
}
4572+
}
4573+
} else if (decpt < 0) {
4574+
/* standard format 0. */
4575+
*dst++ = '0'; /* zero before decimal point */
4576+
*dst++ = dec_point;
4577+
do {
4578+
*dst++ = '0';
4579+
} while (++decpt < 0);
4580+
src = digits;
4581+
while (*src != '\0') {
4582+
*dst++ = *src++;
4583+
}
4584+
*dst = '\0';
4585+
} else {
4586+
/* standard format */
4587+
for (i = 0, src = digits; i < decpt; i++) {
4588+
if (*src != '\0') {
4589+
*dst++ = *src++;
4590+
} else {
4591+
*dst++ = '0';
4592+
}
4593+
}
4594+
if (*src != '\0') {
4595+
if (src == digits) {
4596+
*dst++ = '0'; /* zero before decimal point */
4597+
}
4598+
*dst++ = dec_point;
4599+
for (i = decpt; digits[i] != '\0'; i++) {
4600+
*dst++ = digits[i];
4601+
}
4602+
}
4603+
*dst = '\0';
4604+
}
4605+
zend_freedtoa(digits);
4606+
return (buf);
4607+
}
4608+
45104609
static void destroy_freelist(void)
45114610
{
45124611
int i;

Zend/zend_strtod.h

+10-1
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,8 @@
2424

2525
BEGIN_EXTERN_C()
2626
ZEND_API void zend_freedtoa(char *s);
27-
ZEND_API char * zend_dtoa(double _d, int mode, int ndigits, int *decpt, bool *sign, char **rve);
27+
ZEND_API char *zend_dtoa(double _d, int mode, int ndigits, int *decpt, bool *sign, char **rve);
28+
ZEND_API char *zend_gcvt(double value, int ndigit, char dec_point, char exponent, char *buf);
2829
ZEND_API double zend_strtod(const char *s00, const char **se);
2930
ZEND_API double zend_hex_strtod(const char *str, const char **endptr);
3031
ZEND_API double zend_oct_strtod(const char *str, const char **endptr);
@@ -33,4 +34,12 @@ ZEND_API int zend_startup_strtod(void);
3334
ZEND_API int zend_shutdown_strtod(void);
3435
END_EXTERN_C()
3536

37+
/* double limits */
38+
#include <float.h>
39+
#if defined(DBL_MANT_DIG) && defined(DBL_MIN_EXP)
40+
#define ZEND_DOUBLE_MAX_LENGTH (3 + DBL_MANT_DIG - DBL_MIN_EXP)
41+
#else
42+
#define ZEND_DOUBLE_MAX_LENGTH 1080
43+
#endif
44+
3645
#endif

ext/json/json_encoder.c

+3-3
Original file line numberDiff line numberDiff line change
@@ -80,11 +80,11 @@ static inline int php_json_is_valid_double(double d) /* {{{ */
8080
static inline void php_json_encode_double(smart_str *buf, double d, int options) /* {{{ */
8181
{
8282
size_t len;
83-
char num[PHP_DOUBLE_MAX_LENGTH];
83+
char num[ZEND_DOUBLE_MAX_LENGTH];
8484

85-
php_gcvt(d, (int)PG(serialize_precision), '.', 'e', num);
85+
zend_gcvt(d, (int)PG(serialize_precision), '.', 'e', num);
8686
len = strlen(num);
87-
if (options & PHP_JSON_PRESERVE_ZERO_FRACTION && strchr(num, '.') == NULL && len < PHP_DOUBLE_MAX_LENGTH - 2) {
87+
if (options & PHP_JSON_PRESERVE_ZERO_FRACTION && strchr(num, '.') == NULL && len < ZEND_DOUBLE_MAX_LENGTH - 2) {
8888
num[len++] = '.';
8989
num[len++] = '0';
9090
num[len] = '\0';

ext/mysqlnd/mysql_float_to_double.h

+1-1
Original file line numberDiff line numberDiff line change
@@ -38,7 +38,7 @@ static inline double mysql_float_to_double(float fp4, int decimals) {
3838
char num_buf[MAX_CHAR_BUF_LEN]; /* Over allocated */
3939

4040
if (decimals < 0) {
41-
php_gcvt(fp4, FLT_DIG, '.', 'e', num_buf);
41+
zend_gcvt(fp4, FLT_DIG, '.', 'e', num_buf);
4242
} else {
4343
snprintf(num_buf, MAX_CHAR_BUF_LEN, "%.*F", decimals, fp4);
4444
}

ext/soap/php_encoding.c

+1-1
Original file line numberDiff line numberDiff line change
@@ -1083,7 +1083,7 @@ static xmlNodePtr to_xml_double(encodeTypePtr type, zval *data, int style, xmlNo
10831083
ZVAL_DOUBLE(&tmp, zval_get_double(data));
10841084

10851085
str = (char *) safe_emalloc(EG(precision) >= 0 ? EG(precision) : 17, 1, MAX_LENGTH_OF_DOUBLE + 1);
1086-
php_gcvt(Z_DVAL(tmp), EG(precision), '.', 'E', str);
1086+
zend_gcvt(Z_DVAL(tmp), EG(precision), '.', 'E', str);
10871087
xmlNodeSetContentLen(ret, BAD_CAST(str), strlen(str));
10881088
efree(str);
10891089

ext/standard/formatted_print.c

+1-1
Original file line numberDiff line numberDiff line change
@@ -299,7 +299,7 @@ php_sprintf_appenddouble(zend_string **buffer, size_t *pos,
299299

300300
char exp_char = fmt == 'G' || fmt == 'H' ? 'E' : 'e';
301301
/* We use &num_buf[ 1 ], so that we have room for the sign. */
302-
s = php_gcvt(number, precision, decimal_point, exp_char, &num_buf[1]);
302+
s = zend_gcvt(number, precision, decimal_point, exp_char, &num_buf[1]);
303303
is_negative = 0;
304304
if (*s == '-') {
305305
is_negative = 1;

ext/standard/var.c

+4-4
Original file line numberDiff line numberDiff line change
@@ -480,7 +480,7 @@ static void php_object_element_export(zval *zv, zend_ulong index, zend_string *k
480480
PHPAPI void php_var_export_ex(zval *struc, int level, smart_str *buf) /* {{{ */
481481
{
482482
HashTable *myht;
483-
char tmp_str[PHP_DOUBLE_MAX_LENGTH];
483+
char tmp_str[ZEND_DOUBLE_MAX_LENGTH];
484484
zend_string *ztmp, *ztmp2;
485485
zend_ulong index;
486486
zend_string *key;
@@ -508,7 +508,7 @@ PHPAPI void php_var_export_ex(zval *struc, int level, smart_str *buf) /* {{{ */
508508
smart_str_append_long(buf, Z_LVAL_P(struc));
509509
break;
510510
case IS_DOUBLE:
511-
php_gcvt(Z_DVAL_P(struc), (int)PG(serialize_precision), '.', 'E', tmp_str);
511+
zend_gcvt(Z_DVAL_P(struc), (int)PG(serialize_precision), '.', 'E', tmp_str);
512512
smart_str_appends(buf, tmp_str);
513513
/* Without a decimal point, PHP treats a number literal as an int.
514514
* This check even works for scientific notation, because the
@@ -1038,8 +1038,8 @@ static void php_var_serialize_intern(smart_str *buf, zval *struc, php_serialize_
10381038
return;
10391039

10401040
case IS_DOUBLE: {
1041-
char tmp_str[PHP_DOUBLE_MAX_LENGTH];
1042-
php_gcvt(Z_DVAL_P(struc), (int)PG(serialize_precision), '.', 'E', tmp_str);
1041+
char tmp_str[ZEND_DOUBLE_MAX_LENGTH];
1042+
zend_gcvt(Z_DVAL_P(struc), (int)PG(serialize_precision), '.', 'E', tmp_str);
10431043

10441044
size_t len = strlen(tmp_str);
10451045
char *res = smart_str_extend(buf, 2 + len + 1);

main/php.h

+1-7
Original file line numberDiff line numberDiff line change
@@ -245,13 +245,7 @@ typedef unsigned int socklen_t;
245245
#define INT_MIN (- INT_MAX - 1)
246246
#endif
247247

248-
/* double limits */
249-
#include <float.h>
250-
#if defined(DBL_MANT_DIG) && defined(DBL_MIN_EXP)
251-
#define PHP_DOUBLE_MAX_LENGTH (3 + DBL_MANT_DIG - DBL_MIN_EXP)
252-
#else
253-
#define PHP_DOUBLE_MAX_LENGTH 1080
254-
#endif
248+
#define PHP_DOUBLE_MAX_LENGTH ZEND_DOUBLE_MAX_LENGTH
255249

256250
#define PHP_GCC_VERSION ZEND_GCC_VERSION
257251
#define PHP_ATTRIBUTE_MALLOC ZEND_ATTRIBUTE_MALLOC

main/snprintf.c

+1-101
Original file line numberDiff line numberDiff line change
@@ -128,106 +128,6 @@ static inline char *php_fcvt(double value, int ndigit, int *decpt, bool *sign) /
128128
}
129129
/* }}} */
130130

131-
PHPAPI char *php_gcvt(double value, int ndigit, char dec_point, char exponent, char *buf) /* {{{ */
132-
{
133-
char *digits, *dst, *src;
134-
int i, decpt;
135-
bool sign;
136-
int mode = ndigit >= 0 ? 2 : 0;
137-
138-
if (mode == 0) {
139-
ndigit = 17;
140-
}
141-
digits = zend_dtoa(value, mode, ndigit, &decpt, &sign, NULL);
142-
if (decpt == 9999) {
143-
/*
144-
* Infinity or NaN, convert to inf or nan with sign.
145-
* We assume the buffer is at least ndigit long.
146-
*/
147-
snprintf(buf, ndigit + 1, "%s%s", (sign && *digits == 'I') ? "-" : "", *digits == 'I' ? "INF" : "NAN");
148-
zend_freedtoa(digits);
149-
return (buf);
150-
}
151-
152-
dst = buf;
153-
if (sign) {
154-
*dst++ = '-';
155-
}
156-
157-
if ((decpt >= 0 && decpt > ndigit) || decpt < -3) { /* use E-style */
158-
/* exponential format (e.g. 1.2345e+13) */
159-
if (--decpt < 0) {
160-
sign = 1;
161-
decpt = -decpt;
162-
} else {
163-
sign = 0;
164-
}
165-
src = digits;
166-
*dst++ = *src++;
167-
*dst++ = dec_point;
168-
if (*src == '\0') {
169-
*dst++ = '0';
170-
} else {
171-
do {
172-
*dst++ = *src++;
173-
} while (*src != '\0');
174-
}
175-
*dst++ = exponent;
176-
if (sign) {
177-
*dst++ = '-';
178-
} else {
179-
*dst++ = '+';
180-
}
181-
if (decpt < 10) {
182-
*dst++ = '0' + decpt;
183-
*dst = '\0';
184-
} else {
185-
/* XXX - optimize */
186-
int n;
187-
for (n = decpt, i = 0; (n /= 10) != 0; i++);
188-
dst[i + 1] = '\0';
189-
while (decpt != 0) {
190-
dst[i--] = '0' + decpt % 10;
191-
decpt /= 10;
192-
}
193-
}
194-
} else if (decpt < 0) {
195-
/* standard format 0. */
196-
*dst++ = '0'; /* zero before decimal point */
197-
*dst++ = dec_point;
198-
do {
199-
*dst++ = '0';
200-
} while (++decpt < 0);
201-
src = digits;
202-
while (*src != '\0') {
203-
*dst++ = *src++;
204-
}
205-
*dst = '\0';
206-
} else {
207-
/* standard format */
208-
for (i = 0, src = digits; i < decpt; i++) {
209-
if (*src != '\0') {
210-
*dst++ = *src++;
211-
} else {
212-
*dst++ = '0';
213-
}
214-
}
215-
if (*src != '\0') {
216-
if (src == digits) {
217-
*dst++ = '0'; /* zero before decimal point */
218-
}
219-
*dst++ = dec_point;
220-
for (i = decpt; digits[i] != '\0'; i++) {
221-
*dst++ = digits[i];
222-
}
223-
}
224-
*dst = '\0';
225-
}
226-
zend_freedtoa(digits);
227-
return (buf);
228-
}
229-
/* }}} */
230-
231131
/* {{{ Apache license */
232132
/* ====================================================================
233133
* Copyright (c) 1995-1998 The Apache Group. All rights reserved.
@@ -1043,7 +943,7 @@ static size_t format_converter(buffy * odp, const char *fmt, va_list ap) /* {{{
1043943
lconv = localeconv();
1044944
}
1045945
#endif
1046-
s = php_gcvt(fp_num, precision, (*fmt=='H' || *fmt == 'k') ? '.' : LCONV_DECIMAL_POINT, (*fmt == 'G' || *fmt == 'H')?'E':'e', &num_buf[1]);
946+
s = zend_gcvt(fp_num, precision, (*fmt=='H' || *fmt == 'k') ? '.' : LCONV_DECIMAL_POINT, (*fmt == 'G' || *fmt == 'H')?'E':'e', &num_buf[1]);
1047947
if (*s == '-') {
1048948
prefix_char = *s++;
1049949
} else if (print_sign) {

main/snprintf.h

+3-2
Original file line numberDiff line numberDiff line change
@@ -75,13 +75,14 @@ PHPAPI int ap_php_snprintf(char *, size_t, const char *, ...) ZEND_ATTRIBUTE_FOR
7575
PHPAPI int ap_php_vsnprintf(char *, size_t, const char *, va_list ap);
7676
PHPAPI int ap_php_vasprintf(char **buf, const char *format, va_list ap);
7777
PHPAPI int ap_php_asprintf(char **buf, const char *format, ...) ZEND_ATTRIBUTE_FORMAT(printf, 2, 3);
78-
PHPAPI char * php_gcvt(double value, int ndigit, char dec_point, char exponent, char *buf);
7978
PHPAPI char * php_0cvt(double value, int ndigit, char dec_point, char exponent, char *buf);
8079
PHPAPI char * php_conv_fp(char format, double num,
8180
bool add_dp, int precision, char dec_point, bool * is_negative, char *buf, size_t *len);
8281

8382
END_EXTERN_C()
8483

84+
#define php_gcvt zend_gcvt
85+
8586
#ifdef slprintf
8687
#undef slprintf
8788
#endif
@@ -138,7 +139,7 @@ PHPAPI char * ap_php_conv_p2(uint64_t num, int nbits,
138139
* another level (see NDIG in php_conv_fp()).
139140
* Applies to the formatting functions of both spprintf.c and snprintf.c, which
140141
* use equally sized buffers of MAX_BUF_SIZE = 512 to hold the result of the
141-
* call to php_gcvt().
142+
* call to zend_gcvt().
142143
* This should be reasonably smaller than MAX_BUF_SIZE (I think MAX_BUF_SIZE - 9
143144
* should be enough, but let's give some more space) */
144145
#define FORMAT_CONV_MAX_PRECISION 500

main/spprintf.c

+2-2
Original file line numberDiff line numberDiff line change
@@ -141,7 +141,7 @@
141141
* NUM_BUF_SIZE is the size of the buffer used for arithmetic conversions
142142
* which can be at most max length of double
143143
*/
144-
#define NUM_BUF_SIZE PHP_DOUBLE_MAX_LENGTH
144+
#define NUM_BUF_SIZE ZEND_DOUBLE_MAX_LENGTH
145145

146146
#define NUM(c) (c - '0')
147147

@@ -651,7 +651,7 @@ static void xbuf_format_converter(void *xbuf, bool is_char, const char *fmt, va_
651651
lconv = localeconv();
652652
}
653653
#endif
654-
s = php_gcvt(fp_num, precision, (*fmt=='H' || *fmt == 'k') ? '.' : LCONV_DECIMAL_POINT, (*fmt == 'G' || *fmt == 'H')?'E':'e', &num_buf[1]);
654+
s = zend_gcvt(fp_num, precision, (*fmt=='H' || *fmt == 'k') ? '.' : LCONV_DECIMAL_POINT, (*fmt == 'G' || *fmt == 'H')?'E':'e', &num_buf[1]);
655655
if (*s == '-')
656656
prefix_char = *s++;
657657
else if (print_sign)

0 commit comments

Comments
 (0)