Skip to content

Commit 65a5c18

Browse files
committed
Add functions to convert i64/u64 to string
PDO implement half of this, but this functionality is generally useful. Provide these as zend_u64_to_str and zend_i64_to_str to complement zend_long_to_str.
1 parent 0e7b4d0 commit 65a5c18

File tree

7 files changed

+61
-56
lines changed

7 files changed

+61
-56
lines changed

Zend/zend_operators.c

Lines changed: 53 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3044,6 +3044,59 @@ ZEND_API zend_string* ZEND_FASTCALL zend_long_to_str(zend_long num) /* {{{ */
30443044
}
30453045
/* }}} */
30463046

3047+
/* buf points to the END of the buffer */
3048+
static zend_always_inline char *zend_print_u64_to_buf(char *buf, uint64_t num64) {
3049+
#if SIZEOF_ZEND_LONG == 8
3050+
return zend_print_ulong_to_buf(buf, num64);
3051+
#else
3052+
*buf = '\0';
3053+
while (num64 > ZEND_ULONG_MAX) {
3054+
*--buf = (char) (num64 % 10) + '0';
3055+
num64 /= 10;
3056+
}
3057+
3058+
zend_ulong num = (zend_ulong) num64;
3059+
do {
3060+
*--buf = (char) (num % 10) + '0';
3061+
num /= 10;
3062+
} while (num > 0);
3063+
return buf;
3064+
#endif
3065+
}
3066+
3067+
/* buf points to the END of the buffer */
3068+
static zend_always_inline char *zend_print_i64_to_buf(char *buf, int64_t num) {
3069+
if (num < 0) {
3070+
char *result = zend_print_u64_to_buf(buf, ~((uint64_t) num) + 1);
3071+
*--result = '-';
3072+
return result;
3073+
} else {
3074+
return zend_print_u64_to_buf(buf, num);
3075+
}
3076+
}
3077+
3078+
ZEND_API zend_string* ZEND_FASTCALL zend_u64_to_str(uint64_t num)
3079+
{
3080+
if (num <= 9) {
3081+
return ZSTR_CHAR((zend_uchar)'0' + (zend_uchar)num);
3082+
} else {
3083+
char buf[20 + 1];
3084+
char *res = zend_print_u64_to_buf(buf + sizeof(buf) - 1, num);
3085+
return zend_string_init(res, buf + sizeof(buf) - 1 - res, 0);
3086+
}
3087+
}
3088+
3089+
ZEND_API zend_string* ZEND_FASTCALL zend_i64_to_str(int64_t num)
3090+
{
3091+
if ((uint64_t)num <= 9) {
3092+
return ZSTR_CHAR((zend_uchar)'0' + (zend_uchar)num);
3093+
} else {
3094+
char buf[20 + 1];
3095+
char *res = zend_print_i64_to_buf(buf + sizeof(buf) - 1, num);
3096+
return zend_string_init(res, buf + sizeof(buf) - 1 - res, 0);
3097+
}
3098+
}
3099+
30473100
ZEND_API zend_uchar ZEND_FASTCALL is_numeric_str_function(const zend_string *str, zend_long *lval, double *dval) /* {{{ */ {
30483101
return is_numeric_string(ZSTR_VAL(str), ZSTR_LEN(str), lval, dval, false);
30493102
}

Zend/zend_operators.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -876,6 +876,8 @@ static zend_always_inline char *zend_print_long_to_buf(char *buf, zend_long num)
876876
}
877877

878878
ZEND_API zend_string* ZEND_FASTCALL zend_long_to_str(zend_long num);
879+
ZEND_API zend_string* ZEND_FASTCALL zend_u64_to_str(uint64_t num);
880+
ZEND_API zend_string* ZEND_FASTCALL zend_i64_to_str(int64_t num);
879881

880882
static zend_always_inline void zend_unwrap_reference(zval *op) /* {{{ */
881883
{

ext/mysqlnd/mysqlnd_ps_codec.c

Lines changed: 4 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -55,8 +55,6 @@ void
5555
ps_fetch_from_1_to_8_bytes(zval * zv, const MYSQLND_FIELD * const field, const unsigned int pack_len,
5656
const zend_uchar ** row, unsigned int byte_count)
5757
{
58-
char tmp[22];
59-
size_t tmp_len = 0;
6058
bool is_bit = field->type == MYSQL_TYPE_BIT;
6159
DBG_ENTER("ps_fetch_from_1_to_8_bytes");
6260
DBG_INF_FMT("zv=%p byte_count=%u", zv, byte_count);
@@ -76,22 +74,20 @@ ps_fetch_from_1_to_8_bytes(zval * zv, const MYSQLND_FIELD * const field, const u
7674

7775
if (field->flags & ZEROFILL_FLAG) {
7876
DBG_INF("stringify due to zerofill");
79-
tmp_len = sprintf((char *)&tmp, "%0*" PRIu64, (int) field->length, uval);
80-
DBG_INF_FMT("value=%s", tmp);
77+
ZVAL_STR(zv, zend_strpprintf(0, "%0*" PRIu64, (int) field->length, uval));
8178
} else
8279
#if SIZEOF_ZEND_LONG==4
8380
if (uval > INT_MAX) {
8481
DBG_INF("stringify");
85-
tmp_len = sprintf((char *)&tmp, "%" PRIu64, uval);
82+
ZVAL_STR(zv, zend_u64_to_str(uval));
8683
} else
8784
#endif /* #if SIZEOF_LONG==4 */
8885
{
8986
if (byte_count < 8 || uval <= L64(9223372036854775807)) {
9087
ZVAL_LONG(zv, (zend_long) uval); /* the cast is safe, we are in the range */
9188
} else {
9289
DBG_INF("stringify");
93-
tmp_len = sprintf((char *)&tmp, "%" PRIu64, uval);
94-
DBG_INF_FMT("value=%s", tmp);
90+
ZVAL_STR(zv, zend_u64_to_str(uval));
9591
}
9692
}
9793
} else {
@@ -112,17 +108,14 @@ ps_fetch_from_1_to_8_bytes(zval * zv, const MYSQLND_FIELD * const field, const u
112108
#if SIZEOF_ZEND_LONG==4
113109
if ((L64(2147483647) < (int64_t) lval) || (L64(-2147483648) > (int64_t) lval)) {
114110
DBG_INF("stringify");
115-
tmp_len = sprintf((char *)&tmp, "%" PRIi64, lval);
111+
ZVAL_STR(zv, zend_i64_to_str(lval));
116112
} else
117113
#endif /* SIZEOF */
118114
{
119115
ZVAL_LONG(zv, (zend_long) lval); /* the cast is safe, we are in the range */
120116
}
121117
}
122118

123-
if (tmp_len) {
124-
ZVAL_STRINGL(zv, tmp, tmp_len);
125-
}
126119
(*row)+= byte_count;
127120
DBG_VOID_RETURN;
128121
}

ext/pdo/pdo.c

Lines changed: 0 additions & 41 deletions
Original file line numberDiff line numberDiff line change
@@ -240,47 +240,6 @@ PDO_API int php_pdo_parse_data_source(const char *data_source, zend_ulong data_s
240240
}
241241
/* }}} */
242242

243-
/* TODO Refactor */
244-
static const char digit_vec[] = "0123456789";
245-
PDO_API zend_string *php_pdo_int64_to_str(int64_t i64) /* {{{ */
246-
{
247-
char buffer[65];
248-
char outbuf[65] = "";
249-
register char *p;
250-
zend_long long_val;
251-
char *dst = outbuf;
252-
253-
if (i64 == 0) {
254-
return ZSTR_CHAR('0');
255-
}
256-
257-
if (i64 < 0) {
258-
i64 = -i64;
259-
*dst++ = '-';
260-
}
261-
262-
p = &buffer[sizeof(buffer)-1];
263-
*p = '\0';
264-
265-
while ((uint64_t)i64 > (uint64_t)ZEND_LONG_MAX) {
266-
uint64_t quo = (uint64_t)i64 / (unsigned int)10;
267-
unsigned int rem = (unsigned int)(i64 - quo*10U);
268-
*--p = digit_vec[rem];
269-
i64 = (int64_t)quo;
270-
}
271-
long_val = (zend_long)i64;
272-
while (long_val != 0) {
273-
zend_long quo = long_val / 10;
274-
*--p = digit_vec[(unsigned int)(long_val - quo * 10)];
275-
long_val = quo;
276-
}
277-
while ((*dst++ = *p++) != 0)
278-
;
279-
*dst = '\0';
280-
return zend_string_init(outbuf, strlen(outbuf), 0);
281-
}
282-
/* }}} */
283-
284243
/* {{{ PHP_MINIT_FUNCTION */
285244
PHP_MINIT_FUNCTION(pdo)
286245
{

ext/pdo/php_pdo_driver.h

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -26,8 +26,6 @@ typedef struct _pdo_stmt_t pdo_stmt_t;
2626
typedef struct _pdo_row_t pdo_row_t;
2727
struct pdo_bound_param_data;
2828

29-
PDO_API zend_string *php_pdo_int64_to_str(int64_t i64);
30-
3129
#ifndef TRUE
3230
# define TRUE 1
3331
#endif

ext/pdo_mysql/mysql_driver.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -289,7 +289,7 @@ static zend_string *pdo_mysql_last_insert_id(pdo_dbh_t *dbh, const zend_string *
289289
{
290290
pdo_mysql_db_handle *H = (pdo_mysql_db_handle *)dbh->driver_data;
291291
PDO_DBG_ENTER("pdo_mysql_last_insert_id");
292-
PDO_DBG_RETURN(php_pdo_int64_to_str(mysql_insert_id(H->server)));
292+
PDO_DBG_RETURN(zend_i64_to_str(mysql_insert_id(H->server)));
293293
}
294294
/* }}} */
295295

ext/pdo_sqlite/sqlite_driver.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -220,7 +220,7 @@ static zend_string *pdo_sqlite_last_insert_id(pdo_dbh_t *dbh, const zend_string
220220
{
221221
pdo_sqlite_db_handle *H = (pdo_sqlite_db_handle *)dbh->driver_data;
222222

223-
return php_pdo_int64_to_str(sqlite3_last_insert_rowid(H->db));
223+
return zend_i64_to_str(sqlite3_last_insert_rowid(H->db));
224224
}
225225

226226
/* NB: doesn't handle binary strings... use prepared stmts for that */

0 commit comments

Comments
 (0)