PHP Classes

File: ext/kernel/string.c

Recommend this page to a friend!
  Classes of Alien Fernandez   Phady Framework   ext/kernel/string.c   Download  
File: ext/kernel/string.c
Role: Auxiliary data
Content type: text/plain
Description: Auxiliary data
Class: Phady Framework
Web application MVC framework based on Phalcon
Author: By
Last change:
Date: 8 years ago
Size: 36,169 bytes
 

Contents

Class file image Download
/* +------------------------------------------------------------------------+ | Zephir Language | +------------------------------------------------------------------------+ | Copyright (c) 2011-2015 Zephir Team (http://www.zephir-lang.com) | +------------------------------------------------------------------------+ | This source file is subject to the New BSD License that is bundled | | with this package in the file docs/LICENSE.txt. | | | | If you did not receive a copy of the license and are unable to | | obtain it through the world-wide-web, please send an email | | to license@zephir-lang.com so we can send you a copy immediately. | +------------------------------------------------------------------------+ | Authors: Andres Gutierrez <andres@zephir-lang.com> | | Eduar Carvajal <eduar@zephir-lang.com> | | Vladimir Kolesnikov <vladimir@extrememember.com> | +------------------------------------------------------------------------+ */ #ifdef HAVE_CONFIG_H #include "config.h" #endif #include <ctype.h> #include <php.h> #include "php_ext.h" #include "php_main.h" #include <ext/standard/php_smart_str.h> #include <ext/standard/php_string.h> #include <ext/standard/php_rand.h> #include <ext/standard/php_lcg.h> #include <ext/standard/php_http.h> #include "ext/standard/base64.h" #include "ext/standard/md5.h" #include "ext/standard/crc32.h" #include "ext/standard/url.h" #include "ext/standard/html.h" #include "ext/date/php_date.h" #ifdef ZEPHIR_USE_PHP_PCRE #include <ext/pcre/php_pcre.h> #endif #ifdef ZEPHIR_USE_PHP_JSON #include <ext/json/php_json.h> #endif #include "kernel/main.h" #include "kernel/memory.h" #include "kernel/string.h" #include "kernel/operators.h" #include "kernel/fcall.h" #define PH_RANDOM_ALNUM 0 #define PH_RANDOM_ALPHA 1 #define PH_RANDOM_HEXDEC 2 #define PH_RANDOM_NUMERIC 3 #define PH_RANDOM_NOZERO 4 /** * Fast call to php strlen */ void zephir_fast_strlen(zval *return_value, zval *str){ zval copy; int use_copy = 0; if (Z_TYPE_P(str) != IS_STRING) { zend_make_printable_zval(str, &copy, &use_copy); if (use_copy) { str = &copy; } } ZVAL_LONG(return_value, Z_STRLEN_P(str)); if (use_copy) { zval_dtor(str); } } /** * Fast call to php strlen */ int zephir_fast_strlen_ev(zval *str){ zval copy; int use_copy = 0, length; if (Z_TYPE_P(str) != IS_STRING) { zend_make_printable_zval(str, &copy, &use_copy); if (use_copy) { str = &copy; } } length = Z_STRLEN_P(str); if (use_copy) { zval_dtor(str); } return length; } /** * Fast call to php strlen */ void zephir_fast_strtolower(zval *return_value, zval *str){ zval copy; int use_copy = 0; char *lower_str; unsigned int length; if (Z_TYPE_P(str) != IS_STRING) { zend_make_printable_zval(str, &copy, &use_copy); if (use_copy) { str = &copy; } } length = Z_STRLEN_P(str); lower_str = estrndup(Z_STRVAL_P(str), length); php_strtolower(lower_str, length); if (use_copy) { zval_dtor(str); } ZVAL_STRINGL(return_value, lower_str, length, 0); } void zephir_strtolower_inplace(zval *s) { if (likely(Z_TYPE_P(s) == IS_STRING)) { php_strtolower(Z_STRVAL_P(s), Z_STRLEN_P(s)); } } /** * Fast call to php join function */ void zephir_fast_join(zval *result, zval *glue, zval *pieces TSRMLS_DC) { if (Z_TYPE_P(glue) != IS_STRING || Z_TYPE_P(pieces) != IS_ARRAY) { ZVAL_NULL(result); zend_error(E_WARNING, "Invalid arguments supplied for join()"); return; } php_implode(glue, pieces, result TSRMLS_CC); } /** * Appends to a smart_str a printable version of a zval */ void zephir_append_printable_zval(smart_str *implstr, zval **tmp TSRMLS_DC) { zval tmp_val; unsigned int str_len; switch (Z_TYPE_PP(tmp)) { case IS_STRING: smart_str_appendl(implstr, Z_STRVAL_PP(tmp), Z_STRLEN_PP(tmp)); break; case IS_LONG: smart_str_append_long(implstr, Z_LVAL_PP(tmp)); break; case IS_BOOL: if (Z_LVAL_PP(tmp) == 1) { smart_str_appendl(implstr, "1", sizeof("1") - 1); } break; case IS_NULL: break; case IS_DOUBLE: { char *stmp; str_len = spprintf(&stmp, 0, "%.*G", (int) EG(precision), Z_DVAL_PP(tmp)); smart_str_appendl(implstr, stmp, str_len); efree(stmp); } break; case IS_OBJECT: { int copy; zval expr; zend_make_printable_zval(*tmp, &expr, &copy); smart_str_appendl(implstr, Z_STRVAL(expr), Z_STRLEN(expr)); if (copy) { zval_dtor(&expr); } } break; default: tmp_val = **tmp; zval_copy_ctor(&tmp_val); convert_to_string(&tmp_val); smart_str_appendl(implstr, Z_STRVAL(tmp_val), Z_STRLEN(tmp_val)); zval_dtor(&tmp_val); break; } } /** * Fast join function * This function is an adaption of the php_implode function * */ void zephir_fast_join_str(zval *return_value, char *glue, unsigned int glue_length, zval *pieces TSRMLS_DC) { zval **tmp; HashTable *arr; HashPosition pos; smart_str implstr = {0}; unsigned int numelems, i = 0; if (Z_TYPE_P(pieces) != IS_ARRAY) { php_error_docref(NULL TSRMLS_CC, E_WARNING, "Invalid arguments supplied for fast_join()"); RETURN_EMPTY_STRING(); } arr = Z_ARRVAL_P(pieces); numelems = zend_hash_num_elements(arr); if (numelems == 0) { RETURN_EMPTY_STRING(); } zend_hash_internal_pointer_reset_ex(arr, &pos); while (zend_hash_get_current_data_ex(arr, (void **) &tmp, &pos) == SUCCESS) { zephir_append_printable_zval(&implstr, tmp TSRMLS_CC); if (++i != numelems) { smart_str_appendl(&implstr, glue, glue_length); } zend_hash_move_forward_ex(arr, &pos); } smart_str_0(&implstr); if (implstr.len) { RETURN_STRINGL(implstr.c, implstr.len, 0); } else { smart_str_free(&implstr); RETURN_EMPTY_STRING(); } } /** * Convert dash/underscored texts returning camelized */ void zephir_camelize(zval *return_value, const zval *str) { int i, len, first = 0; smart_str camelize_str = {0}; char *marker, ch; if (unlikely(Z_TYPE_P(str) != IS_STRING)) { zend_error(E_WARNING, "Invalid arguments supplied for camelize()"); RETURN_EMPTY_STRING(); } marker = Z_STRVAL_P(str); len = Z_STRLEN_P(str); for (i = 0; i < len; i++) { ch = marker[i]; if (first == 0) { if (ch == '-' || ch == '_') { continue; } first = 1; smart_str_appendc(&camelize_str, toupper(ch)); continue; } if (ch == '-' || ch == '_') { if (i != (len - 1)) { i++; ch = marker[i]; smart_str_appendc(&camelize_str, toupper(ch)); } continue; } smart_str_appendc(&camelize_str, tolower(ch)); } smart_str_0(&camelize_str); if (camelize_str.c) { RETURN_STRINGL(camelize_str.c, camelize_str.len, 0); } RETURN_EMPTY_STRING(); } /** * Convert dash/underscored texts returning camelized */ void zephir_uncamelize(zval *return_value, const zval *str) { unsigned int i; smart_str uncamelize_str = {0}; char *marker, ch; if (Z_TYPE_P(str) != IS_STRING) { zend_error(E_WARNING, "Invalid arguments supplied for camelize()"); return; } marker = Z_STRVAL_P(str); for (i = 0; i < Z_STRLEN_P(str); i++) { ch = *marker; if (ch == '\0') { break; } if (ch >= 'A' && ch <= 'Z') { if (i > 0) { smart_str_appendc(&uncamelize_str, '_'); } smart_str_appendc(&uncamelize_str, (*marker) + 32); } else { smart_str_appendc(&uncamelize_str, (*marker)); } marker++; } smart_str_0(&uncamelize_str); if (uncamelize_str.c) { RETURN_STRINGL(uncamelize_str.c, uncamelize_str.len, 0); } else { RETURN_EMPTY_STRING(); } } /** * Fast call to explode php function */ void zephir_fast_explode(zval *return_value, zval *delimiter, zval *str, long limit TSRMLS_DC) { if (unlikely(Z_TYPE_P(str) != IS_STRING || Z_TYPE_P(delimiter) != IS_STRING)) { zend_error(E_WARNING, "Invalid arguments supplied for explode()"); RETURN_EMPTY_STRING(); } array_init(return_value); php_explode(delimiter, str, return_value, limit); } /** * Fast call to explode php function */ void zephir_fast_explode_str(zval *return_value, const char *delimiter, int delimiter_length, zval *str, long limit TSRMLS_DC) { zval delimiter_zval; if (unlikely(Z_TYPE_P(str) != IS_STRING)) { zend_error(E_WARNING, "Invalid arguments supplied for explode()"); RETURN_EMPTY_STRING(); } ZVAL_STRINGL(&delimiter_zval, delimiter, delimiter_length, 0); array_init(return_value); php_explode(&delimiter_zval, str, return_value, limit); } /** * Check if a string is contained into another */ int zephir_memnstr(const zval *haystack, const zval *needle ZEPHIR_DEBUG_PARAMS) { if (Z_TYPE_P(haystack) != IS_STRING || Z_TYPE_P(needle) != IS_STRING) { #ifndef ZEPHIR_RELEASE zend_error(E_WARNING, "Invalid arguments supplied for memnstr in %s on line %d", file, line); #else zend_error(E_WARNING, "Invalid arguments supplied for memnstr()"); #endif return 0; } if (Z_STRLEN_P(haystack) >= Z_STRLEN_P(needle)) { return php_memnstr(Z_STRVAL_P(haystack), Z_STRVAL_P(needle), Z_STRLEN_P(needle), Z_STRVAL_P(haystack) + Z_STRLEN_P(haystack)) ? 1 : 0; } return 0; } /** * Check if a string is contained into another */ int zephir_memnstr_str(const zval *haystack, char *needle, unsigned int needle_length ZEPHIR_DEBUG_PARAMS) { if (Z_TYPE_P(haystack) != IS_STRING) { #ifndef ZEPHIR_RELEASE zend_error(E_WARNING, "Invalid arguments supplied for memnstr in %s on line %d", file, line); #else zend_error(E_WARNING, "Invalid arguments supplied for memnstr()"); #endif return 0; } if (Z_STRLEN_P(haystack) >= needle_length) { return php_memnstr(Z_STRVAL_P(haystack), needle, needle_length, Z_STRVAL_P(haystack) + Z_STRLEN_P(haystack)) ? 1 : 0; } return 0; } /** * Inmediate function resolution for strpos function */ void zephir_fast_strpos(zval *return_value, const zval *haystack, const zval *needle, unsigned int offset) { const char *found = NULL; if (unlikely(Z_TYPE_P(haystack) != IS_STRING || Z_TYPE_P(needle) != IS_STRING)) { ZVAL_NULL(return_value); zend_error(E_WARNING, "Invalid arguments supplied for strpos()"); return; } if (offset > Z_STRLEN_P(haystack)) { ZVAL_NULL(return_value); zend_error(E_WARNING, "Offset not contained in string"); return; } if (!Z_STRLEN_P(needle)) { ZVAL_NULL(return_value); zend_error(E_WARNING, "Empty delimiter"); return; } found = php_memnstr(Z_STRVAL_P(haystack)+offset, Z_STRVAL_P(needle), Z_STRLEN_P(needle), Z_STRVAL_P(haystack) + Z_STRLEN_P(haystack)); if (found) { ZVAL_LONG(return_value, found-Z_STRVAL_P(haystack)); } else { ZVAL_BOOL(return_value, 0); } } /** * Inmediate function resolution for strpos function */ void zephir_fast_strpos_str(zval *return_value, const zval *haystack, char *needle, unsigned int needle_length) { const char *found = NULL; if (unlikely(Z_TYPE_P(haystack) != IS_STRING)) { ZVAL_NULL(return_value); zend_error(E_WARNING, "Invalid arguments supplied for strpos()"); return; } found = php_memnstr(Z_STRVAL_P(haystack), needle, needle_length, Z_STRVAL_P(haystack) + Z_STRLEN_P(haystack)); if (found) { ZVAL_LONG(return_value, found-Z_STRVAL_P(haystack)); } else { ZVAL_BOOL(return_value, 0); } } /** * Inmediate function resolution for stripos function */ void zephir_fast_stripos_str(zval *return_value, zval *haystack, char *needle, unsigned int needle_length) { const char *found = NULL; char *needle_dup, *haystack_dup; if (unlikely(Z_TYPE_P(haystack) != IS_STRING)) { ZVAL_NULL(return_value); zend_error(E_WARNING, "Invalid arguments supplied for stripos()"); return; } haystack_dup = estrndup(Z_STRVAL_P(haystack), Z_STRLEN_P(haystack)); php_strtolower(haystack_dup, Z_STRLEN_P(haystack)); needle_dup = estrndup(needle, needle_length); php_strtolower(needle_dup, needle_length); found = php_memnstr(haystack_dup, needle, needle_length, haystack_dup + Z_STRLEN_P(haystack)); efree(haystack_dup); efree(needle_dup); if (found) { ZVAL_LONG(return_value, found-Z_STRVAL_P(haystack)); } else { ZVAL_BOOL(return_value, 0); } } /** * Immediate function resolution for str_replace function */ void zephir_fast_str_replace(zval **return_value_ptr, zval *search, zval *replace, zval *subject TSRMLS_DC) { zval replace_copy, search_copy; zval *return_value = *return_value_ptr; int copy_replace = 0, copy_search = 0; if (Z_TYPE_P(subject) != IS_STRING) { ZVAL_NULL(return_value); zend_error(E_WARNING, "Invalid arguments supplied for str_replace()"); return; } /** * Fallback to userland function if the first parameter is an array */ if (Z_TYPE_P(search) == IS_ARRAY) { do { zval *params[] = { search, replace, subject }; zval_ptr_dtor(return_value_ptr); return_value_ptr = NULL; zephir_call_func_aparams(return_value_ptr, "str_replace", sizeof("str_replace")-1, NULL, 0, 3, params TSRMLS_CC); return; } while(0); } if (Z_TYPE_P(replace) != IS_STRING) { zend_make_printable_zval(replace, &replace_copy, &copy_replace); if (copy_replace) { replace = &replace_copy; } } if (Z_TYPE_P(search) != IS_STRING) { zend_make_printable_zval(search, &search_copy, &copy_search); if (copy_search) { search = &search_copy; } } Z_TYPE_P(return_value) = IS_STRING; if (Z_STRLEN_P(subject) == 0) { ZVAL_STRINGL(return_value, "", 0, 1); return; } if (Z_STRLEN_P(search) == 1) { php_char_to_str_ex(Z_STRVAL_P(subject), Z_STRLEN_P(subject), Z_STRVAL_P(search)[0], Z_STRVAL_P(replace), Z_STRLEN_P(replace), return_value, 1, NULL); } else { if (Z_STRLEN_P(search) > 1) { Z_STRVAL_P(return_value) = php_str_to_str_ex(Z_STRVAL_P(subject), Z_STRLEN_P(subject), Z_STRVAL_P(search), Z_STRLEN_P(search), Z_STRVAL_P(replace), Z_STRLEN_P(replace), &Z_STRLEN_P(return_value), 1, NULL); } else { MAKE_COPY_ZVAL(&subject, return_value); } } if (copy_replace) { zval_dtor(replace); } if (copy_search) { zval_dtor(search); } } /** * Fast call to PHP trim() function */ void zephir_fast_trim(zval *return_value, zval *str, zval *charlist, int where TSRMLS_DC) { zval copy; int use_copy = 0; if (Z_TYPE_P(str) != IS_STRING) { zend_make_printable_zval(str, &copy, &use_copy); if (use_copy) { str = &copy; } } if (charlist && Z_TYPE_P(charlist) == IS_STRING) { php_trim(Z_STRVAL_P(str), Z_STRLEN_P(str), Z_STRVAL_P(charlist), Z_STRLEN_P(charlist), return_value, where TSRMLS_CC); } else { php_trim(Z_STRVAL_P(str), Z_STRLEN_P(str), NULL, 0, return_value, where TSRMLS_CC); } if (use_copy) { zval_dtor(&copy); } } /** * Fast call to PHP strip_tags() function */ void zephir_fast_strip_tags(zval *return_value, zval *str) { zval copy; int use_copy = 0; char *stripped; size_t len; if (Z_TYPE_P(str) != IS_STRING) { zend_make_printable_zval(str, &copy, &use_copy); if (use_copy) { str = &copy; } } stripped = estrndup(Z_STRVAL_P(str), Z_STRLEN_P(str)); len = php_strip_tags(stripped, Z_STRLEN_P(str), NULL, NULL, 0); if (use_copy) { zval_dtor(&copy); } ZVAL_STRINGL(return_value, stripped, len, 0); } /** * Fast call to PHP strtoupper() function */ void zephir_fast_strtoupper(zval *return_value, zval *str) { zval copy; int use_copy = 0; char *lower_str; unsigned int length; if (Z_TYPE_P(str) != IS_STRING) { zend_make_printable_zval(str, &copy, &use_copy); if (use_copy) { str = &copy; } } length = Z_STRLEN_P(str); lower_str = estrndup(Z_STRVAL_P(str), length); php_strtoupper(lower_str, length); if (use_copy) { zval_dtor(str); } ZVAL_STRINGL(return_value, lower_str, length, 0); } /** * Checks if a zval string starts with a zval string */ int zephir_start_with(const zval *str, const zval *compared, zval *case_sensitive) { int i; int sensitive = 0; char *op1_cursor, *op2_cursor; if (Z_TYPE_P(str) != IS_STRING || Z_TYPE_P(compared) != IS_STRING) { return 0; } if (!Z_STRLEN_P(compared) || !Z_STRLEN_P(str) || Z_STRLEN_P(compared) > Z_STRLEN_P(str)) { return 0; } if (case_sensitive) { sensitive = zend_is_true(case_sensitive); } if (!sensitive) { return !memcmp(Z_STRVAL_P(str), Z_STRVAL_P(compared), Z_STRLEN_P(compared)); } op1_cursor = Z_STRVAL_P(str); op2_cursor = Z_STRVAL_P(compared); for (i = 0; i < Z_STRLEN_P(compared); i++) { if (tolower(*op1_cursor) != tolower(*op2_cursor)) { return 0; } op1_cursor++; op2_cursor++; } return 1; } /** * Checks if a zval string starts with a string */ int zephir_start_with_str(const zval *str, char *compared, unsigned int compared_length) { if (Z_TYPE_P(str) != IS_STRING || compared_length > Z_STRLEN_P(str)) { return 0; } return !memcmp(Z_STRVAL_P(str), compared, compared_length); } /** * Checks if a string starts with other string */ int zephir_start_with_str_str(char *str, unsigned int str_length, char *compared, unsigned int compared_length) { if (compared_length > str_length) { return 0; } return !memcmp(str, compared, compared_length); } /** * Checks if a zval string ends with a zval string */ int zephir_end_with(const zval *str, const zval *compared, zval *case_sensitive) { int sensitive = 0; int i; char *op1_cursor, *op2_cursor; if (Z_TYPE_P(str) != IS_STRING || Z_TYPE_P(compared) != IS_STRING) { return 0; } if (!Z_STRLEN_P(compared) || !Z_STRLEN_P(str) || Z_STRLEN_P(compared) > Z_STRLEN_P(str)) { return 0; } if (case_sensitive) { sensitive = zend_is_true(case_sensitive); } if (!sensitive) { return !memcmp(Z_STRVAL_P(str) + Z_STRLEN_P(str) - Z_STRLEN_P(compared), Z_STRVAL_P(compared), Z_STRLEN_P(compared)); } op1_cursor = Z_STRVAL_P(str) + Z_STRLEN_P(str) - Z_STRLEN_P(compared); op2_cursor = Z_STRVAL_P(compared); for (i = 0; i < Z_STRLEN_P(compared); ++i) { if (tolower(*op1_cursor) != tolower(*op2_cursor)) { return 0; } ++op1_cursor; ++op2_cursor; } return 1; } /** * Checks if a zval string ends with a *char string */ int zephir_end_with_str(const zval *str, char *compared, unsigned int compared_length) { if (Z_TYPE_P(str) != IS_STRING) { return 0; } if (!compared_length || !Z_STRLEN_P(str) || compared_length > Z_STRLEN_P(str)) { return 0; } return !memcmp(Z_STRVAL_P(str) + Z_STRLEN_P(str) - compared_length, compared, compared_length); } /** * */ void zephir_random_string(zval *return_value, const zval *type, const zval *length TSRMLS_DC) { long i, rand_type, ch; smart_str random_str = {0}; if (Z_TYPE_P(type) != IS_LONG) { return; } if (Z_LVAL_P(type) > PH_RANDOM_NOZERO) { return; } if (Z_TYPE_P(length) != IS_LONG) { return; } /** Generate seed */ if (!BG(mt_rand_is_seeded)) { php_mt_srand(GENERATE_SEED() TSRMLS_CC); } for (i = 0; i < Z_LVAL_P(length); i++) { switch (Z_LVAL_P(type)) { case PH_RANDOM_ALNUM: rand_type = (long) (php_mt_rand(TSRMLS_C) >> 1); RAND_RANGE(rand_type, 0, 3, PHP_MT_RAND_MAX); break; case PH_RANDOM_ALPHA: rand_type = (long) (php_mt_rand(TSRMLS_C) >> 1); RAND_RANGE(rand_type, 1, 2, PHP_MT_RAND_MAX); break; case PH_RANDOM_HEXDEC: rand_type = (long) (php_mt_rand(TSRMLS_C) >> 1); RAND_RANGE(rand_type, 0, 1, PHP_MT_RAND_MAX); break; case PH_RANDOM_NUMERIC: rand_type = 0; break; case PH_RANDOM_NOZERO: rand_type = 5; break; default: continue; } switch (rand_type) { case 0: ch = (long) (php_mt_rand(TSRMLS_C) >> 1); RAND_RANGE(ch, '0', '9', PHP_MT_RAND_MAX); break; case 1: ch = (long) (php_mt_rand(TSRMLS_C) >> 1); RAND_RANGE(ch, 'a', 'f', PHP_MT_RAND_MAX); break; case 2: ch = (long) (php_mt_rand(TSRMLS_C) >> 1); RAND_RANGE(ch, 'a', 'z', PHP_MT_RAND_MAX); break; case 3: ch = (long) (php_mt_rand(TSRMLS_C) >> 1); RAND_RANGE(ch, 'A', 'Z', PHP_MT_RAND_MAX); break; case 5: ch = (long) (php_mt_rand(TSRMLS_C) >> 1); RAND_RANGE(ch, '1', '9', PHP_MT_RAND_MAX); break; default: continue; } smart_str_appendc(&random_str, (unsigned int) ch); } smart_str_0(&random_str); if (random_str.len) { RETURN_STRINGL(random_str.c, random_str.len, 0); } else { smart_str_free(&random_str); RETURN_EMPTY_STRING(); } } /** * Removes slashes at the end of a string */ void zephir_remove_extra_slashes(zval *return_value, const zval *str) { char *cursor, *removed_str; unsigned int i; if (Z_TYPE_P(str) != IS_STRING) { RETURN_EMPTY_STRING(); } if (Z_STRLEN_P(str) > 1) { cursor = Z_STRVAL_P(str); cursor += (Z_STRLEN_P(str) - 1); for (i = Z_STRLEN_P(str); i > 0; i--) { if ((*cursor) == '/') { cursor--; continue; } break; } } else { i = Z_STRLEN_P(str); } removed_str = emalloc(i + 1); memcpy(removed_str, Z_STRVAL_P(str), i); removed_str[i] = '\0'; RETURN_STRINGL(removed_str, i, 0); } /** * This function is not external in the Zend API so we redeclare it here in the extension */ int zephir_spprintf(char **message, int max_len, char *format, ...) { va_list arg; int len; va_start(arg, format); len = vspprintf(message, max_len, format, arg); va_end(arg); return len; } /** * Makes a substr like the PHP function. This function SUPPORT negative from and length */ void zephir_substr(zval *return_value, zval *str, long f, long l, int flags) { zval copy; int use_copy = 0; int str_len; if (Z_TYPE_P(str) != IS_STRING) { if (Z_TYPE_P(str) == IS_NULL || Z_TYPE_P(str) == IS_BOOL) { RETURN_FALSE; } if (Z_TYPE_P(str) != IS_STRING) { zend_make_printable_zval(str, &copy, &use_copy); if (use_copy) { str = &copy; } } } str_len = Z_STRLEN_P(str); if ((flags & ZEPHIR_SUBSTR_NO_LENGTH) == ZEPHIR_SUBSTR_NO_LENGTH) { l = str_len; } if ((l < 0 && -l > str_len)) { if (use_copy) { zval_dtor(str); } RETURN_FALSE; } else { if (l > str_len) { l = str_len; } } if (f > str_len) { if (use_copy) { zval_dtor(str); } RETURN_FALSE; } else { if (f < 0 && -f > str_len) { f = 0; } } if (l < 0 && (l + str_len - f) < 0) { if (use_copy) { zval_dtor(str); } RETURN_FALSE; } /* if "from" position is negative, count start position from the end * of the string */ if (f < 0) { f = str_len + f; if (f < 0) { f = 0; } } /* if "length" position is negative, set it to the length * needed to stop that many chars from the end of the string */ if (l < 0) { l = (str_len - f) + l; if (l < 0) { l = 0; } } if (f >= str_len) { if (use_copy) { zval_dtor(str); } RETURN_FALSE; } if ((f + l) > str_len) { l = str_len - f; } if (!l) { if (use_copy) { zval_dtor(str); } RETURN_EMPTY_STRING(); } ZVAL_STRINGL(return_value, Z_STRVAL_P(str) + f, l, 1); if (use_copy) { zval_dtor(str); } return; } void zephir_append_printable_array(smart_str *implstr, zval *value TSRMLS_DC) { zval **tmp; HashTable *arr; HashPosition pos; unsigned int numelems, i = 0, str_len; arr = Z_ARRVAL_P(value); numelems = zend_hash_num_elements(arr); smart_str_appendc(implstr, '['); if (numelems > 0) { zend_hash_internal_pointer_reset_ex(arr, &pos); while (zend_hash_get_current_data_ex(arr, (void **) &tmp, &pos) == SUCCESS) { /** * We don't serialize objects */ if (Z_TYPE_PP(tmp) == IS_OBJECT) { smart_str_appendc(implstr, 'O'); { char stmp[MAX_LENGTH_OF_LONG + 1]; str_len = slprintf(stmp, sizeof(stmp), "%ld", Z_OBJVAL_PP(tmp).handle); smart_str_appendl(implstr, stmp, str_len); } } else { if (Z_TYPE_PP(tmp) == IS_ARRAY) { zephir_append_printable_array(implstr, *tmp TSRMLS_CC); } else { zephir_append_printable_zval(implstr, tmp TSRMLS_CC); } } if (++i != numelems) { smart_str_appendc(implstr, ','); } zend_hash_move_forward_ex(arr, &pos); } } smart_str_appendc(implstr, ']'); } /** * Creates a unique key to be used as index in a hash */ void zephir_unique_key(zval *return_value, zval *prefix, zval *value TSRMLS_DC) { smart_str implstr = {0}; if (Z_TYPE_P(prefix) == IS_STRING) { smart_str_appendl(&implstr, Z_STRVAL_P(prefix), Z_STRLEN_P(prefix)); } if (Z_TYPE_P(value) == IS_ARRAY) { zephir_append_printable_array(&implstr, value TSRMLS_CC); } else { zephir_append_printable_zval(&implstr, &value TSRMLS_CC); } smart_str_0(&implstr); if (implstr.len) { RETURN_STRINGL(implstr.c, implstr.len, 0); } else { smart_str_free(&implstr); RETURN_NULL(); } } /** * Returns the PHP_EOL (if the passed parameter is TRUE) */ zval *zephir_eol(int eol TSRMLS_DC) { zval *local_eol; /** * Initialize local var */ ZEPHIR_INIT_VAR(local_eol); /** * Check if the eol is true and return PHP_EOL or empty string */ if (eol) { ZVAL_STRING(local_eol, PHP_EOL, 1); } else { ZVAL_EMPTY_STRING(local_eol); } return local_eol; } /** * Base 64 encode */ void zephir_base64_encode(zval *return_value, zval *data) { zval copy; char *encoded; int use_copy = 0, length; if (Z_TYPE_P(data) != IS_STRING) { zend_make_printable_zval(data, &copy, &use_copy); if (use_copy) { data = &copy; } } encoded = (char *) php_base64_encode((unsigned char *)(Z_STRVAL_P(data)), Z_STRLEN_P(data), &length); if (use_copy) { zval_dtor(data); } if (encoded) { RETURN_STRINGL(encoded, length, 0); } else { RETURN_NULL(); } } /** * Base 64 decode */ void zephir_base64_decode(zval *return_value, zval *data) { zval copy; char *decoded; int use_copy = 0, length; if (Z_TYPE_P(data) != IS_STRING) { zend_make_printable_zval(data, &copy, &use_copy); if (use_copy) { data = &copy; } } decoded = (char *) php_base64_decode((unsigned char *)(Z_STRVAL_P(data)), Z_STRLEN_P(data), &length); if (use_copy) { zval_dtor(data); } if (decoded) { RETURN_STRINGL(decoded, length, 0); } else { RETURN_NULL(); } } void zephir_md5(zval *return_value, zval *str) { PHP_MD5_CTX ctx; unsigned char digest[16]; char hexdigest[33]; zval copy; int use_copy = 0; if (Z_TYPE_P(str) != IS_STRING) { zend_make_printable_zval(str, &copy, &use_copy); if (use_copy) { str = &copy; } } PHP_MD5Init(&ctx); PHP_MD5Update(&ctx, Z_STRVAL_P(str), Z_STRLEN_P(str)); PHP_MD5Final(digest, &ctx); make_digest(hexdigest, digest); ZVAL_STRINGL(return_value, hexdigest, 32, 1); } void zephir_crc32(zval *return_value, zval *str TSRMLS_DC) { zval copy; int use_copy = 0; size_t nr; char *p; php_uint32 crc; php_uint32 crcinit = 0; if (Z_TYPE_P(str) != IS_STRING) { zend_make_printable_zval(str, &copy, &use_copy); if (use_copy) { str = &copy; } } p = Z_STRVAL_P(str); nr = Z_STRLEN_P(str); crc = crcinit^0xFFFFFFFF; for (; nr--; ++p) { crc = ((crc >> 8) & 0x00FFFFFF) ^ crc32tab[(crc ^ (*p)) & 0xFF]; } if (use_copy) { zval_dtor(str); } RETVAL_LONG(crc ^ 0xFFFFFFFF); } #ifdef ZEPHIR_USE_PHP_PCRE /** * Execute preg-match without function lookup in the PHP userland */ void zephir_preg_match(zval *return_value, zval *regex, zval *subject, zval *matches, int global, long flags, long offset TSRMLS_DC) { zval copy; int use_copy = 0; pcre_cache_entry *pce; if (Z_TYPE_P(regex) != IS_STRING) { zend_error(E_WARNING, "Invalid arguments supplied for zephir_preg_match()"); RETURN_FALSE; } if (Z_TYPE_P(subject) != IS_STRING) { zend_make_printable_zval(subject, &copy, &use_copy); if (use_copy) { subject = &copy; } } /* Compile regex or get it from cache. */ if ((pce = pcre_get_compiled_regex_cache(Z_STRVAL_P(regex), Z_STRLEN_P(regex) TSRMLS_CC)) == NULL) { if (use_copy) { zval_dtor(subject); } RETURN_FALSE; } if (flags != 0 || offset != 0) { php_pcre_match_impl(pce, Z_STRVAL_P(subject), Z_STRLEN_P(subject), return_value, matches, global, 1, flags, offset TSRMLS_CC); } else { php_pcre_match_impl(pce, Z_STRVAL_P(subject), Z_STRLEN_P(subject), return_value, matches, global, 0, 0, 0 TSRMLS_CC); } if (use_copy) { zval_dtor(&copy); } } #else void zephir_preg_match(zval *return_value, zval *regex, zval *subject, zval *matches, int global, long flags, long offset TSRMLS_DC) { zval tmp_flags; zval tmp_offset; zval *rv = NULL; zval **rvp = &rv; if (matches) { Z_SET_ISREF_P(matches); } ZEPHIR_SINIT_VAR(tmp_flags); ZEPHIR_SINIT_VAR(tmp_offset); ZVAL_LONG(&tmp_flags, flags); ZVAL_LONG(&tmp_offset, offset); { zval *tmp_params[5] = { regex, subject, matches, &tmp_flags, &tmp_offset }; if (global) { zephir_call_func_aparams(rvp, SL("preg_match_all"), NULL, 0, 5, tmp_params TSRMLS_CC); } else { zephir_call_func_aparams(rvp, SL("preg_match"), NULL, 0, 5, tmp_params TSRMLS_CC); } } if (matches) { Z_UNSET_ISREF_P(matches); } if (return_value) { COPY_PZVAL_TO_ZVAL(*return_value, rv); } } #endif /* ZEPHIR_USE_PHP_PCRE */ #ifdef ZEPHIR_USE_PHP_JSON int zephir_json_encode(zval *return_value, zval **return_value_ptr, zval *v, int opts TSRMLS_DC) { smart_str buf = { NULL, 0, 0 }; php_json_encode(&buf, v, opts TSRMLS_CC); smart_str_0(&buf); ZVAL_STRINGL(return_value, buf.c, buf.len, 0); return SUCCESS; } int zephir_json_decode(zval *return_value, zval **return_value_ptr, zval *v, zend_bool assoc TSRMLS_DC) { zval copy; int use_copy = 0; if (unlikely(Z_TYPE_P(v) != IS_STRING)) { zend_make_printable_zval(v, &copy, &use_copy); if (use_copy) { v = &copy; } } php_json_decode(return_value, Z_STRVAL_P(v), Z_STRLEN_P(v), assoc, 512 /* JSON_PARSER_DEFAULT_DEPTH */ TSRMLS_CC); if (unlikely(use_copy)) { zval_dtor(&copy); } return SUCCESS; } #else int zephir_json_encode(zval *return_value, zval **return_value_ptr, zval *v, int opts TSRMLS_DC) { zval zopts; zval *params[2]; ZEPHIR_SINIT_VAR(zopts); ZVAL_LONG(&zopts, opts); params[0] = v; params[1] = &zopts; return zephir_return_call_function(return_value, NULL, ZEND_STRL("json_encode"), NULL, 0, 2, params TSRMLS_CC); } int zephir_json_decode(zval *return_value, zval **return_value_ptr, zval *v, zend_bool assoc TSRMLS_DC) { zval zassoc; zval *params[2]; ZEPHIR_SINIT_VAR(zassoc); ZVAL_BOOL(&zassoc, assoc); params[0] = v; params[1] = &zassoc; return zephir_return_call_function(return_value, NULL, ZEND_STRL("json_decode"), NULL, 0, 2, params TSRMLS_CC); } #endif /* ZEPHIR_USE_PHP_JSON */ void zephir_lcfirst(zval *return_value, zval *s) { zval copy; char *c; int use_copy = 0; if (unlikely(Z_TYPE_P(s) != IS_STRING)) { zend_make_printable_zval(s, &copy, &use_copy); if (use_copy) { s = &copy; } } if (!Z_STRLEN_P(s)) { ZVAL_EMPTY_STRING(return_value); } else { ZVAL_STRINGL(return_value, Z_STRVAL_P(s), Z_STRLEN_P(s), 1); c = Z_STRVAL_P(return_value); *c = tolower((unsigned char)*c); } if (unlikely(use_copy)) { zval_dtor(&copy); } } void zephir_ucfirst(zval *return_value, zval *s) { zval copy; char *c; int use_copy = 0; if (unlikely(Z_TYPE_P(s) != IS_STRING)) { zend_make_printable_zval(s, &copy, &use_copy); if (use_copy) { s = &copy; } } if (!Z_STRLEN_P(s)) { ZVAL_EMPTY_STRING(return_value); } else { ZVAL_STRINGL(return_value, Z_STRVAL_P(s), Z_STRLEN_P(s), 1); c = Z_STRVAL_P(return_value); *c = toupper((unsigned char)*c); } if (unlikely(use_copy)) { zval_dtor(&copy); } } int zephir_http_build_query(zval *return_value, zval *params, char *sep TSRMLS_DC) { if (Z_TYPE_P(params) == IS_ARRAY || Z_TYPE_P(params) == IS_OBJECT) { smart_str formstr = { NULL, 0, 0 }; int res; #if PHP_VERSION_ID < 50400 res = php_url_encode_hash_ex(HASH_OF(params), &formstr, NULL, 0, NULL, 0, NULL, 0, (Z_TYPE_P(params) == IS_OBJECT ? params : NULL), sep TSRMLS_CC); #else res = php_url_encode_hash_ex(HASH_OF(params), &formstr, NULL, 0, NULL, 0, NULL, 0, (Z_TYPE_P(params) == IS_OBJECT ? params : NULL), sep, PHP_QUERY_RFC1738 TSRMLS_CC); #endif if (res == SUCCESS) { if (!formstr.c) { ZVAL_EMPTY_STRING(return_value); } else { smart_str_0(&formstr); ZVAL_STRINGL(return_value, formstr.c, formstr.len, 0); } return SUCCESS; } smart_str_free(&formstr); ZVAL_FALSE(return_value); } else { ZVAL_NULL(return_value); } return FAILURE; } void zephir_htmlspecialchars(zval *return_value, zval *string, zval *quoting, zval *charset TSRMLS_DC) { zval copy; char *escaped, *cs; int qs, use_copy = 0; #if PHP_VERSION_ID < 50400 int escaped_len; #else size_t escaped_len; #endif if (unlikely(Z_TYPE_P(string) != IS_STRING)) { zend_make_printable_zval(string, &copy, &use_copy); if (use_copy) { string = &copy; } } cs = (charset && Z_TYPE_P(charset) == IS_STRING) ? Z_STRVAL_P(charset) : NULL; qs = (quoting && Z_TYPE_P(quoting) == IS_LONG) ? Z_LVAL_P(quoting) : ENT_COMPAT; escaped = php_escape_html_entities_ex((unsigned char *)(Z_STRVAL_P(string)), Z_STRLEN_P(string), &escaped_len, 0, qs, cs, 1 TSRMLS_CC); ZVAL_STRINGL(return_value, escaped, escaped_len, 0); if (unlikely(use_copy)) { zval_dtor(&copy); } } void zephir_htmlentities(zval *return_value, zval *string, zval *quoting, zval *charset TSRMLS_DC) { zval copy; char *escaped, *cs; int qs, use_copy = 0; #if PHP_VERSION_ID < 50400 int escaped_len; #else size_t escaped_len; #endif if (unlikely(Z_TYPE_P(string) != IS_STRING)) { zend_make_printable_zval(string, &copy, &use_copy); if (use_copy) { string = &copy; } } cs = (charset && Z_TYPE_P(charset) == IS_STRING) ? Z_STRVAL_P(charset) : NULL; qs = (quoting && Z_TYPE_P(quoting) == IS_LONG) ? Z_LVAL_P(quoting) : ENT_COMPAT; escaped = php_escape_html_entities_ex((unsigned char *)(Z_STRVAL_P(string)), Z_STRLEN_P(string), &escaped_len, 1, qs, cs, 1 TSRMLS_CC); ZVAL_STRINGL(return_value, escaped, escaped_len, 0); if (unlikely(use_copy)) { zval_dtor(&copy); } } void zephir_strval(zval *return_value, zval *v) { zval copy; int use_copy = 0; zend_make_printable_zval(v, &copy, &use_copy); if (use_copy) { zval *tmp = &copy; ZVAL_ZVAL(return_value, tmp, 0, 0); } else { ZVAL_ZVAL(return_value, v, 1, 0); } } void zephir_date(zval *return_value, zval *format, zval *timestamp TSRMLS_DC) { long int ts; zval copy; int use_copy = 0; char *formatted; if (unlikely(Z_TYPE_P(format) != IS_STRING)) { zend_make_printable_zval(format, &copy, &use_copy); if (use_copy) { format = &copy; } } ts = (timestamp) ? zephir_get_intval(timestamp) : time(NULL); formatted = php_format_date(Z_STRVAL_P(format), Z_STRLEN_P(format), ts, 1 TSRMLS_CC); ZVAL_STRING(return_value, formatted, 0); if (unlikely(use_copy)) { zval_dtor(&copy); } } void zephir_addslashes(zval *return_value, zval *str TSRMLS_DC) { zval copy; int use_copy = 0; if (unlikely(Z_TYPE_P(str) != IS_STRING)) { zend_make_printable_zval(str, &copy, &use_copy); if (use_copy) { str = &copy; } } ZVAL_STRING(return_value, php_addslashes(Z_STRVAL_P(str), Z_STRLEN_P(str), &Z_STRLEN_P(return_value), 0 TSRMLS_CC), 0); if (unlikely(use_copy)) { zval_dtor(&copy); } } void zephir_stripslashes(zval *return_value, zval *str TSRMLS_DC) { zval copy; int use_copy = 0; if (unlikely(Z_TYPE_P(str) != IS_STRING)) { zend_make_printable_zval(str, &copy, &use_copy); if (use_copy) { str = &copy; } } ZVAL_STRINGL(return_value, Z_STRVAL_P(str), Z_STRLEN_P(str), 1); php_stripslashes(Z_STRVAL_P(return_value), &Z_STRLEN_P(return_value) TSRMLS_CC); if (unlikely(use_copy)) { zval_dtor(&copy); } } void zephir_stripcslashes(zval *return_value, zval *str TSRMLS_DC) { zval copy; int use_copy = 0; if (unlikely(Z_TYPE_P(str) != IS_STRING)) { zend_make_printable_zval(str, &copy, &use_copy); if (use_copy) { str = &copy; } } ZVAL_STRINGL(return_value, Z_STRVAL_P(str), Z_STRLEN_P(str), 1); php_stripcslashes(Z_STRVAL_P(return_value), &Z_STRLEN_P(return_value)); if (unlikely(use_copy)) { zval_dtor(&copy); } } #if PHP_VERSION_ID < 50400 const char* zend_new_interned_string(const char *arKey, int nKeyLength, int free_src TSRMLS_DC) { return arKey; } #endif