Merge branch 'v2.6.x'
[m6w6/ext-http] / src / php_http_negotiate.c
index 02b0a646a8c099d7c016c2b9a5ecf03bbacaae91..cd09d3740f6dc8e293b72b3dbb742b096cca58ca 100644 (file)
 # 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(&params, 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(&params, &opts TSRMLS_CC);
+               php_http_params_parse(&params, &opts);
                efree(opts.input.str);
 
-               INIT_PZVAL(&arr);
                array_init(&arr);
 
-               FOREACH_HASH_KEYVAL(pos, &params, key, val) {
+               ZEND_HASH_FOREACH_KEY_VAL(&params, 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(&params);
                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;
 }