diff options
author | Pavlo Yatsukhnenko <yatsukhnenko@gmail.com> | 2019-02-16 20:48:02 +0300 |
---|---|---|
committer | michael-grunder <michael.grunder@gmail.com> | 2019-03-19 23:05:40 +0300 |
commit | b994ee42df8a4acf4b5cc16faeb09a60619e3245 (patch) | |
tree | 8c9eb4dce1deb56476499bdaf3a2075487de3802 /common.h | |
parent | b2511d632cc2fb4a4c4cda07ae9403e37bf9055b (diff) |
Persistent connections pool
Diffstat (limited to 'common.h')
-rw-r--r-- | common.h | 463 |
1 files changed, 463 insertions, 0 deletions
@@ -9,6 +9,469 @@ #include "zend_llist.h" #include <ext/standard/php_var.h> #include <ext/standard/php_math.h> +#if (PHP_MAJOR_VERSION < 7) +#include <ext/standard/php_smart_str.h> +typedef smart_str smart_string; +#define smart_string_0(x) smart_str_0(x) +#define smart_string_appendc(dest, c) smart_str_appendc(dest, c) +#define smart_string_append_long(dest, val) smart_str_append_long(dest, val) +#define smart_string_appendl(dest, src, len) smart_str_appendl(dest, src, len) + +typedef struct { + short gc; + size_t len; + char *val; +} zend_string; + +#define REDIS_MAKE_STD_ZVAL(zv) MAKE_STD_ZVAL(zv) +#define REDIS_FREE_ZVAL(zv) (efree(zv)) + +#define ZSTR_VAL(s) (s)->val +#define ZSTR_LEN(s) (s)->len + +static zend_always_inline zend_string * +zend_string_alloc(size_t len, int persistent) +{ + zend_string *zstr = emalloc(sizeof(*zstr) + len + 1); + + ZSTR_VAL(zstr) = (char *)zstr + sizeof(*zstr); + ZSTR_LEN(zstr) = len; + zstr->gc = 0x01; + return zstr; +} + +static zend_always_inline zend_string * +zend_string_init(const char *str, size_t len, int persistent) +{ + zend_string *zstr = zend_string_alloc(len, persistent); + + memcpy(ZSTR_VAL(zstr), str, len); + ZSTR_VAL(zstr)[len] = '\0'; + return zstr; +} + +static zend_always_inline zend_string * +zend_string_realloc(zend_string *s, size_t len, int persistent) +{ + zend_string *zstr; + + if (!s->gc) { + zstr = zend_string_init(ZSTR_VAL(s), len, 0); + } else if (s->gc & 0x10) { + ZSTR_VAL(s) = erealloc(ZSTR_VAL(s), len + 1); + ZSTR_LEN(s) = len; + zstr = s; + } else { + zstr = erealloc(s, sizeof(*zstr) + len + 1); + ZSTR_VAL(zstr) = (char *)zstr + sizeof(*zstr); + ZSTR_LEN(zstr) = len; + } + return zstr; +} + +#define strpprintf zend_strpprintf + +static zend_string * +zend_strpprintf(size_t max_len, const char *format, ...) +{ + va_list ap; + zend_string *zstr; + + va_start(ap, format); + zstr = ecalloc(1, sizeof(*zstr)); + ZSTR_LEN(zstr) = vspprintf(&ZSTR_VAL(zstr), max_len, format, ap); + zstr->gc = 0x11; + va_end(ap); + return zstr; +} + +#define zend_string_copy(s) zend_string_init(ZSTR_VAL(s), ZSTR_LEN(s), 0) + +#define zend_string_equal_val(s1, s2) !memcmp(ZSTR_VAL(s1), ZSTR_VAL(s2), ZSTR_LEN(s1)) +#define zend_string_equal_content(s1, s2) (ZSTR_LEN(s1) == ZSTR_LEN(s2) && zend_string_equal_val(s1, s2)) +#define zend_string_equals(s1, s2) (s1 == s2 || zend_string_equal_content(s1, s2)) + +#define zend_string_release(s) do { \ + if ((s) && (s)->gc) { \ + if ((s)->gc & 0x10 && ZSTR_VAL(s)) efree(ZSTR_VAL(s)); \ + if ((s)->gc & 0x01) efree((s)); \ + } \ +} while (0) + +#define ZEND_HASH_FOREACH_KEY_VAL(ht, _h, _key, _val) do { \ + HashPosition _hpos; \ + for (zend_hash_internal_pointer_reset_ex(ht, &_hpos); \ + zend_hash_has_more_elements_ex(ht, &_hpos) == SUCCESS; \ + zend_hash_move_forward_ex(ht, &_hpos) \ + ) { \ + zend_string _zstr = {0}; \ + char *_str_index; uint _str_length; ulong _num_index; \ + _h = 0; _key = NULL; _val = zend_hash_get_current_data_ex(ht, &_hpos); \ + switch (zend_hash_get_current_key_ex(ht, &_str_index, &_str_length, &_num_index, 0, &_hpos)) { \ + case HASH_KEY_IS_STRING: \ + _zstr.len = _str_length - 1; \ + _zstr.val = _str_index; \ + _key = &_zstr; \ + break; \ + case HASH_KEY_IS_LONG: \ + _h = _num_index; \ + break; \ + default: \ + /* noop */ break; \ + } + +#define ZEND_HASH_FOREACH_VAL(ht, _val) do { \ + HashPosition _hpos; \ + for (zend_hash_internal_pointer_reset_ex(ht, &_hpos); \ + zend_hash_has_more_elements_ex(ht, &_hpos) == SUCCESS; \ + zend_hash_move_forward_ex(ht, &_hpos) \ + ) { \ + _val = zend_hash_get_current_data_ex(ht, &_hpos); \ + +#define ZEND_HASH_FOREACH_PTR(ht, _ptr) do { \ + HashPosition _hpos; \ + for (zend_hash_internal_pointer_reset_ex(ht, &_hpos); \ + zend_hash_has_more_elements_ex(ht, &_hpos) == SUCCESS; \ + zend_hash_move_forward_ex(ht, &_hpos) \ + ) { \ + _ptr = zend_hash_get_current_data_ptr_ex(ht, &_hpos); \ + +#define ZEND_HASH_FOREACH_END() \ + } \ +} while(0) + +#undef zend_hash_get_current_key +#define zend_hash_get_current_key(ht, str_index, num_index) \ + zend_hash_get_current_key_ex(ht, str_index, NULL, num_index, 0, NULL) + +#define zend_hash_str_exists(ht, str, len) zend_hash_exists(ht, str, len + 1) + +static zend_always_inline zval * +zend_hash_str_find(const HashTable *ht, const char *key, size_t len) +{ + zval **zv; + + if (zend_hash_find(ht, key, len + 1, (void **)&zv) == SUCCESS) { + return *zv; + } + return NULL; +} + +#define zend_hash_find_ptr(ht, s) zend_hash_str_find_ptr(ht, ZSTR_VAL(s), ZSTR_LEN(s)) + +static zend_always_inline void * +zend_hash_str_find_ptr(const HashTable *ht, const char *str, size_t len) +{ + void **ptr; + + if (zend_hash_find(ht, str, len + 1, (void **)&ptr) == SUCCESS) { + return *ptr; + } + return NULL; +} + +#define zend_hash_str_update_ptr(ht, str, len, pData) zend_hash_str_update_mem(ht, str, len, pData, sizeof(void *)) + +static zend_always_inline void * +zend_hash_str_update_mem(HashTable *ht, const char *str, size_t len, void *pData, size_t size) +{ + if (zend_hash_update(ht, str, len + 1, (void *)&pData, size, NULL) == SUCCESS) { + return pData; + } + return NULL; +} + +static zend_always_inline void * +zend_hash_index_update_ptr(HashTable *ht, zend_ulong h, void *pData) +{ + if (zend_hash_index_update(ht, h, (void **)&pData, sizeof(void *), NULL) == SUCCESS) { + return pData; + } + return NULL; +} + +#undef zend_hash_get_current_data +static zend_always_inline zval * +zend_hash_get_current_data(HashTable *ht) +{ + zval **zv; + + if (zend_hash_get_current_data_ex(ht, (void **)&zv, NULL) == SUCCESS) { + return *zv; + } + return NULL; +} + +static zend_always_inline void * +zend_hash_get_current_data_ptr_ex(HashTable *ht, HashPosition *pos) +{ + void **ptr; + + if (zend_hash_get_current_data_ex(ht, (void **)&ptr, pos) == SUCCESS) { + return *ptr; + } + return NULL; +} +#define zend_hash_get_current_data_ptr(ht) zend_hash_get_current_data_ptr_ex(ht, NULL) + +static int (*_zend_hash_index_find)(const HashTable *, ulong, void **) = &zend_hash_index_find; +#define zend_hash_index_find(ht, h) inline_zend_hash_index_find(ht, h) + +static zend_always_inline zval * +inline_zend_hash_index_find(const HashTable *ht, zend_ulong h) +{ + zval **zv; + if (_zend_hash_index_find(ht, h, (void **)&zv) == SUCCESS) { + return *zv; + } + return NULL; +} + +static zend_always_inline void * +zend_hash_index_find_ptr(const HashTable *ht, zend_ulong h) +{ + void **ptr; + + if (_zend_hash_index_find(ht, h, (void **)&ptr) == SUCCESS) { + return *ptr; + } + return NULL; +} + +static int (*_zend_hash_get_current_data_ex)(HashTable *, void **, HashPosition *) = &zend_hash_get_current_data_ex; +#define zend_hash_get_current_data_ex(ht, pos) inline_zend_hash_get_current_data_ex(ht, pos) +static zend_always_inline zval * +inline_zend_hash_get_current_data_ex(HashTable *ht, HashPosition *pos) +{ + zval **zv; + if (_zend_hash_get_current_data_ex(ht, (void **)&zv, pos) == SUCCESS) { + return *zv; + } + return NULL; +} + +#undef zend_hash_next_index_insert +#define zend_hash_next_index_insert(ht, pData) \ + _zend_hash_next_index_insert(ht, pData ZEND_FILE_LINE_CC) +static zend_always_inline zval * +_zend_hash_next_index_insert(HashTable *ht, zval *pData ZEND_FILE_LINE_DC) +{ + if (_zend_hash_index_update_or_next_insert(ht, 0, &pData, sizeof(pData), + NULL, HASH_NEXT_INSERT ZEND_FILE_LINE_CC) == SUCCESS + ) { + return pData; + } + return NULL; +} + +#undef zend_get_parameters_array +#define zend_get_parameters_array(ht, param_count, argument_array) \ + inline_zend_get_parameters_array(ht, param_count, argument_array TSRMLS_CC) + +static zend_always_inline int +inline_zend_get_parameters_array(int ht, int param_count, zval *argument_array TSRMLS_DC) +{ + int i, ret = FAILURE; + zval **zv = ecalloc(param_count, sizeof(zval *)); + + if (_zend_get_parameters_array(ht, param_count, zv TSRMLS_CC) == SUCCESS) { + for (i = 0; i < param_count; i++) { + argument_array[i] = *zv[i]; + } + ret = SUCCESS; + } + efree(zv); + return ret; +} + +typedef zend_rsrc_list_entry zend_resource; + +extern int (*_add_next_index_string)(zval *, const char *, int); +#define add_next_index_string(arg, str) _add_next_index_string(arg, str, 1); +extern int (*_add_next_index_stringl)(zval *, const char *, uint, int); +#define add_next_index_stringl(arg, str, length) _add_next_index_stringl(arg, str, length, 1); + +#undef ZVAL_STRING +#define ZVAL_STRING(z, s) do { \ + const char *_s = (s); \ + ZVAL_STRINGL(z, _s, strlen(_s)); \ +} while (0) +#undef RETVAL_STRING +#define RETVAL_STRING(s) ZVAL_STRING(return_value, s) +#undef RETURN_STRING +#define RETURN_STRING(s) { RETVAL_STRING(s); return; } + +#undef ZVAL_STRINGL +#define ZVAL_STRINGL(z, s, l) do { \ + const char *__s = (s); int __l = l; \ + zval *__z = (z); \ + Z_STRLEN_P(__z) = __l; \ + Z_STRVAL_P(__z) = estrndup(__s, __l); \ + Z_TYPE_P(__z) = IS_STRING; \ +} while (0) +#undef RETVAL_STRINGL +#define RETVAL_STRINGL(s, l) ZVAL_STRINGL(return_value, s, l) +#undef RETURN_STRINGL +#define RETURN_STRINGL(s, l) { RETVAL_STRINGL(s, l); return; } + +static int (*_call_user_function)(HashTable *, zval **, zval *, zval *, zend_uint, zval *[] TSRMLS_DC) = &call_user_function; +#define call_user_function(function_table, object, function_name, retval_ptr, param_count, params) \ + inline_call_user_function(function_table, object, function_name, retval_ptr, param_count, params TSRMLS_CC) + +static zend_always_inline int +inline_call_user_function(HashTable *function_table, zval *object, zval *function_name, zval *retval_ptr, zend_uint param_count, zval params[] TSRMLS_DC) +{ + int i, ret; + zval **_params = NULL; + if (!params) param_count = 0; + if (param_count > 0) { + _params = ecalloc(param_count, sizeof(zval *)); + for (i = 0; i < param_count; ++i) { + zval *zv = ¶ms[i]; + MAKE_STD_ZVAL(_params[i]); + ZVAL_ZVAL(_params[i], zv, 1, 0); + } + } + ret = _call_user_function(function_table, &object, function_name, retval_ptr, param_count, _params TSRMLS_CC); + if (_params) { + for (i = 0; i < param_count; ++i) { + zval_ptr_dtor(&_params[i]); + } + efree(_params); + } + return ret; +} + +#undef add_assoc_bool +#define add_assoc_bool(__arg, __key, __b) add_assoc_bool_ex(__arg, __key, strlen(__key), __b) +extern int (*_add_assoc_bool_ex)(zval *, const char *, uint, int); +#define add_assoc_bool_ex(_arg, _key, _key_len, _b) _add_assoc_bool_ex(_arg, _key, _key_len + 1, _b) + +#undef add_assoc_long +#define add_assoc_long(__arg, __key, __n) add_assoc_long_ex(__arg, __key, strlen(__key), __n) +extern int (*_add_assoc_long_ex)(zval *, const char *, uint, long); +#define add_assoc_long_ex(_arg, _key, _key_len, _n) _add_assoc_long_ex(_arg, _key, _key_len + 1, _n) + +#undef add_assoc_double +#define add_assoc_double(__arg, __key, __d) add_assoc_double_ex(__arg, __key, strlen(__key), __d) +extern int (*_add_assoc_double_ex)(zval *, const char *, uint, double); +#define add_assoc_double_ex(_arg, _key, _key_len, _d) _add_assoc_double_ex(_arg, _key, _key_len + 1, _d) + +#undef add_assoc_string +#define add_assoc_string(__arg, __key, __str) add_assoc_string_ex(__arg, __key, strlen(__key), __str) +extern int (*_add_assoc_string_ex)(zval *, const char *, uint, char *, int); +#define add_assoc_string_ex(_arg, _key, _key_len, _str) _add_assoc_string_ex(_arg, _key, _key_len + 1, _str, 1) + +extern int (*_add_assoc_stringl_ex)(zval *, const char *, uint, char *, uint, int); +#define add_assoc_stringl_ex(_arg, _key, _key_len, _str, _length) _add_assoc_stringl_ex(_arg, _key, _key_len + 1, _str, _length, 1) + +#undef add_assoc_zval +#define add_assoc_zval(__arg, __key, __value) add_assoc_zval_ex(__arg, __key, strlen(__key), __value) +extern int (*_add_assoc_zval_ex)(zval *, const char *, uint, zval *); +#define add_assoc_zval_ex(_arg, _key, _key_len, _value) _add_assoc_zval_ex(_arg, _key, _key_len + 1, _value); + +typedef long zend_long; +static zend_always_inline zend_long +zval_get_long(zval *op) +{ + switch (Z_TYPE_P(op)) { + case IS_BOOL: + case IS_LONG: + return Z_LVAL_P(op); + case IS_DOUBLE: + return zend_dval_to_lval(Z_DVAL_P(op)); + case IS_STRING: + { + double dval; + zend_long lval; + zend_uchar type = is_numeric_string(Z_STRVAL_P(op), Z_STRLEN_P(op), &lval, &dval, 0); + if (type == IS_LONG) { + return lval; + } else if (type == IS_DOUBLE) { + return zend_dval_to_lval(dval); + } + } + break; + EMPTY_SWITCH_DEFAULT_CASE() + } + return 0; +} + +static zend_always_inline double +zval_get_double(zval *op) +{ + switch (Z_TYPE_P(op)) { + case IS_BOOL: + case IS_LONG: + return (double)Z_LVAL_P(op); + case IS_DOUBLE: + return Z_DVAL_P(op); + case IS_STRING: + return zend_strtod(Z_STRVAL_P(op), NULL); + EMPTY_SWITCH_DEFAULT_CASE() + } + return 0.0; +} + +static zend_always_inline zend_string * +zval_get_string(zval *op) +{ + zend_string *zstr = ecalloc(1, sizeof(zend_string)); + + zstr->gc = 0; + ZSTR_VAL(zstr) = ""; + ZSTR_LEN(zstr) = 0; + switch (Z_TYPE_P(op)) { + case IS_STRING: + ZSTR_VAL(zstr) = Z_STRVAL_P(op); + ZSTR_LEN(zstr) = Z_STRLEN_P(op); + break; + case IS_BOOL: + if (Z_LVAL_P(op)) { + ZSTR_VAL(zstr) = "1"; + ZSTR_LEN(zstr) = 1; + } + break; + case IS_LONG: { + zstr->gc = 0x10; + ZSTR_LEN(zstr) = spprintf(&ZSTR_VAL(zstr), 0, "%ld", Z_LVAL_P(op)); + break; + } + case IS_DOUBLE: { + zstr->gc = 0x10; + ZSTR_LEN(zstr) = spprintf(&ZSTR_VAL(zstr), 0, "%.16g", Z_DVAL_P(op)); + break; + } + EMPTY_SWITCH_DEFAULT_CASE() + } + zstr->gc |= 0x01; + return zstr; +} + +extern void (*_php_var_serialize)(smart_str *, zval **, php_serialize_data_t * TSRMLS_DC); +#define php_var_serialize(buf, struc, data) _php_var_serialize(buf, &struc, data TSRMLS_CC) +extern int (*_php_var_unserialize)(zval **, const unsigned char **, const unsigned char *, php_unserialize_data_t * TSRMLS_DC); +#define php_var_unserialize(rval, p, max, var_hash) _php_var_unserialize(&rval, p, max, var_hash TSRMLS_CC) +typedef int strlen_t; + +#define PHPREDIS_ZVAL_IS_STRICT_FALSE(z) (Z_TYPE_P(z) == IS_BOOL && !Z_BVAL_P(z)) + +/* If ZEND_MOD_END isn't defined, use legacy version */ +#ifndef ZEND_MOD_END +#define ZEND_MOD_END { NULL, NULL, NULL } +#endif + +/* PHP_FE_END exists since 5.3.7 */ +#ifndef PHP_FE_END +#define PHP_FE_END { NULL, NULL, NULL } +#endif + +/* References don't need any actions */ +#define ZVAL_DEREF(v) PHPREDIS_NOTUSED(v) + +#define PHPREDIS_GET_OBJECT(class_entry, z) (class_entry *)zend_objects_get_address(z TSRMLS_CC) + +#else #include <zend_smart_str.h> #include <ext/standard/php_smart_string.h> |