X-Git-Url: https://git.m6w6.name/?p=m6w6%2Fext-http;a=blobdiff_plain;f=php_http_buffer.c;h=e24a4e18baa2e4d7e7a6c8cbdbf7d7c7967fc31b;hp=41fd48a54655ac09cf5e142dfc0d2d49e840e132;hb=refs%2Fheads%2Fv2.3.x;hpb=0a0f485c70d8571a954cb5fccc53e104540b9a30 diff --git a/php_http_buffer.c b/php_http_buffer.c index 41fd48a..e24a4e1 100644 --- a/php_http_buffer.c +++ b/php_http_buffer.c @@ -1,7 +1,16 @@ - -/* $Id: php_http_buffer_t.c 211942 2006-04-24 17:17:09Z mike $ */ - -#include "php.h" +/* + +--------------------------------------------------------------------+ + | PECL :: http | + +--------------------------------------------------------------------+ + | Redistribution and use in source and binary forms, with or without | + | modification, are permitted provided that the conditions mentioned | + | in the accompanying LICENSE file are met. | + +--------------------------------------------------------------------+ + | Copyright (c) 2004-2014, Michael Wallner | + +--------------------------------------------------------------------+ +*/ + +#include #include "php_http_buffer.h" PHP_HTTP_BUFFER_API php_http_buffer_t *php_http_buffer_init_ex(php_http_buffer_t *buf, size_t chunk_size, int flags) @@ -36,7 +45,7 @@ PHP_HTTP_BUFFER_API size_t php_http_buffer_resize_ex(php_http_buffer_t *buf, siz { char *ptr = NULL; #if 0 - fprintf(stderr, "RESIZE: len=%lu, size=%lu, used=%lu, free=%lu\n", len, buf->size, buf->used, buf->free); + fprintf(stderr, "RESIZE: len=%lu, size=%lu, used=%lu, free=%lu, total=%lu\n", len, buf->size, buf->used, buf->free, buf->free+buf->used); #endif if (buf->free < len) { size_t size = override_size ? override_size : buf->size; @@ -63,6 +72,16 @@ PHP_HTTP_BUFFER_API size_t php_http_buffer_resize_ex(php_http_buffer_t *buf, siz return 0; } +PHP_HTTP_BUFFER_API char *php_http_buffer_account(php_http_buffer_t *buf, size_t to_account) +{ + assert(to_account <= buf->free); + + buf->free -= to_account; + buf->used += to_account; + + return buf->data + buf->used; +} + PHP_HTTP_BUFFER_API size_t php_http_buffer_shrink(php_http_buffer_t *buf) { /* avoid another realloc on fixation */ @@ -81,7 +100,7 @@ PHP_HTTP_BUFFER_API size_t php_http_buffer_shrink(php_http_buffer_t *buf) PHP_HTTP_BUFFER_API size_t php_http_buffer_append(php_http_buffer_t *buf, const char *append, size_t append_len) { - if (PHP_HTTP_BUFFER_NOMEM == php_http_buffer_resize(buf, append_len)) { + if (buf->free < append_len && PHP_HTTP_BUFFER_NOMEM == php_http_buffer_resize(buf, append_len)) { return PHP_HTTP_BUFFER_NOMEM; } memcpy(buf->data + buf->used, append, append_len); @@ -109,68 +128,6 @@ PHP_HTTP_BUFFER_API size_t php_http_buffer_appendf(php_http_buffer_t *buf, const return append_len; } -PHP_HTTP_BUFFER_API size_t php_http_buffer_insert(php_http_buffer_t *buf, const char *insert, size_t insert_len, size_t offset) -{ - if (PHP_HTTP_BUFFER_NOMEM == php_http_buffer_resize(buf, insert_len)) { - return PHP_HTTP_BUFFER_NOMEM; - } - memmove(buf->data + offset + insert_len, buf->data + offset, insert_len); - memcpy(buf->data + offset, insert, insert_len); - buf->used += insert_len; - buf->free -= insert_len; - return insert_len; -} - -PHP_HTTP_BUFFER_API size_t php_http_buffer_insertf(php_http_buffer_t *buf, size_t offset, const char *format, ...) -{ - va_list argv; - char *insert; - size_t insert_len, alloc; - - va_start(argv, format); - insert_len = vspprintf(&insert, 0, format, argv); - va_end(argv); - - alloc = php_http_buffer_insert(buf, insert, insert_len, offset); - efree(insert); - - if (PHP_HTTP_BUFFER_NOMEM == alloc) { - return PHP_HTTP_BUFFER_NOMEM; - } - return insert_len; -} - -PHP_HTTP_BUFFER_API size_t php_http_buffer_prepend(php_http_buffer_t *buf, const char *prepend, size_t prepend_len) -{ - if (PHP_HTTP_BUFFER_NOMEM == php_http_buffer_resize(buf, prepend_len)) { - return PHP_HTTP_BUFFER_NOMEM; - } - memmove(buf->data + prepend_len, buf->data, buf->used); - memcpy(buf->data, prepend, prepend_len); - buf->used += prepend_len; - buf->free -= prepend_len; - return prepend_len; -} - -PHP_HTTP_BUFFER_API size_t php_http_buffer_prependf(php_http_buffer_t *buf, const char *format, ...) -{ - va_list argv; - char *prepend; - size_t prepend_len, alloc; - - va_start(argv, format); - prepend_len = vspprintf(&prepend, 0, format, argv); - va_end(argv); - - alloc = php_http_buffer_prepend(buf, prepend, prepend_len); - efree(prepend); - - if (PHP_HTTP_BUFFER_NOMEM == alloc) { - return PHP_HTTP_BUFFER_NOMEM; - } - return prepend_len; -} - PHP_HTTP_BUFFER_API char *php_http_buffer_data(const php_http_buffer_t *buf, char **into, size_t *len) { char *copy = ecalloc(1, buf->used + 1); @@ -184,22 +141,6 @@ PHP_HTTP_BUFFER_API char *php_http_buffer_data(const php_http_buffer_t *buf, cha return copy; } -PHP_HTTP_BUFFER_API php_http_buffer_t *php_http_buffer_copy(const php_http_buffer_t *from, php_http_buffer_t *to) -{ - int free_to = !to; - - to = php_http_buffer_clone(from, to); - - if (PHP_HTTP_BUFFER_NOMEM == php_http_buffer_append(to, from->data, from->used)) { - if (free_to) { - php_http_buffer_free(&to); - } else { - php_http_buffer_dtor(to); - } - } - return to; -} - PHP_HTTP_BUFFER_API size_t php_http_buffer_cut(php_http_buffer_t *buf, size_t offset, size_t length) { if (offset > buf->used) { @@ -214,93 +155,15 @@ PHP_HTTP_BUFFER_API size_t php_http_buffer_cut(php_http_buffer_t *buf, size_t of return length; } -PHP_HTTP_BUFFER_API php_http_buffer_t *php_http_buffer_sub(const php_http_buffer_t *buf, size_t offset, size_t length) -{ - if (offset >= buf->used) { - return NULL; - } else { - size_t need = 1 + ((length + offset) > buf->used ? (buf->used - offset) : (length - offset)); - php_http_buffer_t *sub = php_http_buffer_init_ex(NULL, need, PHP_HTTP_BUFFER_INIT_PREALLOC | (buf->pmem ? PHP_HTTP_BUFFER_INIT_PERSISTENT:0)); - if (sub) { - if (PHP_HTTP_BUFFER_NOMEM == php_http_buffer_append(sub, buf->data + offset, need)) { - php_http_buffer_free(&sub); - } else { - sub->size = buf->size; - } - } - return sub; - } -} - -PHP_HTTP_BUFFER_API php_http_buffer_t *php_http_buffer_right(const php_http_buffer_t *buf, size_t length) -{ - if (length < buf->used) { - return php_http_buffer_sub(buf, buf->used - length, length); - } else { - return php_http_buffer_sub(buf, 0, buf->used); - } -} - - -PHP_HTTP_BUFFER_API php_http_buffer_t *php_http_buffer_merge_va(php_http_buffer_t *buf, unsigned argc, va_list argv) -{ - unsigned i = 0; - buf = php_http_buffer_init(buf); - - if (buf) { - while (argc > i++) { - php_http_buffer_free_t f = va_arg(argv, php_http_buffer_free_t); - php_http_buffer_t *current = va_arg(argv, php_http_buffer_t *); - php_http_buffer_append(buf, current->data, current->used); - FREE_PHP_HTTP_BUFFER(f, current); - } - } - - return buf; -} - -PHP_HTTP_BUFFER_API php_http_buffer_t *php_http_buffer_merge_ex(php_http_buffer_t *buf, unsigned argc, ...) -{ - va_list argv; - php_http_buffer_t *ret; - - va_start(argv, argc); - ret = php_http_buffer_merge_va(buf, argc, argv); - va_end(argv); - return ret; -} - -PHP_HTTP_BUFFER_API php_http_buffer_t *php_http_buffer_merge(unsigned argc, ...) -{ - va_list argv; - php_http_buffer_t *ret; - - va_start(argv, argc); - ret = php_http_buffer_merge_va(NULL, argc, argv); - va_end(argv); - return ret; -} - PHP_HTTP_BUFFER_API php_http_buffer_t *php_http_buffer_fix(php_http_buffer_t *buf) { - if (PHP_HTTP_BUFFER_NOMEM == php_http_buffer_resize_ex(buf, 1, 1, 0)) { + if (buf->free < 1 && PHP_HTTP_BUFFER_NOMEM == php_http_buffer_resize_ex(buf, 1, 1, 0)) { return NULL; } buf->data[buf->used] = '\0'; return buf; } -PHP_HTTP_BUFFER_API int php_http_buffer_cmp(php_http_buffer_t *left, php_http_buffer_t *right) -{ - if (left->used > right->used) { - return -1; - } else if (right->used > left->used) { - return 1; - } else { - return memcmp(left->data, right->data, left->used); - } -} - PHP_HTTP_BUFFER_API void php_http_buffer_reset(php_http_buffer_t *buf) { buf->free += buf->used; @@ -347,7 +210,7 @@ PHP_HTTP_BUFFER_API size_t php_http_buffer_chunk_buffer(php_http_buffer_t **s, c return chunk_size; } - if (storage->used >= (chunk_size = storage->size >> 1)) { + if (storage->used >= chunk_size) { *chunk = estrndup(storage->data, chunk_size); php_http_buffer_cut(storage, 0, chunk_size); return chunk_size; @@ -356,13 +219,17 @@ PHP_HTTP_BUFFER_API size_t php_http_buffer_chunk_buffer(php_http_buffer_t **s, c return 0; } -PHP_HTTP_BUFFER_API void php_http_buffer_chunked_output(php_http_buffer_t **s, const char *data, size_t data_len, size_t chunk_len, php_http_buffer_pass_func_t passout, void *opaque TSRMLS_DC) +PHP_HTTP_BUFFER_API size_t php_http_buffer_chunked_output(php_http_buffer_t **s, const char *data, size_t data_len, size_t chunk_len, php_http_buffer_pass_func_t passout, void *opaque TSRMLS_DC) { char *chunk = NULL; - size_t got = 0; - + size_t passed = 0, got = 0; + while ((got = php_http_buffer_chunk_buffer(s, data, data_len, &chunk, chunk_len))) { - passout(opaque, chunk, got TSRMLS_CC); + if (PHP_HTTP_BUFFER_PASS0 == passout(opaque, chunk, got TSRMLS_CC)) { + PTR_SET(chunk, NULL); + return PHP_HTTP_BUFFER_PASS0; + } + ++passed; if (!chunk_len) { /* we already got the last chunk, and freed all resources */ @@ -370,27 +237,28 @@ PHP_HTTP_BUFFER_API void php_http_buffer_chunked_output(php_http_buffer_t **s, c } data = NULL; data_len = 0; - STR_SET(chunk, NULL); + PTR_SET(chunk, NULL); } - STR_FREE(chunk); + PTR_FREE(chunk); + return passed; } -PHP_HTTP_BUFFER_API ssize_t php_http_buffer_passthru(php_http_buffer_t *s, size_t chunk_size, php_http_buffer_pass_func_t passin, void *passin_arg, php_http_buffer_pass_func_t passon, void *passon_arg TSRMLS_DC) +PHP_HTTP_BUFFER_API ssize_t php_http_buffer_passthru(php_http_buffer_t **s, size_t chunk_size, php_http_buffer_pass_func_t passin, void *passin_arg, php_http_buffer_pass_func_t passon, void *passon_arg TSRMLS_DC) { - size_t passed_on = 0, passed_in = php_http_buffer_chunked_input(&s, chunk_size, passin, passin_arg TSRMLS_CC); + size_t passed_on = 0, passed_in = php_http_buffer_chunked_input(s, chunk_size, passin, passin_arg TSRMLS_CC); if (passed_in == PHP_HTTP_BUFFER_PASS0) { return passed_in; } - if (passed_in) { - passed_on = passon(passon_arg, s->data, passed_in TSRMLS_CC); + if (passed_in || (*s)->used) { + passed_on = passon(passon_arg, (*s)->data, (*s)->used TSRMLS_CC); if (passed_on == PHP_HTTP_BUFFER_PASS0) { return passed_on; } if (passed_on) { - php_http_buffer_cut(s, 0, passed_on); + php_http_buffer_cut(*s, 0, passed_on); } } @@ -420,6 +288,166 @@ PHP_HTTP_BUFFER_API size_t php_http_buffer_chunked_input(php_http_buffer_t **s, return passed; } +#ifdef PHP_HTTP_BUFFER_EXTENDED + +PHP_HTTP_BUFFER_API int php_http_buffer_cmp(php_http_buffer_t *left, php_http_buffer_t *right) +{ + if (left->used > right->used) { + return -1; + } else if (right->used > left->used) { + return 1; + } else { + return memcmp(left->data, right->data, left->used); + } +} + +PHP_HTTP_BUFFER_API php_http_buffer_t *php_http_buffer_copy(const php_http_buffer_t *from, php_http_buffer_t *to) +{ + int free_to = !to; + + to = php_http_buffer_clone(from, to); + + if (PHP_HTTP_BUFFER_NOMEM == php_http_buffer_append(to, from->data, from->used)) { + if (free_to) { + php_http_buffer_free(&to); + } else { + php_http_buffer_dtor(to); + } + } + return to; +} + +PHP_HTTP_BUFFER_API size_t php_http_buffer_insert(php_http_buffer_t *buf, const char *insert, size_t insert_len, size_t offset) +{ + if (PHP_HTTP_BUFFER_NOMEM == php_http_buffer_resize(buf, insert_len)) { + return PHP_HTTP_BUFFER_NOMEM; + } + memmove(buf->data + offset + insert_len, buf->data + offset, insert_len); + memcpy(buf->data + offset, insert, insert_len); + buf->used += insert_len; + buf->free -= insert_len; + return insert_len; +} + +PHP_HTTP_BUFFER_API size_t php_http_buffer_insertf(php_http_buffer_t *buf, size_t offset, const char *format, ...) +{ + va_list argv; + char *insert; + size_t insert_len, alloc; + + va_start(argv, format); + insert_len = vspprintf(&insert, 0, format, argv); + va_end(argv); + + alloc = php_http_buffer_insert(buf, insert, insert_len, offset); + efree(insert); + + if (PHP_HTTP_BUFFER_NOMEM == alloc) { + return PHP_HTTP_BUFFER_NOMEM; + } + return insert_len; +} + +PHP_HTTP_BUFFER_API size_t php_http_buffer_prepend(php_http_buffer_t *buf, const char *prepend, size_t prepend_len) +{ + if (PHP_HTTP_BUFFER_NOMEM == php_http_buffer_resize(buf, prepend_len)) { + return PHP_HTTP_BUFFER_NOMEM; + } + memmove(buf->data + prepend_len, buf->data, buf->used); + memcpy(buf->data, prepend, prepend_len); + buf->used += prepend_len; + buf->free -= prepend_len; + return prepend_len; +} + +PHP_HTTP_BUFFER_API size_t php_http_buffer_prependf(php_http_buffer_t *buf, const char *format, ...) +{ + va_list argv; + char *prepend; + size_t prepend_len, alloc; + + va_start(argv, format); + prepend_len = vspprintf(&prepend, 0, format, argv); + va_end(argv); + + alloc = php_http_buffer_prepend(buf, prepend, prepend_len); + efree(prepend); + + if (PHP_HTTP_BUFFER_NOMEM == alloc) { + return PHP_HTTP_BUFFER_NOMEM; + } + return prepend_len; +} + +PHP_HTTP_BUFFER_API php_http_buffer_t *php_http_buffer_sub(const php_http_buffer_t *buf, size_t offset, size_t length) +{ + if (offset >= buf->used) { + return NULL; + } else { + size_t need = 1 + ((length + offset) > buf->used ? (buf->used - offset) : (length - offset)); + php_http_buffer_t *sub = php_http_buffer_init_ex(NULL, need, PHP_HTTP_BUFFER_INIT_PREALLOC | (buf->pmem ? PHP_HTTP_BUFFER_INIT_PERSISTENT:0)); + if (sub) { + if (PHP_HTTP_BUFFER_NOMEM == php_http_buffer_append(sub, buf->data + offset, need)) { + php_http_buffer_free(&sub); + } else { + sub->size = buf->size; + } + } + return sub; + } +} + +PHP_HTTP_BUFFER_API php_http_buffer_t *php_http_buffer_right(const php_http_buffer_t *buf, size_t length) +{ + if (length < buf->used) { + return php_http_buffer_sub(buf, buf->used - length, length); + } else { + return php_http_buffer_sub(buf, 0, buf->used); + } +} + + +PHP_HTTP_BUFFER_API php_http_buffer_t *php_http_buffer_merge_va(php_http_buffer_t *buf, unsigned argc, va_list argv) +{ + unsigned i = 0; + buf = php_http_buffer_init(buf); + + if (buf) { + while (argc > i++) { + php_http_buffer_free_t f = va_arg(argv, php_http_buffer_free_t); + php_http_buffer_t *current = va_arg(argv, php_http_buffer_t *); + php_http_buffer_append(buf, current->data, current->used); + FREE_PHP_HTTP_BUFFER(f, current); + } + } + + return buf; +} + +PHP_HTTP_BUFFER_API php_http_buffer_t *php_http_buffer_merge_ex(php_http_buffer_t *buf, unsigned argc, ...) +{ + va_list argv; + php_http_buffer_t *ret; + + va_start(argv, argc); + ret = php_http_buffer_merge_va(buf, argc, argv); + va_end(argv); + return ret; +} + +PHP_HTTP_BUFFER_API php_http_buffer_t *php_http_buffer_merge(unsigned argc, ...) +{ + va_list argv; + php_http_buffer_t *ret; + + va_start(argv, argc); + ret = php_http_buffer_merge_va(NULL, argc, argv); + va_end(argv); + return ret; +} + +#endif + /* * Local variables: * tab-width: 4