performance improvements
authorMichael Wallner <mike@php.net>
Thu, 22 Feb 2018 16:35:13 +0000 (17:35 +0100)
committerMichael Wallner <mike@php.net>
Thu, 22 Feb 2018 16:35:13 +0000 (17:35 +0100)
14 files changed:
src/php_http_buffer.c
src/php_http_buffer.h
src/php_http_env_response.c
src/php_http_exception.h
src/php_http_header_parser.c
src/php_http_header_parser.h
src/php_http_info.c
src/php_http_message.c
src/php_http_message_parser.c
src/php_http_message_parser.h
src/php_http_misc.c
src/php_http_misc.h
src/php_http_url.c
src/php_http_utf8.h

index d7cfd56..9ff4065 100644 (file)
@@ -37,7 +37,7 @@ PHP_HTTP_BUFFER_API php_http_buffer_t *php_http_buffer_from_string_ex(
 {
        int free_buf = !!buf;
 
-       if ((buf = php_http_buffer_init(buf))) {
+       if (EXPECTED(buf = php_http_buffer_init(buf))) {
                if (PHP_HTTP_BUFFER_NOMEM == php_http_buffer_append(buf, str, len)) {
                        if (free_buf) {
                                pefree(buf, buf->pmem);
@@ -59,7 +59,7 @@ PHP_HTTP_BUFFER_API size_t php_http_buffer_resize_ex(
        if (buf->free < len) {
                size_t size = override_size ? override_size : buf->size;
                
-               while ((size + buf->free) < len) {
+               while (UNEXPECTED((size + buf->free) < len)) {
                        size <<= 1;
                }
                
@@ -300,7 +300,7 @@ PHP_HTTP_BUFFER_API size_t php_http_buffer_chunked_input(php_http_buffer_t **s,
        php_http_buffer_t *str;
        size_t passed;
 
-       if (!*s) {
+       if (UNEXPECTED(!*s)) {
                *s = php_http_buffer_init_ex(NULL, chunk_size,
                                chunk_size ? PHP_HTTP_BUFFER_INIT_PREALLOC : 0);
        }
index 818c443..6592ec4 100644 (file)
@@ -24,7 +24,7 @@
 #ifndef PTR_FREE
 #      define PTR_FREE(PTR) \
        { \
-               if (PTR) { \
+               if (EXPECTED(PTR)) { \
                        efree(PTR); \
                } \
        }
index 7406857..ab959f3 100644 (file)
@@ -15,7 +15,7 @@
 static void set_option(zval *options, const char *name_str, size_t name_len, int type, void *value_ptr, size_t value_len)
 {
        if (Z_TYPE_P(options) == IS_OBJECT) {
-               if (value_ptr) {
+               if (EXPECTED(value_ptr)) {
                        switch (type) {
                                case IS_DOUBLE:
                                        zend_update_property_double(Z_OBJCE_P(options), options, name_str, name_len, *(double *)value_ptr);
@@ -36,7 +36,7 @@ static void set_option(zval *options, const char *name_str, size_t name_len, int
                }
        } else {
                convert_to_array(options);
-               if (value_ptr) {
+               if (EXPECTED(value_ptr)) {
                        switch (type) {
                                case IS_DOUBLE:
                                        add_assoc_double_ex(options, name_str, name_len, *(double *)value_ptr);
@@ -64,9 +64,9 @@ static zval *get_option(zval *options, const char *name_str, size_t name_len, zv
 {
        zval *val = NULL;
 
-       if (Z_TYPE_P(options) == IS_OBJECT) {
+       if (EXPECTED(Z_TYPE_P(options) == IS_OBJECT)) {
                val = zend_read_property(Z_OBJCE_P(options), options, name_str, name_len, 0, tmp);
-       } else if (Z_TYPE_P(options) == IS_ARRAY) {
+       } else if (EXPECTED(Z_TYPE_P(options) == IS_ARRAY)) {
                val = zend_symtable_str_find(Z_ARRVAL_P(options), name_str, name_len);
        } else {
                abort();
@@ -81,7 +81,7 @@ static php_http_message_body_t *get_body(zval *options)
        zval zbody_tmp, *zbody;
        php_http_message_body_t *body = NULL;
 
-       if ((zbody = get_option(options, ZEND_STRL("body"), &zbody_tmp))) {
+       if (EXPECTED(zbody = get_option(options, ZEND_STRL("body"), &zbody_tmp))) {
                if ((Z_TYPE_P(zbody) == IS_OBJECT) && instanceof_function(Z_OBJCE_P(zbody), php_http_get_message_body_class_entry())) {
                        php_http_message_body_object_t *body_obj = PHP_HTTP_OBJ(NULL, zbody);
 
@@ -97,8 +97,8 @@ static php_http_message_t *get_request(zval *options)
        zval zrequest_tmp, *zrequest;
        php_http_message_t *request = NULL;
 
-       if ((zrequest = get_option(options, ZEND_STRL("request"), &zrequest_tmp))) {
-               if (Z_TYPE_P(zrequest) == IS_OBJECT && instanceof_function(Z_OBJCE_P(zrequest), php_http_message_get_class_entry())) {
+       if (EXPECTED(zrequest = get_option(options, ZEND_STRL("request"), &zrequest_tmp))) {
+               if (UNEXPECTED(Z_TYPE_P(zrequest) == IS_OBJECT && instanceof_function(Z_OBJCE_P(zrequest), php_http_message_get_class_entry()))) {
                        php_http_message_object_t *request_obj = PHP_HTTP_OBJ(NULL, zrequest);
 
                        request = request_obj->message;
@@ -144,11 +144,11 @@ php_http_cache_status_t php_http_env_is_response_cached_by_etag(zval *options, c
        zval zetag_tmp, *zetag;
 
 
-       if (!(body = get_body(options))) {
+       if (UNEXPECTED(!(body = get_body(options)))) {
                return ret;
        }
 
-       if ((zetag = get_option(options, ZEND_STRL("etag"), &zetag_tmp)) && Z_TYPE_P(zetag) != IS_NULL) {
+       if (EXPECTED(zetag = get_option(options, ZEND_STRL("etag"), &zetag_tmp)) && Z_TYPE_P(zetag) != IS_NULL) {
                zend_string *zs = zval_get_string(zetag);
                etag = estrndup(zs->val, zs->len);
                zend_string_release(zs);
@@ -177,16 +177,16 @@ php_http_cache_status_t php_http_env_is_response_cached_by_last_modified(zval *o
        php_http_message_body_t *body;
        zval zlm_tmp, *zlm;
 
-       if (!(body = get_body(options))) {
+       if (UNEXPECTED(!(body = get_body(options)))) {
                return ret;
        }
 
-       if ((zlm = get_option(options, ZEND_STRL("lastModified"), &zlm_tmp))) {
+       if (EXPECTED(zlm = get_option(options, ZEND_STRL("lastModified"), &zlm_tmp))) {
                lm = zval_get_long(zlm);
                zval_ptr_dtor(zlm);
        }
 
-       if (lm <= 0) {
+       if (EXPECTED(lm <= 0)) {
                lm = php_http_message_body_mtime(body);
                set_option(options, ZEND_STRL("lastModified"), IS_LONG, &lm, 0);
        }
@@ -228,13 +228,13 @@ static size_t output(void *context, char *buf, size_t len)
 {
        php_http_env_response_t *r = context;
 
-       if (SUCCESS != r->ops->write(r, buf, len)) {
+       if (UNEXPECTED(SUCCESS != r->ops->write(r, buf, len))) {
                return (size_t) -1;
        }
 
        /*      we really only need to flush when throttling is enabled,
                because we push the data as fast as possible anyway if not */
-       if (r->throttle.delay >= PHP_HTTP_DIFFSEC) {
+       if (UNEXPECTED(r->throttle.delay >= PHP_HTTP_DIFFSEC)) {
                r->ops->flush(r);
                php_http_sleep(r->throttle.delay);
        }
@@ -339,14 +339,14 @@ static ZEND_RESULT_CODE php_http_env_response_send_head(php_http_env_response_t
                return ret;
        }
 
-       if ((zoption = get_option(options, ZEND_STRL("headers"), &zoption_tmp))) {
-               if (Z_TYPE_P(zoption) == IS_ARRAY) {
+       if (EXPECTED(zoption = get_option(options, ZEND_STRL("headers"), &zoption_tmp))) {
+               if (EXPECTED(Z_TYPE_P(zoption) == IS_ARRAY)) {
                        php_http_header_to_callback(Z_ARRVAL_P(zoption), 0, (php_http_pass_format_callback_t) r->ops->set_header, r);
                }
                zval_ptr_dtor(zoption);
        }
 
-       if ((zoption = get_option(options, ZEND_STRL("responseCode"), &zoption_tmp))) {
+       if (EXPECTED(zoption = get_option(options, ZEND_STRL("responseCode"), &zoption_tmp))) {
                zend_long rc = zval_get_long(zoption);
 
                zval_ptr_dtor(zoption);
@@ -359,12 +359,12 @@ static ZEND_RESULT_CODE php_http_env_response_send_head(php_http_env_response_t
                return ret;
        }
 
-       if ((zoption = get_option(options, ZEND_STRL("httpVersion"), &zoption_tmp))) {
+       if (EXPECTED(zoption = get_option(options, ZEND_STRL("httpVersion"), &zoption_tmp))) {
                php_http_version_t v;
                zend_string *zs = zval_get_string(zoption);
 
                zval_ptr_dtor(zoption);
-               if (zs->len && php_http_version_parse(&v, zs->val)) {
+               if (EXPECTED(zs->len && php_http_version_parse(&v, zs->val))) {
                        ret = r->ops->set_protocol_version(r, &v);
                        php_http_version_dtor(&v);
                }
@@ -375,7 +375,7 @@ static ZEND_RESULT_CODE php_http_env_response_send_head(php_http_env_response_t
                return ret;
        }
 
-       if ((zoption = get_option(options, ZEND_STRL("cookies"), &zoption_tmp))) {
+       if (EXPECTED(zoption = get_option(options, ZEND_STRL("cookies"), &zoption_tmp))) {
                if (Z_TYPE_P(zoption) == IS_ARRAY) {
                        zval *zcookie;
 
@@ -403,7 +403,7 @@ static ZEND_RESULT_CODE php_http_env_response_send_head(php_http_env_response_t
                return ret;
        }
 
-       if ((zoption = get_option(options, ZEND_STRL("contentType"), &zoption_tmp))) {
+       if (EXPECTED(zoption = get_option(options, ZEND_STRL("contentType"), &zoption_tmp))) {
                zend_string *zs = zval_get_string(zoption);
 
                zval_ptr_dtor(zoption);
@@ -419,12 +419,12 @@ static ZEND_RESULT_CODE php_http_env_response_send_head(php_http_env_response_t
                return ret;
        }
 
-       if (r->range.status == PHP_HTTP_RANGE_OK) {
+       if (UNEXPECTED(r->range.status == PHP_HTTP_RANGE_OK)) {
                if (zend_hash_num_elements(&r->range.values) == 1) {
                        zval *range, *begin, *end;
 
-                       if (    1 == php_http_array_list(&r->range.values, 1, &range)
-                               &&      2 == php_http_array_list(Z_ARRVAL_P(range), 2, &begin, &end)
+                       if (EXPECTED(   1 == php_http_array_list(&r->range.values, 1, &range)
+                               &&      2 == php_http_array_list(Z_ARRVAL_P(range), 2, &begin, &end))
                        ) {
                                if (SUCCESS == (ret = r->ops->set_status(r, 206))) {
                                        ret = r->ops->set_header(r, "Content-Range: bytes %ld-%ld/%zu", Z_LVAL_P(begin), Z_LVAL_P(end), r->content.length);
@@ -441,7 +441,7 @@ static ZEND_RESULT_CODE php_http_env_response_send_head(php_http_env_response_t
                        }
                }
        } else {
-               if ((zoption = get_option(options, ZEND_STRL("cacheControl"), &zoption_tmp))) {
+               if (EXPECTED(zoption = get_option(options, ZEND_STRL("cacheControl"), &zoption_tmp))) {
                        zend_string *zs = zval_get_string(zoption);
 
                        zval_ptr_dtor(zoption);
@@ -455,7 +455,7 @@ static ZEND_RESULT_CODE php_http_env_response_send_head(php_http_env_response_t
                        return ret;
                }
 
-               if ((zoption = get_option(options, ZEND_STRL("contentDisposition"), &zoption_tmp))) {
+               if (EXPECTED(zoption = get_option(options, ZEND_STRL("contentDisposition"), &zoption_tmp))) {
 
                        if (Z_TYPE_P(zoption) == IS_ARRAY) {
                                php_http_buffer_t buf;
@@ -476,7 +476,7 @@ static ZEND_RESULT_CODE php_http_env_response_send_head(php_http_env_response_t
                        return ret;
                }
 
-               if ((zoption = get_option(options, ZEND_STRL("contentEncoding"), &zoption_tmp))) {
+               if (EXPECTED(zoption = get_option(options, ZEND_STRL("contentEncoding"), &zoption_tmp))) {
                        zend_long ce = zval_get_long(zoption);
                        zval zsupported;
                        HashTable *result = NULL;
@@ -551,22 +551,22 @@ static ZEND_RESULT_CODE php_http_env_response_send_head(php_http_env_response_t
                                        break;
                        }
 
-                       if ((zoption = get_option(options, ZEND_STRL("etag"), &zoption_tmp))) {
+                       if (EXPECTED(zoption = get_option(options, ZEND_STRL("etag"), &zoption_tmp))) {
                                zend_string *zs = zval_get_string(zoption);
 
                                zval_ptr_dtor(zoption);
-                               if (*zs->val != '"' && strncmp(zs->val, "W/\"", 3)) {
+                               if (EXPECTED(*zs->val != '"' && strncmp(zs->val, "W/\"", 3))) {
                                        ret = r->ops->set_header(r, "ETag: \"%s\"", zs->val);
                                } else {
                                        ret = r->ops->set_header(r, "ETag: %s", zs->val);
                                }
                                zend_string_release(zs);
                        }
-                       if ((zoption = get_option(options, ZEND_STRL("lastModified"), &zoption_tmp))) {
+                       if (EXPECTED(zoption = get_option(options, ZEND_STRL("lastModified"), &zoption_tmp))) {
                                zend_long lm = zval_get_long(zoption);
 
                                zval_ptr_dtor(zoption);
-                               if (lm) {
+                               if (EXPECTED(lm)) {
                                        zend_string *date = php_format_date(ZEND_STRL(PHP_HTTP_DATE_FORMAT), lm, 0);
                                        if (date) {
                                                ret = r->ops->set_header(r, "Last-Modified: %s", date->val);
@@ -590,17 +590,17 @@ static ZEND_RESULT_CODE php_http_env_response_send_body(php_http_env_response_t
                return ret;
        }
 
-       if ((body = get_body(&r->options))) {
-               if ((zoption = get_option(&r->options, ZEND_STRL("throttleDelay"), &zoption_tmp))) {
+       if (EXPECTED(body = get_body(&r->options))) {
+               if (EXPECTED(zoption = get_option(&r->options, ZEND_STRL("throttleDelay"), &zoption_tmp))) {
                        r->throttle.delay = zval_get_double(zoption);
                        zval_ptr_dtor(zoption);
                }
-               if ((zoption = get_option(&r->options, ZEND_STRL("throttleChunk"), &zoption_tmp))) {
+               if (EXPECTED(zoption = get_option(&r->options, ZEND_STRL("throttleChunk"), &zoption_tmp))) {
                        r->throttle.chunk = zval_get_long(zoption);
                        zval_ptr_dtor(zoption);
                }
 
-               if (r->range.status == PHP_HTTP_RANGE_OK) {
+               if (UNEXPECTED(r->range.status == PHP_HTTP_RANGE_OK)) {
                        if (zend_hash_num_elements(&r->range.values) == 1) {
                                /* single range */
                                zval *range, *begin, *end;
@@ -672,10 +672,10 @@ ZEND_RESULT_CODE php_http_env_response_send(php_http_env_response_t *r)
        request = get_request(&r->options);
 
        /* check for ranges */
-       if ((body = get_body(&r->options))) {
+       if (EXPECTED(body = get_body(&r->options))) {
                r->content.length = php_http_message_body_size(body);
 
-               if (SUCCESS != r->ops->set_header(r, "Accept-Ranges: bytes")) {
+               if (UNEXPECTED(SUCCESS != r->ops->set_header(r, "Accept-Ranges: bytes"))) {
                        return FAILURE;
                } else {
                        ZEND_INIT_SYMTABLE_EX(&r->range.values, 0, 0);
@@ -727,17 +727,17 @@ ZEND_RESULT_CODE php_http_env_response_send(php_http_env_response_t *r)
                }
        }
 
-       if (SUCCESS != php_http_env_response_send_head(r, request)) {
+       if (UNEXPECTED(SUCCESS != php_http_env_response_send_head(r, request))) {
                php_error_docref(NULL, E_WARNING, "Failed to send response headers");
                return FAILURE;
        }
 
-       if (SUCCESS != php_http_env_response_send_body(r)) {
+       if (UNEXPECTED(SUCCESS != php_http_env_response_send_body(r))) {
                php_error_docref(NULL, E_WARNING, "Failed to send response body");
                return FAILURE;
        }
 
-       if (SUCCESS != r->ops->finish(r)) {
+       if (UNEXPECTED(SUCCESS != r->ops->finish(r))) {
                php_error_docref(NULL, E_WARNING, "Failed to finish response");
                return FAILURE;
        }
@@ -857,7 +857,7 @@ static ZEND_RESULT_CODE php_http_env_response_stream_init(php_http_env_response_
        ctx->request = get_request(&r->options);
 
        /* there are some limitations regarding TE:chunked, see https://tools.ietf.org/html/rfc7230#section-3.3.1 */
-       if (ctx->request && ctx->request->http.version.major == 1 && ctx->request->http.version.minor == 0) {
+       if (UNEXPECTED(ctx->request && ctx->request->http.version.major == 1 && ctx->request->http.version.minor == 0)) {
                ctx->version.minor = 0;
        }
 
@@ -869,7 +869,7 @@ static void php_http_env_response_stream_dtor(php_http_env_response_t *r)
 {
        php_http_env_response_stream_ctx_t *ctx = r->ctx;
 
-       if (ctx->chunked_filter) {
+       if (UNEXPECTED(ctx->chunked_filter)) {
                ctx->chunked_filter = php_stream_filter_remove(ctx->chunked_filter, 1);
        }
        zend_hash_destroy(&ctx->header);
@@ -883,7 +883,7 @@ static void php_http_env_response_stream_header(php_http_env_response_stream_ctx
 
        ZEND_HASH_FOREACH_VAL(header, val)
        {
-               if (Z_TYPE_P(val) == IS_ARRAY) {
+               if (UNEXPECTED(Z_TYPE_P(val) == IS_ARRAY)) {
                        php_http_env_response_stream_header(ctx, Z_ARRVAL_P(val), buf);
                } else {
                        zend_string *zs = zval_get_string(val);
@@ -913,11 +913,11 @@ static ZEND_RESULT_CODE php_http_env_response_stream_start(php_http_env_response
        php_http_buffer_appendf(&header_buf, "HTTP/%u.%u %ld %s" PHP_HTTP_CRLF, ctx->version.major, ctx->version.minor, ctx->status_code, php_http_env_get_response_status_for_code(ctx->status_code));
 
        /* there are some limitations regarding TE:chunked, see https://tools.ietf.org/html/rfc7230#section-3.3.1 */
-       if (ctx->version.major == 1 && ctx->version.minor == 0) {
+       if (UNEXPECTED(ctx->version.major == 1 && ctx->version.minor == 0)) {
                ctx->chunked = 0;
-       } else if (ctx->status_code == 204 || ctx->status_code/100 == 1) {
+       } else if (UNEXPECTED(ctx->status_code == 204 || ctx->status_code/100 == 1)) {
                ctx->chunked = 0;
-       } else if (ctx->request && ctx->status_code/100 == 2 && !strcasecmp(ctx->request->http.info.request.method, "CONNECT")) {
+       } else if (UNEXPECTED(ctx->request && ctx->status_code/100 == 2 && !strcasecmp(ctx->request->http.info.request.method, "CONNECT"))) {
                ctx->chunked = 0;
        }
 
@@ -982,13 +982,13 @@ static ZEND_RESULT_CODE php_http_env_response_stream_set_header_ex(php_http_env_
        zend_string *header_key;
        ZEND_RESULT_CODE rv;
 
-       if (stream_ctx->started || stream_ctx->finished) {
+       if (UNEXPECTED(stream_ctx->started || stream_ctx->finished)) {
                return FAILURE;
        }
 
        header_len = vspprintf(&header_str, 0, fmt, argv);
 
-       if (!(header_end = strchr(header_str, ':'))) {
+       if (UNEXPECTED(!(header_end = strchr(header_str, ':')))) {
                efree(header_str);
                return FAILURE;
        }
@@ -1080,10 +1080,10 @@ static ZEND_RESULT_CODE php_http_env_response_stream_finish(php_http_env_respons
 {
        php_http_env_response_stream_ctx_t *ctx = r->ctx;
 
-       if (ctx->finished) {
+       if (UNEXPECTED(ctx->finished)) {
                return FAILURE;
        }
-       if (!ctx->started) {
+       if (UNEXPECTED(!ctx->started)) {
                if (SUCCESS != php_http_env_response_stream_start(ctx)) {
                        return FAILURE;
                }
index 5acf280..e3e66f1 100644 (file)
@@ -22,7 +22,7 @@
        do { \
                zend_error_handling __zeh; \
                zend_replace_error_handling(EH_THROW, php_http_get_exception_ ##e## _class_entry(), &__zeh); \
-               if (!(test)) { \
+               if (UNEXPECTED(!(test))) { \
                        zend_restore_error_handling(&__zeh); \
                        fail; \
                } \
index fb84452..b97ae6b 100644 (file)
@@ -40,42 +40,19 @@ php_http_header_parser_t *php_http_header_parser_init(php_http_header_parser_t *
        return parser;
 }
 
-php_http_header_parser_state_t php_http_header_parser_state_push(php_http_header_parser_t *parser, unsigned argc, ...)
-{
-       va_list va_args;
-       unsigned i;
-       php_http_header_parser_state_t state = 0;
-
-       /* short circuit */
-       ZEND_PTR_STACK_RESIZE_IF_NEEDED((&parser->stack), argc);
-
-       va_start(va_args, argc);
-       for (i = 0; i < argc; ++i) {
-               state = va_arg(va_args, php_http_header_parser_state_t);
-               zend_ptr_stack_push(&parser->stack, (void *) state);
-       }
-       va_end(va_args);
-
-       return state;
-}
+#define php_http_header_parser_state_push(parser, state) zend_ptr_stack_push(&(parser)->stack, (void *) (state)), (state)
+#define php_http_header_parser_state_ex(parser) ((parser)->stack.top \
+               ? (php_http_header_parser_state_t) (parser)->stack.elements[(parser)->stack.top - 1] \
+               : PHP_HTTP_HEADER_PARSER_STATE_START)
 
 php_http_header_parser_state_t php_http_header_parser_state_is(php_http_header_parser_t *parser)
 {
-       if (parser->stack.top) {
-               return (php_http_header_parser_state_t) parser->stack.elements[parser->stack.top - 1];
-       }
-
-       return PHP_HTTP_HEADER_PARSER_STATE_START;
+       return php_http_header_parser_state_ex(parser);
 }
 
-php_http_header_parser_state_t php_http_header_parser_state_pop(php_http_header_parser_t *parser)
-{
-       if (parser->stack.top) {
-               return (php_http_header_parser_state_t) zend_ptr_stack_pop(&parser->stack);
-       }
-
-       return PHP_HTTP_HEADER_PARSER_STATE_START;
-}
+#define php_http_header_parser_state_pop(parser) ((parser)->stack.top \
+               ? (php_http_header_parser_state_t) zend_ptr_stack_pop(&(parser)->stack) \
+               : PHP_HTTP_HEADER_PARSER_STATE_START)
 
 void php_http_header_parser_dtor(php_http_header_parser_t *parser)
 {
@@ -114,7 +91,7 @@ static void php_http_header_parser_error(size_t valid_len, char *str, size_t len
 
 php_http_header_parser_state_t php_http_header_parser_parse(php_http_header_parser_t *parser, php_http_buffer_t *buffer, unsigned flags, HashTable *headers, php_http_info_callback_t callback_func, void *callback_arg)
 {
-       while (buffer->used || !php_http_header_parser_states[php_http_header_parser_state_is(parser)].need_data) {
+       while (buffer->used || !php_http_header_parser_states[php_http_header_parser_state_ex(parser)].need_data) {
 #if DBG_PARSER
                const char *state[] = {"START", "KEY", "VALUE", "VALUE_EX", "HEADER_DONE", "DONE"};
                fprintf(stderr, "#HP: %s (avail:%zu, num:%d cleanup:%u)\n", php_http_header_parser_state_is(parser) < 0 ? "FAILURE" : state[php_http_header_parser_state_is(parser)], buffer->used, headers?zend_hash_num_elements(headers):0, flags);
@@ -123,7 +100,7 @@ php_http_header_parser_state_t php_http_header_parser_parse(php_http_header_pars
                switch (php_http_header_parser_state_pop(parser)) {
                        case PHP_HTTP_HEADER_PARSER_STATE_FAILURE:
                                php_error_docref(NULL, E_WARNING, "Failed to parse headers");
-                               return php_http_header_parser_state_push(parser, 1, PHP_HTTP_HEADER_PARSER_STATE_FAILURE);
+                               return php_http_header_parser_state_push(parser, PHP_HTTP_HEADER_PARSER_STATE_FAILURE);
 
                        case PHP_HTTP_HEADER_PARSER_STATE_START: {
                                char *ptr = buffer->data;
@@ -133,7 +110,7 @@ php_http_header_parser_state_t php_http_header_parser_parse(php_http_header_pars
                                }
 
                                php_http_buffer_cut(buffer, 0, ptr - buffer->data);
-                               php_http_header_parser_state_push(parser, 1, PHP_HTTP_HEADER_PARSER_STATE_KEY);
+                               php_http_header_parser_state_push(parser, PHP_HTTP_HEADER_PARSER_STATE_KEY);
                                break;
                        }
 
@@ -147,7 +124,7 @@ php_http_header_parser_state_t php_http_header_parser_parse(php_http_header_pars
                                if (buffer->data == (eol_str = php_http_locate_bin_eol(buffer->data, buffer->used, &eol_len))) {
                                        /* end of headers */
                                        php_http_buffer_cut(buffer, 0, eol_len);
-                                       php_http_header_parser_state_push(parser, 1, PHP_HTTP_HEADER_PARSER_STATE_DONE);
+                                       php_http_header_parser_state_push(parser, PHP_HTTP_HEADER_PARSER_STATE_DONE);
                                } else if (php_http_info_parse(&parser->info, buffer->data)) {
                                        /* new message starting with request/response line */
                                        if (callback_func) {
@@ -155,7 +132,7 @@ php_http_header_parser_state_t php_http_header_parser_parse(php_http_header_pars
                                        }
                                        php_http_info_dtor(&parser->info);
                                        php_http_buffer_cut(buffer, 0, eol_str + eol_len - buffer->data);
-                                       php_http_header_parser_state_push(parser, 1, PHP_HTTP_HEADER_PARSER_STATE_HEADER_DONE);
+                                       php_http_header_parser_state_push(parser, PHP_HTTP_HEADER_PARSER_STATE_HEADER_DONE);
                                } else if ((colon = memchr(buffer->data, ':', buffer->used)) && (!eol_str || eol_str > colon)) {
                                        /* header: string */
                                        size_t valid_len;
@@ -167,18 +144,18 @@ php_http_header_parser_state_t php_http_header_parser_parse(php_http_header_pars
                                        if (valid_len != parser->_key.len) {
                                                php_http_header_parser_error(valid_len, parser->_key.str, parser->_key.len, eol_str);
                                                PTR_SET(parser->_key.str, NULL);
-                                               return php_http_header_parser_state_push(parser, 1, PHP_HTTP_HEADER_PARSER_STATE_FAILURE);
+                                               return php_http_header_parser_state_push(parser, PHP_HTTP_HEADER_PARSER_STATE_FAILURE);
                                        }
                                        while (PHP_HTTP_IS_CTYPE(space, *++colon) && *colon != '\n' && *colon != '\r');
                                        php_http_buffer_cut(buffer, 0, colon - buffer->data);
-                                       php_http_header_parser_state_push(parser, 1, PHP_HTTP_HEADER_PARSER_STATE_VALUE);
+                                       php_http_header_parser_state_push(parser, PHP_HTTP_HEADER_PARSER_STATE_VALUE);
                                } else if (eol_str || (flags & PHP_HTTP_HEADER_PARSER_CLEANUP)) {
                                        /* neither reqeust/response line nor 'header:' string, or injected new line or NUL etc. */
                                        php_http_header_parser_error(strspn(buffer->data, PHP_HTTP_HEADER_NAME_CHARS), buffer->data, buffer->used, eol_str);
-                                       return php_http_header_parser_state_push(parser, 1, PHP_HTTP_HEADER_PARSER_STATE_FAILURE);
+                                       return php_http_header_parser_state_push(parser, PHP_HTTP_HEADER_PARSER_STATE_FAILURE);
                                } else {
                                        /* keep feeding */
-                                       return php_http_header_parser_state_push(parser, 1, PHP_HTTP_HEADER_PARSER_STATE_KEY);
+                                       return php_http_header_parser_state_push(parser, PHP_HTTP_HEADER_PARSER_STATE_KEY);
                                }
                                break;
                        }
@@ -217,26 +194,26 @@ php_http_header_parser_state_t php_http_header_parser_parse(php_http_header_pars
 
                                if ((eol_str = php_http_locate_bin_eol(buffer->data, buffer->used, &eol_len))) {
                                        SET_ADD_VAL(eol_str - buffer->data, eol_len);
-                                       php_http_header_parser_state_push(parser, 1, PHP_HTTP_HEADER_PARSER_STATE_VALUE_EX);
+                                       php_http_header_parser_state_push(parser, PHP_HTTP_HEADER_PARSER_STATE_VALUE_EX);
                                } else if (flags & PHP_HTTP_HEADER_PARSER_CLEANUP) {
                                        if (buffer->used) {
                                                SET_ADD_VAL(buffer->used, 0);
                                        }
-                                       php_http_header_parser_state_push(parser, 1, PHP_HTTP_HEADER_PARSER_STATE_HEADER_DONE);
+                                       php_http_header_parser_state_push(parser, PHP_HTTP_HEADER_PARSER_STATE_HEADER_DONE);
                                } else {
-                                       return php_http_header_parser_state_push(parser, 1, PHP_HTTP_HEADER_PARSER_STATE_VALUE);
+                                       return php_http_header_parser_state_push(parser, PHP_HTTP_HEADER_PARSER_STATE_VALUE);
                                }
                                break;
                        }
 
                        case PHP_HTTP_HEADER_PARSER_STATE_VALUE_EX:
                                if (buffer->used && (*buffer->data == ' ' || *buffer->data == '\t')) {
-                                       php_http_header_parser_state_push(parser, 1, PHP_HTTP_HEADER_PARSER_STATE_VALUE);
+                                       php_http_header_parser_state_push(parser, PHP_HTTP_HEADER_PARSER_STATE_VALUE);
                                } else if (buffer->used || (flags & PHP_HTTP_HEADER_PARSER_CLEANUP)) {
-                                       php_http_header_parser_state_push(parser, 1, PHP_HTTP_HEADER_PARSER_STATE_HEADER_DONE);
+                                       php_http_header_parser_state_push(parser, PHP_HTTP_HEADER_PARSER_STATE_HEADER_DONE);
                                } else {
                                        /* keep feeding */
-                                       return php_http_header_parser_state_push(parser, 1, PHP_HTTP_HEADER_PARSER_STATE_VALUE_EX);
+                                       return php_http_header_parser_state_push(parser, PHP_HTTP_HEADER_PARSER_STATE_VALUE_EX);
                                }
                                break;
 
@@ -252,7 +229,7 @@ php_http_header_parser_state_t php_http_header_parser_parse(php_http_header_pars
                                                PTR_SET(parser->_key.str, NULL);
                                                PTR_SET(parser->_val.str, NULL);
 
-                                               return php_http_header_parser_state_push(parser, 1, PHP_HTTP_HEADER_PARSER_STATE_FAILURE);
+                                               return php_http_header_parser_state_push(parser, PHP_HTTP_HEADER_PARSER_STATE_FAILURE);
                                        }
 
                                        if (!headers && callback_func) {
@@ -273,7 +250,7 @@ php_http_header_parser_state_t php_http_header_parser_parse(php_http_header_pars
                                PTR_SET(parser->_key.str, NULL);
                                PTR_SET(parser->_val.str, NULL);
 
-                               php_http_header_parser_state_push(parser, 1, PHP_HTTP_HEADER_PARSER_STATE_KEY);
+                               php_http_header_parser_state_push(parser, PHP_HTTP_HEADER_PARSER_STATE_KEY);
                                break;
 
                        case PHP_HTTP_HEADER_PARSER_STATE_DONE:
index c22c6a7..c923998 100644 (file)
@@ -41,9 +41,7 @@ typedef struct php_http_header_parser {
 } php_http_header_parser_t;
 
 PHP_HTTP_API php_http_header_parser_t *php_http_header_parser_init(php_http_header_parser_t *parser);
-PHP_HTTP_API php_http_header_parser_state_t php_http_header_parser_state_push(php_http_header_parser_t *parser, unsigned argc, ...);
 PHP_HTTP_API php_http_header_parser_state_t php_http_header_parser_state_is(php_http_header_parser_t *parser);
-PHP_HTTP_API php_http_header_parser_state_t php_http_header_parser_state_pop(php_http_header_parser_t *parser);
 PHP_HTTP_API void php_http_header_parser_dtor(php_http_header_parser_t *parser);
 PHP_HTTP_API void php_http_header_parser_free(php_http_header_parser_t **parser);
 PHP_HTTP_API php_http_header_parser_state_t php_http_header_parser_parse(php_http_header_parser_t *parser, php_http_buffer_t *buffer, unsigned flags, HashTable *headers, php_http_info_callback_t callback_func, void *callback_arg);
index 1470f97..5125a94 100644 (file)
@@ -96,12 +96,12 @@ php_http_info_t *php_http_info_parse(php_http_info_t *info, const char *pre_head
        zend_bool free_info = !info;
 
        /* sane parameter */
-       if ((!pre_header) || (!*pre_header)) {
+       if (UNEXPECTED((!pre_header) || (!*pre_header))) {
                return NULL;
        }
 
        /* where's the end of the line */
-       if (!(end = php_http_locate_eol(pre_header, NULL))) {
+       if (UNEXPECTED(!(end = php_http_locate_eol(pre_header, NULL)))) {
                end = pre_header + strlen(pre_header);
        }
 
@@ -112,7 +112,7 @@ php_http_info_t *php_http_info_parse(php_http_info_t *info, const char *pre_head
 
        info = php_http_info_init(info);
 
-       if (!php_http_version_parse(&info->http.version, http)) {
+       if (UNEXPECTED(!php_http_version_parse(&info->http.version, http))) {
                if (free_info) {
                        php_http_info_free(&info);
                }
@@ -126,7 +126,7 @@ php_http_info_t *php_http_info_parse(php_http_info_t *info, const char *pre_head
        }
 
        /* and nothing than SPACE or NUL after HTTP/X(.x) */
-       if (*off && (!PHP_HTTP_IS_CTYPE(space, *off))) {
+       if (UNEXPECTED(*off && (!PHP_HTTP_IS_CTYPE(space, *off)))) {
                if (free_info) {
                        php_http_info_free(&info);
                }
@@ -147,7 +147,7 @@ php_http_info_t *php_http_info_parse(php_http_info_t *info, const char *pre_head
 
                info->type = PHP_HTTP_RESPONSE;
                while (code < end && ' ' == *code) ++code;
-               if (end > code) {
+               if (EXPECTED(end > code)) {
                        /* rfc7230#3.1.2 The status-code element is a 3-digit integer code */
                        PHP_HTTP_INFO(info).response.code = 100*(*code++ - '0');
                        PHP_HTTP_INFO(info).response.code += 10*(*code++ - '0');
@@ -162,7 +162,7 @@ php_http_info_t *php_http_info_parse(php_http_info_t *info, const char *pre_head
                } else {
                        PHP_HTTP_INFO(info).response.code = 0;
                }
-               if (status && end > status) {
+               if (EXPECTED(status && end > status)) {
                        while (' ' == *status) ++status;
                        PHP_HTTP_INFO(info).response.status = estrndup(status, end - status);
                } else {
@@ -177,7 +177,7 @@ php_http_info_t *php_http_info_parse(php_http_info_t *info, const char *pre_head
                const char *url = strchr(pre_header, ' ');
 
                info->type = PHP_HTTP_REQUEST;
-               if (url && http > url) {
+               if (EXPECTED(url && http > url)) {
                        size_t url_len = url - pre_header;
 
                        PHP_HTTP_INFO(info).request.method = estrndup(pre_header, url_len);
@@ -185,9 +185,9 @@ php_http_info_t *php_http_info_parse(php_http_info_t *info, const char *pre_head
                        while (' ' == *url) ++url;
                        while (' ' == *(http-1)) --http;
 
-                       if (http > url) {
+                       if (EXPECTED(http > url)) {
                                /* CONNECT presents an authority only */
-                               if (strcasecmp(PHP_HTTP_INFO(info).request.method, "CONNECT")) {
+                               if (UNEXPECTED(strcasecmp(PHP_HTTP_INFO(info).request.method, "CONNECT"))) {
                                        PHP_HTTP_INFO(info).request.url = php_http_url_parse(url, http - url, PHP_HTTP_URL_STDFLAGS);
                                } else {
                                        PHP_HTTP_INFO(info).request.url = php_http_url_parse_authority(url, http - url, PHP_HTTP_URL_STDFLAGS);
index 7d8a6f7..55225d3 100644 (file)
@@ -177,24 +177,24 @@ zend_bool php_http_message_is_multipart(php_http_message_t *msg, char **boundary
                popts.input.str = ct->val;
                popts.input.len = ct->len;
 
-               if (php_http_params_parse(&params, &popts)) {
+               if (EXPECTED(php_http_params_parse(&params, &popts))) {
                        zval *cur, *arg;
                        zend_string *ct_str;
                        zend_ulong index;
 
                        zend_hash_internal_pointer_reset(&params);
 
-                       if ((cur = zend_hash_get_current_data(&params))
+                       if (EXPECTED((cur = zend_hash_get_current_data(&params))
                        &&      (Z_TYPE_P(cur) == IS_ARRAY)
-                       &&      (HASH_KEY_IS_STRING == zend_hash_get_current_key(&params, &ct_str, &index))
+                       &&      (HASH_KEY_IS_STRING == zend_hash_get_current_key(&params, &ct_str, &index)))
                        ) {
                                if (php_http_match(ct_str->val, "multipart", PHP_HTTP_MATCH_WORD)) {
                                        is_multipart = 1;
 
                                        /* get boundary */
-                                       if (boundary
+                                       if (EXPECTED(boundary
                                        &&      (arg = zend_hash_str_find(Z_ARRVAL_P(cur), ZEND_STRL("arguments")))
-                                       &&      Z_TYPE_P(arg) == IS_ARRAY
+                                       &&      Z_TYPE_P(arg) == IS_ARRAY)
                                        ) {
                                                zval *val;
                                                php_http_arrkey_t key;
@@ -204,7 +204,7 @@ zend_bool php_http_message_is_multipart(php_http_message_t *msg, char **boundary
                                                        if (key.key && key.key->len == lenof("boundary") && !strcasecmp(key.key->val, "boundary")) {
                                                                zend_string *bnd = zval_get_string(val);
 
-                                                               if (bnd->len) {
+                                                               if (EXPECTED(bnd->len)) {
                                                                        *boundary = estrndup(bnd->val, bnd->len);
                                                                }
                                                                zend_string_release(bnd);
@@ -471,7 +471,7 @@ php_http_message_t *php_http_message_copy_ex(php_http_message_t *from, php_http_
 
 void php_http_message_dtor(php_http_message_t *message)
 {
-       if (message) {
+       if (EXPECTED(message)) {
                zend_hash_destroy(&message->hdrs);
                php_http_message_body_free(&message->body);
 
@@ -493,7 +493,7 @@ void php_http_message_dtor(php_http_message_t *message)
 
 void php_http_message_free(php_http_message_t **message)
 {
-       if (*message) {
+       if (EXPECTED(*message)) {
                if ((*message)->parent) {
                        php_http_message_free(&(*message)->parent);
                }
index db935d9..49a6013 100644 (file)
@@ -57,41 +57,16 @@ php_http_message_parser_t *php_http_message_parser_init(php_http_message_parser_
        return parser;
 }
 
-php_http_message_parser_state_t php_http_message_parser_state_push(php_http_message_parser_t *parser, unsigned argc, ...)
-{
-       php_http_message_parser_state_t state = PHP_HTTP_MESSAGE_PARSER_STATE_FAILURE;
-       va_list va_args;
-       unsigned i;
-
-       if (argc > 0) {
-               /* short circuit */
-               ZEND_PTR_STACK_RESIZE_IF_NEEDED((&parser->stack), argc);
-
-               va_start(va_args, argc);
-               for (i = 0; i < argc; ++i) {
-                       state  = va_arg(va_args, php_http_message_parser_state_t);
-                       zend_ptr_stack_push(&parser->stack, (void *) state);
-               }
-               va_end(va_args);
-       }
-
-       return state;
-}
-
+#define php_http_message_parser_state_push(parser, state) zend_ptr_stack_push(&(parser)->stack, (void *) (state)), (state)
+#define php_http_message_parser_state_pop(parser) ((parser)->stack.top \
+               ? (php_http_message_parser_state_t) zend_ptr_stack_pop(&parser->stack) \
+               : PHP_HTTP_MESSAGE_PARSER_STATE_START)
+#define php_http_message_parser_state_is_ex(parser) ((parser)->stack.top \
+               ? (php_http_message_parser_state_t) (parser)->stack.elements[(parser)->stack.top - 1] \
+               : PHP_HTTP_MESSAGE_PARSER_STATE_START)
 php_http_message_parser_state_t php_http_message_parser_state_is(php_http_message_parser_t *parser)
 {
-       if (parser->stack.top) {
-               return (php_http_message_parser_state_t) parser->stack.elements[parser->stack.top - 1];
-       }
-       return PHP_HTTP_MESSAGE_PARSER_STATE_START;
-}
-
-php_http_message_parser_state_t php_http_message_parser_state_pop(php_http_message_parser_t *parser)
-{
-       if (parser->stack.top) {
-               return (php_http_message_parser_state_t) zend_ptr_stack_pop(&parser->stack);
-       }
-       return PHP_HTTP_MESSAGE_PARSER_STATE_START;
+       return php_http_message_parser_state_is_ex(parser);
 }
 
 void php_http_message_parser_dtor(php_http_message_parser_t *parser)
@@ -188,7 +163,7 @@ php_http_message_parser_state_t php_http_message_parser_parse_stream(php_http_me
 
                        case PHP_HTTP_MESSAGE_PARSER_STATE_DONE:
                        case PHP_HTTP_MESSAGE_PARSER_STATE_FAILURE:
-                               return php_http_message_parser_state_is(parser);
+                               return php_http_message_parser_state_is_ex(parser);
                }
 
                if (justread) {
@@ -210,7 +185,7 @@ php_http_message_parser_state_t php_http_message_parser_parse(php_http_message_p
        size_t len = 0;
        size_t cut = 0;
 
-       while (buffer->used || !php_http_message_parser_states[php_http_message_parser_state_is(parser)].need_data) {
+       while (buffer->used || !php_http_message_parser_states[php_http_message_parser_state_is_ex(parser)].need_data) {
 #if DBG_PARSER
                fprintf(stderr, "#MP: %s (f: %u, t:%d, l:%zu)\n", 
                        php_http_message_parser_state_name(php_http_message_parser_state_is(parser)),
@@ -224,7 +199,7 @@ php_http_message_parser_state_t php_http_message_parser_parse(php_http_message_p
                switch (php_http_message_parser_state_pop(parser))
                {
                        case PHP_HTTP_MESSAGE_PARSER_STATE_FAILURE:
-                               return php_http_message_parser_state_push(parser, 1, PHP_HTTP_MESSAGE_PARSER_STATE_FAILURE);
+                               return php_http_message_parser_state_push(parser, PHP_HTTP_MESSAGE_PARSER_STATE_FAILURE);
 
                        case PHP_HTTP_MESSAGE_PARSER_STATE_START:
                        {
@@ -237,7 +212,7 @@ php_http_message_parser_state_t php_http_message_parser_parse(php_http_message_p
                                php_http_buffer_cut(buffer, 0, ptr - buffer->data);
 
                                if (buffer->used) {
-                                       php_http_message_parser_state_push(parser, 1, PHP_HTTP_MESSAGE_PARSER_STATE_HEADER);
+                                       php_http_message_parser_state_push(parser, PHP_HTTP_MESSAGE_PARSER_STATE_HEADER);
                                }
                                break;
                        }
@@ -251,14 +226,14 @@ php_http_message_parser_state_t php_http_message_parser_parse(php_http_message_p
                                                return PHP_HTTP_MESSAGE_PARSER_STATE_FAILURE;
 
                                        case PHP_HTTP_HEADER_PARSER_STATE_DONE:
-                                               php_http_message_parser_state_push(parser, 1, PHP_HTTP_MESSAGE_PARSER_STATE_HEADER_DONE);
+                                               php_http_message_parser_state_push(parser, PHP_HTTP_MESSAGE_PARSER_STATE_HEADER_DONE);
                                                break;
 
                                        default:
                                                if (buffer->used || !(flags & PHP_HTTP_MESSAGE_PARSER_CLEANUP)) {
-                                                       return php_http_message_parser_state_push(parser, 1, PHP_HTTP_MESSAGE_PARSER_STATE_HEADER);
+                                                       return php_http_message_parser_state_push(parser, PHP_HTTP_MESSAGE_PARSER_STATE_HEADER);
                                                } else {
-                                                       php_http_message_parser_state_push(parser, 1, PHP_HTTP_MESSAGE_PARSER_STATE_HEADER_DONE);
+                                                       php_http_message_parser_state_push(parser, PHP_HTTP_MESSAGE_PARSER_STATE_HEADER_DONE);
                                                }
                                }
                                break;
@@ -313,7 +288,7 @@ php_http_message_parser_state_t php_http_message_parser_parse(php_http_message_p
 
                                        if (php_http_match(con->val, "close", PHP_HTTP_MATCH_WORD)) {
                                                zend_string_release(con);
-                                               php_http_message_parser_state_push(parser, 1, PHP_HTTP_MESSAGE_PARSER_STATE_DONE);
+                                               php_http_message_parser_state_push(parser, PHP_HTTP_MESSAGE_PARSER_STATE_DONE);
                                                break;
                                        }
                                        zend_string_release(con);
@@ -339,11 +314,11 @@ php_http_message_parser_state_t php_http_message_parser_parse(php_http_message_p
                                }
 
                                if ((flags & PHP_HTTP_MESSAGE_PARSER_DUMB_BODIES)) {
-                                       php_http_message_parser_state_push(parser, 1, PHP_HTTP_MESSAGE_PARSER_STATE_BODY_DUMB);
+                                       php_http_message_parser_state_push(parser, PHP_HTTP_MESSAGE_PARSER_STATE_BODY_DUMB);
                                } else {
                                        if (chunked) {
                                                parser->dechunk = php_http_encoding_stream_init(parser->dechunk, php_http_encoding_stream_get_dechunk_ops(), 0);
-                                               php_http_message_parser_state_push(parser, 1, PHP_HTTP_MESSAGE_PARSER_STATE_BODY_CHUNKED);
+                                               php_http_message_parser_state_push(parser, PHP_HTTP_MESSAGE_PARSER_STATE_BODY_CHUNKED);
                                                break;
                                        }
 
@@ -368,7 +343,11 @@ php_http_message_parser_state_t php_http_message_parser_parse(php_http_message_p
 
                                                                if (end >= start && (!total || end <= total)) {
                                                                        parser->body_length = end + 1 - start;
-                                                                       php_http_message_parser_state_push(parser, 1, !parser->body_length?PHP_HTTP_MESSAGE_PARSER_STATE_BODY_DONE:PHP_HTTP_MESSAGE_PARSER_STATE_BODY_LENGTH);
+                                                                       if (parser->body_length) {
+                                                                               php_http_message_parser_state_push(parser, PHP_HTTP_MESSAGE_PARSER_STATE_BODY_LENGTH);
+                                                                       } else {
+                                                                               php_http_message_parser_state_push(parser, PHP_HTTP_MESSAGE_PARSER_STATE_BODY_DONE);
+                                                                       }
                                                                        zend_string_release(content_range);
                                                                        break;
                                                                }
@@ -380,14 +359,18 @@ php_http_message_parser_state_t php_http_message_parser_parse(php_http_message_p
 
                                        if (content_length >= 0) {
                                                parser->body_length = content_length;
-                                               php_http_message_parser_state_push(parser, 1, !parser->body_length?PHP_HTTP_MESSAGE_PARSER_STATE_BODY_DONE:PHP_HTTP_MESSAGE_PARSER_STATE_BODY_LENGTH);
+                                               if (parser->body_length) {
+                                                       php_http_message_parser_state_push(parser, PHP_HTTP_MESSAGE_PARSER_STATE_BODY_LENGTH);
+                                               } else {
+                                                       php_http_message_parser_state_push(parser, PHP_HTTP_MESSAGE_PARSER_STATE_BODY_DONE);
+                                               }
                                                break;
                                        }
 
                                        if ((*message)->type == PHP_HTTP_REQUEST) {
-                                               php_http_message_parser_state_push(parser, 1, PHP_HTTP_MESSAGE_PARSER_STATE_DONE);
+                                               php_http_message_parser_state_push(parser, PHP_HTTP_MESSAGE_PARSER_STATE_DONE);
                                        } else {
-                                               php_http_message_parser_state_push(parser, 1, PHP_HTTP_MESSAGE_PARSER_STATE_BODY_DUMB);
+                                               php_http_message_parser_state_push(parser, PHP_HTTP_MESSAGE_PARSER_STATE_BODY_DUMB);
                                        }
                                }
                                break;
@@ -401,7 +384,7 @@ php_http_message_parser_state_t php_http_message_parser_parse(php_http_message_p
                                                size_t dec_len;
 
                                                if (SUCCESS != php_http_encoding_stream_update(parser->inflate, str, len, &dec_str, &dec_len)) {
-                                                       return php_http_message_parser_state_push(parser, 1, PHP_HTTP_MESSAGE_PARSER_STATE_FAILURE);
+                                                       return php_http_message_parser_state_push(parser, PHP_HTTP_MESSAGE_PARSER_STATE_FAILURE);
                                                }
 
                                                if (str != buffer->data) {
@@ -434,7 +417,8 @@ php_http_message_parser_state_t php_http_message_parser_parse(php_http_message_p
                                len = buffer->used;
                                cut = len;
 
-                               php_http_message_parser_state_push(parser, 2, PHP_HTTP_MESSAGE_PARSER_STATE_BODY_DONE, PHP_HTTP_MESSAGE_PARSER_STATE_BODY);
+                               php_http_message_parser_state_push(parser, PHP_HTTP_MESSAGE_PARSER_STATE_BODY_DONE);
+                               php_http_message_parser_state_push(parser, PHP_HTTP_MESSAGE_PARSER_STATE_BODY);
                                break;
                        }
 
@@ -446,7 +430,12 @@ php_http_message_parser_state_t php_http_message_parser_parse(php_http_message_p
 
                                parser->body_length -= len;
 
-                               php_http_message_parser_state_push(parser, 2, !parser->body_length?PHP_HTTP_MESSAGE_PARSER_STATE_BODY_DONE:PHP_HTTP_MESSAGE_PARSER_STATE_BODY_LENGTH, PHP_HTTP_MESSAGE_PARSER_STATE_BODY);
+                               if (parser->body_length) {
+                                       php_http_message_parser_state_push(parser, PHP_HTTP_MESSAGE_PARSER_STATE_BODY_LENGTH);
+                               } else {
+                                       php_http_message_parser_state_push(parser, PHP_HTTP_MESSAGE_PARSER_STATE_BODY_DONE);
+                               }
+                               php_http_message_parser_state_push(parser, PHP_HTTP_MESSAGE_PARSER_STATE_BODY);
                                break;
                        }
 
@@ -472,24 +461,26 @@ php_http_message_parser_state_t php_http_message_parser_parse(php_http_message_p
 
                                if (php_http_encoding_stream_done(parser->dechunk)) {
                                        cut = buffer->used - PHP_HTTP_BUFFER(parser->dechunk->ctx)->used;
-                                       php_http_message_parser_state_push(parser, 2, PHP_HTTP_MESSAGE_PARSER_STATE_BODY_DONE, PHP_HTTP_MESSAGE_PARSER_STATE_BODY);
+                                       php_http_message_parser_state_push(parser, PHP_HTTP_MESSAGE_PARSER_STATE_BODY_DONE);
+                                       php_http_message_parser_state_push(parser, PHP_HTTP_MESSAGE_PARSER_STATE_BODY);
                                } else {
                                        cut = buffer->used;
-                                       php_http_message_parser_state_push(parser, 2, PHP_HTTP_MESSAGE_PARSER_STATE_BODY_CHUNKED, PHP_HTTP_MESSAGE_PARSER_STATE_BODY);
+                                       php_http_message_parser_state_push(parser, PHP_HTTP_MESSAGE_PARSER_STATE_BODY_CHUNKED);
+                                       php_http_message_parser_state_push(parser, PHP_HTTP_MESSAGE_PARSER_STATE_BODY);
                                }
                                break;
                        }
 
                        case PHP_HTTP_MESSAGE_PARSER_STATE_BODY_DONE:
                        {
-                               php_http_message_parser_state_push(parser, 1, PHP_HTTP_MESSAGE_PARSER_STATE_DONE);
+                               php_http_message_parser_state_push(parser, PHP_HTTP_MESSAGE_PARSER_STATE_DONE);
 
                                if (parser->dechunk && parser->dechunk->ctx) {
                                        char *dec_str = NULL;
                                        size_t dec_len;
 
                                        if (SUCCESS != php_http_encoding_stream_finish(parser->dechunk, &dec_str, &dec_len)) {
-                                               return php_http_message_parser_state_push(parser, 1, PHP_HTTP_MESSAGE_PARSER_STATE_FAILURE);
+                                               return php_http_message_parser_state_push(parser, PHP_HTTP_MESSAGE_PARSER_STATE_FAILURE);
                                        }
                                        php_http_encoding_stream_dtor(parser->dechunk);
 
@@ -497,7 +488,8 @@ php_http_message_parser_state_t php_http_message_parser_parse(php_http_message_p
                                                str = dec_str;
                                                len = dec_len;
                                                cut = 0;
-                                               php_http_message_parser_state_push(parser, 2, PHP_HTTP_MESSAGE_PARSER_STATE_UPDATE_CL, PHP_HTTP_MESSAGE_PARSER_STATE_BODY);
+                                               php_http_message_parser_state_push(parser, PHP_HTTP_MESSAGE_PARSER_STATE_UPDATE_CL);
+                                               php_http_message_parser_state_push(parser, PHP_HTTP_MESSAGE_PARSER_STATE_BODY);
                                        }
                                }
 
@@ -531,7 +523,7 @@ php_http_message_parser_state_t php_http_message_parser_parse(php_http_message_p
                }
        }
 
-       return php_http_message_parser_state_is(parser);
+       return php_http_message_parser_state_is_ex(parser);
 }
 
 static zend_class_entry *php_http_message_parser_class_entry;
@@ -584,7 +576,7 @@ static PHP_METHOD(HttpMessageParser, getState)
 
        zend_parse_parameters_none();
        /* always return the real state */
-       RETVAL_LONG(php_http_message_parser_state_is(parser_obj->parser));
+       RETVAL_LONG(php_http_message_parser_state_is_ex(parser_obj->parser));
 }
 
 ZEND_BEGIN_ARG_INFO_EX(ai_HttpMessageParser_parse, 0, 0, 3)
index 9b6174d..edc6c2b 100644 (file)
@@ -46,9 +46,7 @@ typedef struct php_http_message_parser {
 } php_http_message_parser_t;
 
 PHP_HTTP_API php_http_message_parser_t *php_http_message_parser_init(php_http_message_parser_t *parser);
-PHP_HTTP_API php_http_message_parser_state_t php_http_message_parser_state_push(php_http_message_parser_t *parser, unsigned argc, ...);
 PHP_HTTP_API php_http_message_parser_state_t php_http_message_parser_state_is(php_http_message_parser_t *parser);
-PHP_HTTP_API php_http_message_parser_state_t php_http_message_parser_state_pop(php_http_message_parser_t *parser);
 PHP_HTTP_API void php_http_message_parser_dtor(php_http_message_parser_t *parser);
 PHP_HTTP_API void php_http_message_parser_free(php_http_message_parser_t **parser);
 PHP_HTTP_API php_http_message_parser_state_t php_http_message_parser_parse(php_http_message_parser_t *parser, php_http_buffer_t *buffer, unsigned flags, php_http_message_t **message);
index 467988b..f0cc25f 100644 (file)
@@ -50,11 +50,11 @@ int php_http_match(const char *haystack_str, const char *needle_str, int flags)
 {
        int result = 0;
 
-       if (!haystack_str || !needle_str) {
+       if (UNEXPECTED(!haystack_str || !needle_str)) {
                return result;
        }
 
-       if (flags & PHP_HTTP_MATCH_FULL) {
+       if (UNEXPECTED(flags & PHP_HTTP_MATCH_FULL)) {
                if (flags & PHP_HTTP_MATCH_CASE) {
                        result = !strcmp(haystack_str, needle_str);
                } else {
@@ -64,7 +64,7 @@ int php_http_match(const char *haystack_str, const char *needle_str, int flags)
                const char *found;
                char *haystack = estrdup(haystack_str), *needle = estrdup(needle_str);
 
-               if (flags & PHP_HTTP_MATCH_CASE) {
+               if (UNEXPECTED(flags & PHP_HTTP_MATCH_CASE)) {
                        found = zend_memnstr(haystack, needle, strlen(needle), haystack+strlen(haystack));
                } else {
                        found = php_stristr(haystack, needle, strlen(haystack), strlen(needle));
@@ -73,7 +73,7 @@ int php_http_match(const char *haystack_str, const char *needle_str, int flags)
                if (found) {
                        if (!(flags & PHP_HTTP_MATCH_WORD)
                        ||      (       (found == haystack || !PHP_HTTP_IS_CTYPE(alnum, *(found - 1)))
-                               &&      (!*(found + strlen(needle)) || !PHP_HTTP_IS_CTYPE(alnum, *(found + strlen(needle))))
+                               &&      EXPECTED(!*(found + strlen(needle)) || !PHP_HTTP_IS_CTYPE(alnum, *(found + strlen(needle))))
                                )
                        ) {
                                result = 1;
@@ -89,25 +89,35 @@ int php_http_match(const char *haystack_str, const char *needle_str, int flags)
 
 char *php_http_pretty_key(char *key, size_t key_len, zend_bool uctitle, zend_bool xhyphen)
 {
-       size_t i = 1;
+       size_t i;
        int wasalpha;
 
        if (key && key_len) {
-               if ((wasalpha = PHP_HTTP_IS_CTYPE(alpha, key[0]))) {
-                       key[0] = (char) (uctitle ? PHP_HTTP_TO_CTYPE(upper, key[0]) : PHP_HTTP_TO_CTYPE(lower, key[0]));
+               if (EXPECTED(wasalpha = PHP_HTTP_IS_CTYPE(alpha, key[0]))) {
+                       if (EXPECTED(uctitle)) {
+                               key[0] = PHP_HTTP_TO_CTYPE(upper, key[0]);
+                       } else {
+                               key[0] = PHP_HTTP_TO_CTYPE(lower, key[0]);
+                       }
                }
-               PHP_HTTP_DUFF(key_len,
-                       if (PHP_HTTP_IS_CTYPE(alpha, key[i])) {
-                               key[i] = (char) (((!wasalpha) && uctitle) ? PHP_HTTP_TO_CTYPE(upper, key[i]) : PHP_HTTP_TO_CTYPE(lower, key[i]));
-                               wasalpha = 1;
+               for (i = 1; i < key_len; ++i) {
+                       if (EXPECTED(PHP_HTTP_IS_CTYPE(alpha, key[i]))) {
+                               if (EXPECTED(wasalpha)) {
+                                       key[i] = PHP_HTTP_TO_CTYPE(lower, key[i]);
+                               } else if (EXPECTED(uctitle)) {
+                                       key[i] = PHP_HTTP_TO_CTYPE(upper, key[i]);
+                                       wasalpha = 1;
+                               } else {
+                                       key[i] = PHP_HTTP_TO_CTYPE(lower, key[i]);
+                                       wasalpha = 1;
+                               }
                        } else {
-                               if (xhyphen && (key[i] == '_')) {
+                               if (EXPECTED(xhyphen && (key[i] == '_'))) {
                                        key[i] = '-';
                                }
                                wasalpha = 0;
                        }
-                       ++i;
-               );
+               }
        }
        return key;
 }
index c8ab922..35de35e 100644 (file)
@@ -67,47 +67,7 @@ char *php_http_pretty_key(register char *key, size_t key_len, zend_bool uctitle,
 size_t php_http_boundary(char *buf, size_t len);
 int php_http_select_str(const char *cmp, int argc, ...);
 
-/* See "A Reusable Duff Device" By Ralf Holly, August 01, 2005 */
-#define PHP_HTTP_DUFF_BREAK() times_=1
-#define PHP_HTTP_DUFF(c, a) do { \
-       size_t count_ = (c); \
-       size_t times_ = (count_ + 7) >> 3; \
-       switch (count_ & 7){ \
-               case 0: do { \
-                       a; \
-               case 7: \
-                       a; \
-               case 6: \
-                       a; \
-               case 5: \
-                       a; \
-               case 4: \
-                       a; \
-               case 3: \
-                       a; \
-               case 2: \
-                       a; \
-               case 1: \
-                       a; \
-                                       } while (--times_ > 0); \
-       } \
-} while (0)
-
-static inline const char *php_http_locate_str(register const char *h, size_t h_len, const char *n, size_t n_len)
-{
-       if (!n_len || !h_len || h_len < n_len) {
-               return NULL;
-       }
-
-       PHP_HTTP_DUFF(h_len - n_len + 1,
-               if (*h == *n && !strncmp(h + 1, n + 1, n_len - 1)) {
-                       return h;
-               }
-               ++h;
-       );
-
-       return NULL;
-}
+#define php_http_locate_str(h, h_len, n, n_len) zend_memnstr((h), (n), (n_len), (h)+(h_len))
 
 static inline const char *php_http_locate_eol(const char *line, int *eol_len)
 {
@@ -123,16 +83,14 @@ static inline const char *php_http_locate_bin_eol(const char *bin, size_t len, i
 {
        register const char *eol = bin;
 
-       if (len > 0) {
-               PHP_HTTP_DUFF(len,
-                       if (*eol == '\r' || *eol == '\n') {
-                               if (eol_len) {
-                                       *eol_len = ((eol[0] == '\r' && eol[1] == '\n') ? 2 : 1);
-                               }
-                               return eol;
+       while (len--) {
+               if (UNEXPECTED(*eol == '\r' || *eol == '\n')) {
+                       if (EXPECTED(eol_len)) {
+                               *eol_len = (EXPECTED(eol[0] == '\r' && eol[1] == '\n') ? 2 : 1);
                        }
-                       ++eol;
-               );
+                       return eol;
+               }
+               ++eol;
        }
        return NULL;
 }
index 65cc3d8..ad4f14c 100644 (file)
@@ -752,16 +752,17 @@ static inline size_t parse_mb(struct parse_state *state, parse_mb_what_t what, c
                                }
 #endif
                        }
-                       PHP_HTTP_DUFF(consumed, state->buffer[state->offset++] = *ptr++);
+
+                       memcpy(&state->buffer[state->offset], ptr, consumed);
+                       state->offset += consumed;
                } else {
-                       int i = 0;
-
-                       PHP_HTTP_DUFF(consumed,
-                                       state->buffer[state->offset++] = '%';
-                                       state->buffer[state->offset++] = parse_xdigits[((unsigned char) ptr[i]) >> 4];
-                                       state->buffer[state->offset++] = parse_xdigits[((unsigned char) ptr[i]) & 0xf];
-                                       ++i;
-                       );
+                       size_t i;
+
+                       for (i = 0; i < consumed; ++i) {
+                               state->buffer[state->offset++] = '%';
+                               state->buffer[state->offset++] = parse_xdigits[((unsigned char) ptr[i]) >> 4];
+                               state->buffer[state->offset++] = parse_xdigits[((unsigned char) ptr[i]) & 0xf];
+                       }
                }
 
                return consumed;
@@ -982,10 +983,10 @@ typedef uint16_t UChar;
 typedef enum { U_ZERO_ERROR = 0 } UErrorCode;
 int32_t uidna_IDNToASCII(const UChar *src, int32_t srcLength, UChar *dest, int32_t destCapacity, int32_t options, void *parseError, UErrorCode *status);
 #      endif
-static ZEND_RESULT_CODE parse_uidn_2003(struct parse_state *state)
+static ZEND_RESULT_CODE parse_uidn_2003(struct parse_state *state, size_t prev_len)
 {
-       char *host_ptr = state->url.host, ebuf[64] = {0}, *error = NULL;
-       uint16_t *uhost_str, ahost_str[256], *ahost_ptr;
+       char ebuf[64] = {0}, *error = NULL;
+       uint16_t *uhost_str, ahost_str[256];
        size_t uhost_len, ahost_len;
        UErrorCode rc = U_ZERO_ERROR;
 
@@ -1019,10 +1020,11 @@ static ZEND_RESULT_CODE parse_uidn_2003(struct parse_state *state)
                goto error;
        }
 
-       ahost_ptr = ahost_str;
-       PHP_HTTP_DUFF(ahost_len, *host_ptr++ = *ahost_ptr++);
-       *host_ptr = '\0';
-       state->offset += host_ptr - state->url.host;
+       state->url.host[ahost_len] = '\0';
+       state->offset += ahost_len - prev_len;
+       while (ahost_len--) {
+               state->url.host[ahost_len] = ahost_str[ahost_len];
+       }
 
        return SUCCESS;
 
@@ -1038,9 +1040,9 @@ static ZEND_RESULT_CODE parse_uidn_2003(struct parse_state *state)
 #endif
 
 #if PHP_HTTP_HAVE_LIBICU && HAVE_UIDNA_NAMETOASCII_UTF8
-static ZEND_RESULT_CODE parse_uidn_2008(struct parse_state *state)
+static ZEND_RESULT_CODE parse_uidn_2008(struct parse_state *state, size_t prev_len)
 {
-       char *host_ptr, *error = NULL, ebuf[64] = {0};
+       char *error = NULL, ebuf[64] = {0};
        UErrorCode rc = U_ZERO_ERROR;
        UIDNAInfo info = UIDNA_INFO_INITIALIZER;
        UIDNA *uidna = uidna_openUTS46(UIDNA_ALLOW_UNASSIGNED, &rc);
@@ -1049,42 +1051,46 @@ static ZEND_RESULT_CODE parse_uidn_2008(struct parse_state *state)
                return FAILURE;
        }
 
-       host_ptr = state->url.host;
-
        if (state->flags & PHP_HTTP_URL_PARSE_MBUTF8) {
-               char ahost_str[256], *ahost_ptr = &ahost_str[0];
-               size_t ahost_len = uidna_nameToASCII_UTF8(uidna, host_ptr, -1, ahost_str, sizeof(ahost_str)-1, &info, &rc);
+               char ahost_str[256];
+               size_t ahost_len = uidna_nameToASCII_UTF8(uidna, state->url.host, -1, ahost_str, sizeof(ahost_str)-1, &info, &rc);
 
                if (U_FAILURE(rc) || info.errors) {
                        goto error;
                }
-               PHP_HTTP_DUFF(ahost_len, *host_ptr++ = *ahost_ptr++);
+
+               memcpy(state->url.host, ahost_str, ahost_len);
+               state->url.host[ahost_len] = '\0';
+               state->offset += ahost_len - prev_len;
+
 #if PHP_HTTP_HAVE_WCHAR
        } else if (state->flags & PHP_HTTP_URL_PARSE_MBLOC) {
-               uint16_t *uhost_str, whost_str[256], *whost_ptr = &whost_str[0];
+               uint16_t *uhost_str, whost_str[256];
                size_t uhost_len, whost_len;
 
-               if (SUCCESS != to_utf16(parse_mb_loc, host_ptr, &uhost_str, &uhost_len)) {
+               if (SUCCESS != to_utf16(parse_mb_loc, state->url.host, &uhost_str, &uhost_len)) {
                        error = "could not convert to UTF-16";
                        goto error;
                }
 
                whost_len = uidna_nameToASCII(uidna, uhost_str, uhost_len, whost_str, sizeof(whost_str)-1, &info, &rc);
-               whost_ptr = whost_str;
                efree(uhost_str);
+
                if (U_FAILURE(rc) || info.errors) {
                        goto error;
                }
-               PHP_HTTP_DUFF(whost_len, *host_ptr++ = *whost_ptr++);
+
+               state->url.host[whost_len] = '\0';
+               state->offset += whost_len - prev_len;
+               while (whost_len--) {
+                       state->url.host[whost_len] = whost_str[whost_len];
+               }
 #endif
        } else {
                error = "codepage not specified";
                goto error;
        }
 
-       *host_ptr = '\0';
-       state->offset += host_ptr - state->url.host;
-
        uidna_close(uidna);
        return SUCCESS;
 
@@ -1111,7 +1117,7 @@ static ZEND_RESULT_CODE parse_uidn_2008(struct parse_state *state)
 #      if __GNUC__
 __attribute__ ((unused))
 #      endif
-static ZEND_RESULT_CODE parse_kidn(struct parse_state *state)
+static ZEND_RESULT_CODE parse_kidn(struct parse_state *state, size_t prev_len)
 {
        idn_result_t rc;
 #if PHP_HTTP_HAVE_LIBIDNKIT
@@ -1119,7 +1125,7 @@ static ZEND_RESULT_CODE parse_kidn(struct parse_state *state)
 #elif PHP_HTTP_HAVE_LIBIDNKIT2
        int actions = IDN_MAP|IDN_ASCLOWER|IDN_RTCONV|IDN_PROHCHECK|IDN_NFCCHECK|IDN_PREFCHECK|IDN_COMBCHECK|IDN_CTXOLITECHECK|IDN_BIDICHECK|IDN_LOCALCHECK|IDN_IDNCONV|IDN_LENCHECK|IDN_RTCHECK;
 #endif
-       char ahost_str[256] = {0}, *ahost_ptr = &ahost_str[0], *host_ptr = state->url.host;
+       char ahost_str[256] = {0};
 
        if (state->flags & PHP_HTTP_URL_PARSE_MBLOC) {
 #if PHP_HTTP_HAVE_LIBIDNKIT
@@ -1131,10 +1137,10 @@ static ZEND_RESULT_CODE parse_kidn(struct parse_state *state)
 
        rc = idn_encodename(actions, state->url.host, ahost_str, 256);
        if (rc == idn_success) {
-               PHP_HTTP_DUFF(strlen(ahost_str), *host_ptr++ = *ahost_ptr++);
+               size_t ahost_len = strlen(ahost_str);
 
-               *host_ptr = '\0';
-               state->offset += host_ptr - state->url.host;
+               memcpy(state->url.host, ahost_str, ahost_len + 1);
+               state->offset += ahost_len - prev_len;
 
                return SUCCESS;
        } else {
@@ -1145,11 +1151,11 @@ static ZEND_RESULT_CODE parse_kidn(struct parse_state *state)
 #endif
 
 #if 0 && PHP_WIN32
-static ZEND_RESULT_CODE parse_widn_2003(struct parse_state *state)
+static ZEND_RESULT_CODE parse_widn_2003(struct parse_state *state, size_t prev_len)
 {
        char *host_ptr;
-       uint16_t *uhost_str, ahost_str[256], *ahost_ptr;
-       size_t uhost_len;
+       uint16_t *uhost_str, ahost_str[256];
+       size_t uhost_len, ahost_len;
 
        if (state->flags & PHP_HTTP_URL_PARSE_MBUTF8) {
                if (SUCCESS != to_utf16(parse_mb_utf8, state->url.host, &uhost_str, &uhost_len)) {
@@ -1175,12 +1181,12 @@ static ZEND_RESULT_CODE parse_widn_2003(struct parse_state *state)
        }
 
        efree(uhost_str);
-       host_ptr = state->url.host;
-       ahost_ptr = ahost_str;
-       PHP_HTTP_DUFF(wcslen(ahost_str), *host_ptr++ = *ahost_ptr++);
-
-       *host_ptr = '\0';
-       state->offset += host_ptr - state->url.host;
+       ahost_len = wcslen(ahost_str);
+       state->url.host[ahost_len] = '\0';
+       state->offset += ahost_len - prev_len;
+       while (ahost_len--) {
+               state->url.host[ahost_len] = ahost_str[ahost_len];
+       }
 
        return SUCCESS;
 }
@@ -1195,11 +1201,11 @@ static ZEND_RESULT_CODE parse_idna(struct parse_state *state, size_t len)
 #      endif
        ) {
 #if PHP_HTTP_HAVE_LIBICU && HAVE_UIDNA_NAMETOASCII_UTF8
-               return parse_uidn_2008(state);
+               return parse_uidn_2008(state, len);
 #elif PHP_HTTP_HAVE_LIBIDN2
                return parse_gidn_2008(state, len);
 #elif PHP_HTTP_HAVE_LIBIDNKIT2
-               return parse_kidn(state);
+               return parse_kidn(state, len);
 #endif
        }
 #endif
@@ -1211,31 +1217,31 @@ static ZEND_RESULT_CODE parse_idna(struct parse_state *state, size_t len)
 #endif
        ) {
 #if HAVE_UIDNA_IDNTOASCII
-               return parse_uidn_2003(state);
+               return parse_uidn_2003(state, len);
 #elif PHP_HTTP_HAVE_LIBIDN
                return parse_gidn_2003(state, len);
 #elif PHP_HTTP_HAVE_LIBIDNKIT
-               return parse_kidn(state);
+               return parse_kidn(state, len);
 #endif
        }
 #endif
 
 #if 0 && PHP_WIN32
-       return parse_widn_2003(state);
+       return parse_widn_2003(state, len);
 #endif
 
 #if PHP_HTTP_HAVE_LIBICU && HAVE_UIDNA_NAMETOASCII_UTF8
-               return parse_uidn_2008(state);
+               return parse_uidn_2008(state, len);
 #elif PHP_HTTP_HAVE_LIBIDN2
                return parse_gidn_2008(state, len);
 #elif PHP_HTTP_HAVE_LIBIDNKIT2
-               return parse_kidn(state);
+               return parse_kidn(state, len);
 #elif HAVE_UIDNA_IDNTOASCII
-               return parse_uidn_2003(state);
+               return parse_uidn_2003(state, len);
 #elif PHP_HTTP_HAVE_LIBIDN
                return parse_gidn_2003(state, len);
 #elif PHP_HTTP_HAVE_LIBIDNKIT
-               return parse_kidn(state);
+               return parse_kidn(state, len);
 #endif
 
        return SUCCESS;
index f900803..02fd8d7 100644 (file)
@@ -595,24 +595,25 @@ static inline size_t utf8towc(unsigned *wc, const unsigned char *uc, size_t len)
 
 static inline zend_bool isualpha(unsigned ch)
 {
-       unsigned i = 0, j;
+       unsigned j;
+       const utf8_range_t *u = &utf8_ranges[0], *e = &utf8_ranges[sizeof(utf8_ranges)/sizeof(utf8_range_t)-1];
 
-       PHP_HTTP_DUFF(sizeof(utf8_ranges)/sizeof(utf8_range_t),
-               if (utf8_ranges[i].start == ch) {
+       do {
+               if (u->start == ch) {
                        return 1;
-               } else if (utf8_ranges[i].start <= ch && utf8_ranges[i].end >= ch) {
-                       if (utf8_ranges[i].step == 1) {
+               } else if (u->start <= ch && u->end >= ch) {
+                       if (u->step == 1) {
                                return 1;
                        }
-                       for (j = utf8_ranges[i].start; j <= utf8_ranges[i].end; j+= utf8_ranges[i].step) {
+                       for (j = u->start; j <= u->end; j+= u->step) {
                                if (ch == j) {
                                        return 1;
                                }
                        }
                        return 0;
                }
-               ++i;
-       );
+       } while (++u != e);
+
        return 0;
 }