X-Git-Url: https://git.m6w6.name/?p=m6w6%2Fext-http;a=blobdiff_plain;f=src%2Fphp_http_negotiate.c;fp=src%2Fphp_http_negotiate.c;h=cd09d3740f6dc8e293b72b3dbb742b096cca58ca;hp=02b0a646a8c099d7c016c2b9a5ecf03bbacaae91;hb=43a9a6f8cb56e25c3770d652ce77045f89f68ca6;hpb=a1d6c90d8630ec1385f10052656d129498720adf diff --git a/src/php_http_negotiate.c b/src/php_http_negotiate.c index 02b0a64..cd09d37 100644 --- a/src/php_http_negotiate.c +++ b/src/php_http_negotiate.c @@ -16,17 +16,12 @@ # define PHP_HTTP_DEBUG_NEG 0 #endif -static int php_http_negotiate_sort(const void *a, const void *b TSRMLS_DC) +static int php_http_negotiate_sort(const void *first, const void *second) { - zval result, *first, *second; + Bucket *b1 = (Bucket *) first, *b2 = (Bucket *) second; + int result = numeric_compare_function(&b1->val, &b2->val); - first = *((zval **) (*((Bucket **) a))->pData); - second= *((zval **) (*((Bucket **) b))->pData); - - if (numeric_compare_function(&result, first, second TSRMLS_CC) != SUCCESS) { - return 0; - } - return (Z_LVAL(result) > 0 ? -1 : (Z_LVAL(result) < 0 ? 1 : 0)); + return (result > 0 ? -1 : (result < 0 ? 1 : 0)); } #define M_PRI 5 @@ -36,7 +31,7 @@ static int php_http_negotiate_sort(const void *a, const void *b TSRMLS_DC) #define M_ALL ~0 static inline unsigned php_http_negotiate_match(const char *param_str, size_t param_len, const char *supported_str, size_t supported_len, const char *sep_str, size_t sep_len) { - int match = M_NOT; + unsigned match = M_NOT; if (param_len == supported_len && !strncasecmp(param_str, supported_str, param_len)) { /* that was easy */ @@ -75,54 +70,56 @@ static inline unsigned php_http_negotiate_match(const char *param_str, size_t pa #endif return match; } - -static int php_http_negotiate_reduce(void *p TSRMLS_DC, int num_args, va_list args, zend_hash_key *hash_key) +static int php_http_negotiate_reduce(zval *p, int num_args, va_list args, zend_hash_key *hash_key) { unsigned best_match = 0; double q = 0; - HashPosition pos; - php_http_array_hashkey_t key = php_http_array_hashkey_init(0); - zval **val, *supported = php_http_ztyp(IS_STRING, *(zval **)p); + php_http_arrkey_t key; + zval *value; + zend_string *supported = zval_get_string(p); HashTable *params = va_arg(args, HashTable *); HashTable *result = va_arg(args, HashTable *); const char *sep_str = va_arg(args, const char *); size_t sep_len = va_arg(args, size_t); - FOREACH_HASH_KEYVAL(pos, params, key, val) { - if (key.type == HASH_KEY_IS_STRING) { - unsigned match = php_http_negotiate_match(key.str, key.len-1, Z_STRVAL_P(supported), Z_STRLEN_P(supported), sep_str, sep_len); + ZEND_HASH_FOREACH_KEY_VAL(params, key.h, key.key, value) + { + unsigned match; + #if PHP_HTTP_DEBUG_NEG fprintf(stderr, "match(%u) > best_match(%u) = %u (q=%f)\n", match, best_match, match>best_match, Z_DVAL_PP(val)); #endif - if (match > best_match) { - best_match = match; - q = Z_DVAL_PP(val) - 0.1 / match; - } + php_http_arrkey_stringify(&key, NULL); + match = php_http_negotiate_match(key.key->val, key.key->len, supported->val, supported->len, sep_str, sep_len); + + if (match > best_match) { + best_match = match; + q = Z_DVAL_P(value) - 0.1 / match; } + php_http_arrkey_dtor(&key); } + ZEND_HASH_FOREACH_END(); if (q > 0) { - zval *tmp; + zval tmp; - MAKE_STD_ZVAL(tmp); - ZVAL_DOUBLE(tmp, q); - zend_hash_update(result, Z_STRVAL_P(supported), Z_STRLEN_P(supported) + 1, (void *) &tmp, sizeof(zval *), NULL); + ZVAL_DOUBLE(&tmp, q); + zend_hash_update(result, supported, &tmp); } - zval_ptr_dtor(&supported); + zend_string_release(supported); return ZEND_HASH_APPLY_KEEP; } -HashTable *php_http_negotiate(const char *value_str, size_t value_len, HashTable *supported, const char *primary_sep_str, size_t primary_sep_len TSRMLS_DC) +HashTable *php_http_negotiate(const char *value_str, size_t value_len, HashTable *supported, const char *primary_sep_str, size_t primary_sep_len) { HashTable *result = NULL; if (value_str && value_len) { unsigned i = 0; - zval arr, **val, **arg, **zq; - HashPosition pos; + zval arr, *val, *arg, *zq; HashTable params; - php_http_array_hashkey_t key = php_http_array_hashkey_init(1); + php_http_arrkey_t key; php_http_params_opts_t opts; zend_hash_init(¶ms, 10, NULL, ZVAL_PTR_DTOR, 0); @@ -130,47 +127,48 @@ HashTable *php_http_negotiate(const char *value_str, size_t value_len, HashTable opts.input.str = estrndup(value_str, value_len); opts.input.len = value_len; opts.flags &= ~PHP_HTTP_PARAMS_RFC5987; - php_http_params_parse(¶ms, &opts TSRMLS_CC); + php_http_params_parse(¶ms, &opts); efree(opts.input.str); - INIT_PZVAL(&arr); array_init(&arr); - FOREACH_HASH_KEYVAL(pos, ¶ms, key, val) { + ZEND_HASH_FOREACH_KEY_VAL(¶ms, key.h, key.key, val) + { double q; - if (SUCCESS == zend_hash_find(Z_ARRVAL_PP(val), ZEND_STRS("arguments"), (void *) &arg) - && IS_ARRAY == Z_TYPE_PP(arg) - && SUCCESS == zend_hash_find(Z_ARRVAL_PP(arg), ZEND_STRS("q"), (void *) &zq)) { - zval *tmp = php_http_ztyp(IS_DOUBLE, *zq); - - q = Z_DVAL_P(tmp); - zval_ptr_dtor(&tmp); + if ((arg = zend_hash_str_find(Z_ARRVAL_P(val), ZEND_STRL("arguments"))) + && (IS_ARRAY == Z_TYPE_P(arg)) + && (zq = zend_hash_str_find(Z_ARRVAL_P(arg), ZEND_STRL("q")))) { + q = zval_get_double(zq); } else { q = 1.0 - (((double) ++i) / 100.0); } - if (key.type == HASH_KEY_IS_STRING) { - add_assoc_double_ex(&arr, key.str, key.len, q); +#if 0 + fprintf(stderr, "Q: %s=%1.3f\n", key.key->val, q); +#endif + + if (key.key) { + add_assoc_double_ex(&arr, key.key->val, key.key->len, q); } else { - add_index_double(&arr, key.num, q); + add_index_double(&arr, key.h, q); } - PTR_FREE(key.str); } + ZEND_HASH_FOREACH_END(); #if PHP_HTTP_DEBUG_NEG - zend_print_zval_r(&arr, 1 TSRMLS_CC); + zend_print_zval_r(&arr, 1); #endif ALLOC_HASHTABLE(result); zend_hash_init(result, zend_hash_num_elements(supported), NULL, ZVAL_PTR_DTOR, 0); - zend_hash_apply_with_arguments(supported TSRMLS_CC, php_http_negotiate_reduce, 4, Z_ARRVAL(arr), result, primary_sep_str, primary_sep_len); + zend_hash_apply_with_arguments(supported, php_http_negotiate_reduce, 4, Z_ARRVAL(arr), result, primary_sep_str, primary_sep_len); zend_hash_destroy(¶ms); zval_dtor(&arr); - zend_hash_sort(result, zend_qsort, php_http_negotiate_sort, 0 TSRMLS_CC); + zend_hash_sort(result, php_http_negotiate_sort, 0); } - + return result; }