📄 formatted_print.c
字号:
int width, char padding, int alignment, int n, char *chartable, int expprec){ char numbuf[NUM_BUF_SIZE]; register unsigned long num; register unsigned int i = NUM_BUF_SIZE - 1; register int andbits = (1 << n) - 1; PRINTF_DEBUG(("sprintf: append2n(%x, %x, %x, %d, %d, '%c', %d, %d, %x)\n", *buffer, pos, size, number, width, padding, alignment, n, chartable)); PRINTF_DEBUG(("sprintf: append2n 2^%d andbits=%x\n", n, andbits)); num = (unsigned long) number; numbuf[i] = '\0'; do { numbuf[--i] = chartable[(num & andbits)]; num >>= n; } while (num > 0); php_sprintf_appendstring(buffer, pos, size, &numbuf[i], width, 0, padding, alignment, (NUM_BUF_SIZE - 1) - i, 0, expprec, 0);}inline static intphp_sprintf_getnumber(char *buffer, int *pos){ char *endptr; register long num = strtol(&buffer[*pos], &endptr, 10); register int i = 0; if (endptr != NULL) { i = (endptr - &buffer[*pos]); } PRINTF_DEBUG(("sprintf_getnumber: number was %d bytes long\n", i)); *pos += i; if (num >= INT_MAX || num < 0) { return -1; } else { return (int) num; }}/* {{{ php_formatted_print * New sprintf implementation for PHP. * * Modifiers: * * " " pad integers with spaces * "-" left adjusted field * n field size * "."n precision (floats only) * "+" Always place a sign (+ or -) in front of a number * * Type specifiers: * * "%" literal "%", modifiers are ignored. * "b" integer argument is printed as binary * "c" integer argument is printed as a single character * "d" argument is an integer * "f" the argument is a float, the decimal separator is locale-aware * "F" the argument is a float, but the decimal separator is always "." * "o" integer argument is printed as octal * "s" argument is a string * "x" integer argument is printed as lowercase hexadecimal * "X" integer argument is printed as uppercase hexadecimal * */static char *php_formatted_print(int ht, int *len, int use_array TSRMLS_DC){ zval ***args, **z_format, **array; int argc, size = 240, inpos = 0, outpos = 0, temppos; int alignment, currarg, adjusting, argnum, width, precision; char *format, *result, padding; int always_sign; argc = ZEND_NUM_ARGS(); if (use_array) { int i = 1; if (ZEND_NUM_ARGS() != 2 || zend_get_parameters_ex(argc, &z_format, &array) == FAILURE) { WRONG_PARAM_COUNT_WITH_RETVAL(NULL); } SEPARATE_ZVAL(array); convert_to_array_ex(array); argc = 1 + zend_hash_num_elements(Z_ARRVAL_PP(array)); args = (zval ***)safe_emalloc(argc, sizeof(zval *), 0); args[0] = z_format; for (zend_hash_internal_pointer_reset(Z_ARRVAL_PP(array)); zend_hash_get_current_data(Z_ARRVAL_PP(array), (void **)&args[i++]) == SUCCESS; zend_hash_move_forward(Z_ARRVAL_PP(array))); } else { if (argc < 1) { WRONG_PARAM_COUNT_WITH_RETVAL(NULL); } args = (zval ***)safe_emalloc(argc, sizeof(zval *), 0); if (zend_get_parameters_array_ex(argc, args) == FAILURE) { efree(args); WRONG_PARAM_COUNT_WITH_RETVAL(NULL); } } convert_to_string_ex(args[0]); format = Z_STRVAL_PP(args[0]); result = emalloc(size); currarg = 1; while (inpos<Z_STRLEN_PP(args[0])) { int expprec = 0, multiuse = 0; zval *tmp; PRINTF_DEBUG(("sprintf: format[%d]='%c'\n", inpos, format[inpos])); PRINTF_DEBUG(("sprintf: outpos=%d\n", outpos)); if (format[inpos] != '%') { php_sprintf_appendchar(&result, &outpos, &size, format[inpos++] TSRMLS_CC); } else if (format[inpos + 1] == '%') { php_sprintf_appendchar(&result, &outpos, &size, '%' TSRMLS_CC); inpos += 2; } else { /* starting a new format specifier, reset variables */ alignment = ALIGN_RIGHT; adjusting = 0; padding = ' '; always_sign = 0; inpos++; /* skip the '%' */ PRINTF_DEBUG(("sprintf: first looking at '%c', inpos=%d\n", format[inpos], inpos)); if (isascii((int)format[inpos]) && !isalpha((int)format[inpos])) { /* first look for argnum */ temppos = inpos; while (isdigit((int)format[temppos])) temppos++; if (format[temppos] == '$') { argnum = php_sprintf_getnumber(format, &inpos); if (argnum <= 0) { efree(result); efree(args); php_error_docref(NULL TSRMLS_CC, E_WARNING, "Argument number must be greater then zero."); return NULL; } multiuse = 1; inpos++; /* skip the '$' */ } else { argnum = currarg++; } /* after argnum comes modifiers */ PRINTF_DEBUG(("sprintf: looking for modifiers\n" "sprintf: now looking at '%c', inpos=%d\n", format[inpos], inpos)); for (;; inpos++) { if (format[inpos] == ' ' || format[inpos] == '0') { padding = format[inpos]; } else if (format[inpos] == '-') { alignment = ALIGN_LEFT; /* space padding, the default */ } else if (format[inpos] == '+') { always_sign = 1; } else if (format[inpos] == '\'') { padding = format[++inpos]; } else { PRINTF_DEBUG(("sprintf: end of modifiers\n")); break; } } PRINTF_DEBUG(("sprintf: padding='%c'\n", padding)); PRINTF_DEBUG(("sprintf: alignment=%s\n", (alignment == ALIGN_LEFT) ? "left" : "right")); /* after modifiers comes width */ if (isdigit((int)format[inpos])) { PRINTF_DEBUG(("sprintf: getting width\n")); if ((width = php_sprintf_getnumber(format, &inpos)) < 0) { efree(result); efree(args); php_error_docref(NULL TSRMLS_CC, E_WARNING, "Width must be greater then zero and less then %d.", INT_MAX); return NULL; } adjusting |= ADJ_WIDTH; } else { width = 0; } PRINTF_DEBUG(("sprintf: width=%d\n", width)); /* after width and argnum comes precision */ if (format[inpos] == '.') { inpos++; PRINTF_DEBUG(("sprintf: getting precision\n")); if (isdigit((int)format[inpos])) { if ((precision = php_sprintf_getnumber(format, &inpos)) < 0) { efree(result); efree(args); php_error_docref(NULL TSRMLS_CC, E_WARNING, "Precision must be greater then zero and less then %d.", INT_MAX); return NULL; } adjusting |= ADJ_PRECISION; expprec = 1; } else { precision = 0; } } else { precision = 0; } PRINTF_DEBUG(("sprintf: precision=%d\n", precision)); } else { width = precision = 0; argnum = currarg++; } if (argnum >= argc) { efree(result); efree(args); php_error_docref(NULL TSRMLS_CC, E_WARNING, "Too few arguments"); return NULL; } if (format[inpos] == 'l') { inpos++; } PRINTF_DEBUG(("sprintf: format character='%c'\n", format[inpos])); /* now we expect to find a type specifier */ if (multiuse) { MAKE_STD_ZVAL(tmp); *tmp = **(args[argnum]); INIT_PZVAL(tmp); zval_copy_ctor(tmp); } else { SEPARATE_ZVAL(args[argnum]); tmp = *(args[argnum]); } switch (format[inpos]) { case 's': convert_to_string(tmp); php_sprintf_appendstring(&result, &outpos, &size, Z_STRVAL_P(tmp), width, precision, padding, alignment, Z_STRLEN_P(tmp), 0, expprec, 0); break; case 'd': convert_to_long(tmp); php_sprintf_appendint(&result, &outpos, &size, Z_LVAL_P(tmp), width, padding, alignment, always_sign); break; case 'u': convert_to_long(tmp); php_sprintf_appenduint(&result, &outpos, &size, Z_LVAL_P(tmp), width, padding, alignment); break; case 'e': case 'f': case 'F': /* XXX not done */ convert_to_double(tmp); php_sprintf_appenddouble(&result, &outpos, &size, Z_DVAL_P(tmp), width, padding, alignment, precision, adjusting, format[inpos], always_sign TSRMLS_CC); break; case 'c': convert_to_long(tmp); php_sprintf_appendchar(&result, &outpos, &size, (char) Z_LVAL_P(tmp) TSRMLS_CC); break; case 'o': convert_to_long(tmp); php_sprintf_append2n(&result, &outpos, &size, Z_LVAL_P(tmp), width, padding, alignment, 3, hexchars, expprec); break; case 'x': convert_to_long(tmp); php_sprintf_append2n(&result, &outpos, &size, Z_LVAL_P(tmp), width, padding, alignment, 4, hexchars, expprec); break; case 'X': convert_to_long(tmp); php_sprintf_append2n(&result, &outpos, &size, Z_LVAL_P(tmp), width, padding, alignment, 4, HEXCHARS, expprec); break; case 'b': convert_to_long(tmp); php_sprintf_append2n(&result, &outpos, &size, Z_LVAL_P(tmp), width, padding, alignment, 1, hexchars, expprec); break; case '%': php_sprintf_appendchar(&result, &outpos, &size, '%' TSRMLS_CC); break; default: break; } if (multiuse) { zval_ptr_dtor(&tmp); } inpos++; } } efree(args); /* possibly, we have to make sure we have room for the terminating null? */ result[outpos]=0; *len = outpos; return result;}/* }}} *//* {{{ proto string sprintf(string format [, mixed arg1 [, mixed ...]]) Return a formatted string */PHP_FUNCTION(user_sprintf){ char *result; int len; if ((result=php_formatted_print(ht, &len, 0 TSRMLS_CC))==NULL) { RETURN_FALSE; } RETVAL_STRINGL(result, len, 1); efree(result);}/* }}} *//* {{{ proto string vsprintf(string format, array args) Return a formatted string */PHP_FUNCTION(vsprintf){ char *result; int len; if ((result=php_formatted_print(ht, &len, 1 TSRMLS_CC))==NULL) { RETURN_FALSE; } RETVAL_STRINGL(result, len, 1); efree(result);}/* }}} *//* {{{ proto int printf(string format [, mixed arg1 [, mixed ...]]) Output a formatted string */PHP_FUNCTION(user_printf){ char *result; int len; if ((result=php_formatted_print(ht, &len, 0 TSRMLS_CC))==NULL) { RETURN_FALSE; } PHPWRITE(result, len); efree(result); RETURN_LONG(len);}/* }}} *//* {{{ proto int vprintf(string format, array args) Output a formatted string */PHP_FUNCTION(vprintf){ char *result; int len; if ((result=php_formatted_print(ht, &len, 1 TSRMLS_CC))==NULL) { RETURN_FALSE; } PHPWRITE(result, len); efree(result); RETURN_LONG(len);}/* }}} *//* * Local variables: * tab-width: 4 * c-basic-offset: 4 * End: * vim600: sw=4 ts=4 fdm=marker * vim<600: sw=4 ts=4 */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -