LCOV - code coverage report
Current view: top level - http - php_http_buffer.c (source / functions) Hit Total Coverage
Test: PHP Code Coverage Lines: 141 153 92.2 %
Date: 2014-11-03 12:21:11 Functions: 17 17 100.0 %
Legend: Lines: hit not hit

          Line data    Source code
       1             : /*
       2             :     +--------------------------------------------------------------------+
       3             :     | PECL :: http                                                       |
       4             :     +--------------------------------------------------------------------+
       5             :     | Redistribution and use in source and binary forms, with or without |
       6             :     | modification, are permitted provided that the conditions mentioned |
       7             :     | in the accompanying LICENSE file are met.                          |
       8             :     +--------------------------------------------------------------------+
       9             :     | Copyright (c) 2004-2014, Michael Wallner <mike@php.net>            |
      10             :     +--------------------------------------------------------------------+
      11             : */
      12             : 
      13             : #include <php.h>
      14             : #include "php_http_buffer.h"
      15             : 
      16         885 : PHP_HTTP_BUFFER_API php_http_buffer_t *php_http_buffer_init_ex(php_http_buffer_t *buf, size_t chunk_size, int flags)
      17             : {
      18         885 :         if (!buf) {
      19         249 :                 buf = pemalloc(sizeof(*buf), flags & PHP_HTTP_BUFFER_INIT_PERSISTENT);
      20             :         }
      21             : 
      22         885 :         if (buf) {
      23         885 :                 buf->size = (chunk_size) ? chunk_size : PHP_HTTP_BUFFER_DEFAULT_SIZE;
      24         885 :                 buf->pmem = (flags & PHP_HTTP_BUFFER_INIT_PERSISTENT) ? 1 : 0;
      25         885 :                 buf->data = (flags & PHP_HTTP_BUFFER_INIT_PREALLOC) ? pemalloc(buf->size, buf->pmem) : NULL;
      26         885 :                 buf->free = (flags & PHP_HTTP_BUFFER_INIT_PREALLOC) ? buf->size : 0;
      27         885 :                 buf->used = 0;
      28             :         }
      29             :         
      30         885 :         return buf;
      31             : }
      32             : 
      33          97 : PHP_HTTP_BUFFER_API php_http_buffer_t *php_http_buffer_from_string_ex(php_http_buffer_t *buf, const char *string, size_t length)
      34             : {
      35          97 :         if ((buf = php_http_buffer_init(buf))) {
      36          97 :                 if (PHP_HTTP_BUFFER_NOMEM == php_http_buffer_append(buf, string, length)) {
      37           0 :                         pefree(buf, buf->pmem);
      38           0 :                         buf = NULL;
      39             :                 }
      40             :         }
      41          97 :         return buf;
      42             : }
      43             : 
      44         738 : PHP_HTTP_BUFFER_API size_t php_http_buffer_resize_ex(php_http_buffer_t *buf, size_t len, size_t override_size, int allow_error)
      45             : {
      46         738 :         char *ptr = NULL;
      47             : #if 0
      48             :         fprintf(stderr, "RESIZE: len=%lu, size=%lu, used=%lu, free=%lu\n", len, buf->size, buf->used, buf->free);
      49             : #endif
      50         738 :         if (buf->free < len) {
      51         683 :                 size_t size = override_size ? override_size : buf->size;
      52             :                 
      53        1559 :                 while ((size + buf->free) < len) {
      54         193 :                         size <<= 1;
      55             :                 }
      56             :                 
      57         683 :                 if (allow_error) {
      58           9 :                         ptr = perealloc_recoverable(buf->data, buf->used + buf->free + size, buf->pmem);
      59             :                 } else {
      60         674 :                         ptr = perealloc(buf->data, buf->used + buf->free + size, buf->pmem);
      61             :                 }
      62             :                 
      63         683 :                 if (ptr) {
      64         683 :                         buf->data = ptr;
      65             :                 } else {
      66           0 :                         return PHP_HTTP_BUFFER_NOMEM;
      67             :                 }
      68             :                 
      69         683 :                 buf->free += size;
      70         683 :                 return size;
      71             :         }
      72          55 :         return 0;
      73             : }
      74             : 
      75         185 : PHP_HTTP_BUFFER_API char *php_http_buffer_account(php_http_buffer_t *buf, size_t to_account)
      76             : {
      77             :         /* it's probably already too late but check anyway */
      78         185 :         if (to_account > buf->free) {
      79           0 :                 return NULL;
      80             :         }
      81             : 
      82         185 :         buf->free -= to_account;
      83         185 :         buf->used += to_account;
      84             : 
      85         185 :         return buf->data + buf->used;
      86             : }
      87             : 
      88         118 : PHP_HTTP_BUFFER_API size_t php_http_buffer_shrink(php_http_buffer_t *buf)
      89             : {
      90             :         /* avoid another realloc on fixation */
      91         118 :         if (buf->free > 1) {
      92         101 :                 char *ptr = perealloc(buf->data, buf->used + 1, buf->pmem);
      93             :                 
      94         101 :                 if (ptr) {
      95         101 :                         buf->data = ptr;
      96             :                 } else {
      97           0 :                         return PHP_HTTP_BUFFER_NOMEM;
      98             :                 }
      99         101 :                 buf->free = 1;
     100             :         }
     101         118 :         return buf->used;
     102             : }
     103             : 
     104        2770 : PHP_HTTP_BUFFER_API size_t php_http_buffer_append(php_http_buffer_t *buf, const char *append, size_t append_len)
     105             : {
     106        2770 :         if (buf->free < append_len && PHP_HTTP_BUFFER_NOMEM == php_http_buffer_resize(buf, append_len)) {
     107           0 :                 return PHP_HTTP_BUFFER_NOMEM;
     108             :         }
     109        2770 :         memcpy(buf->data + buf->used, append, append_len);
     110        2770 :         buf->used += append_len;
     111        2770 :         buf->free -= append_len;
     112        2770 :         return append_len;
     113             : }
     114             : 
     115         437 : PHP_HTTP_BUFFER_API size_t php_http_buffer_appendf(php_http_buffer_t *buf, const char *format, ...)
     116             : {
     117             :         va_list argv;
     118             :         char *append;
     119             :         size_t append_len, alloc;
     120             : 
     121         437 :         va_start(argv, format);
     122         437 :         append_len = vspprintf(&append, 0, format, argv);
     123         437 :         va_end(argv);
     124             : 
     125         437 :         alloc = php_http_buffer_append(buf, append, append_len);
     126         437 :         efree(append);
     127             : 
     128         437 :         if (PHP_HTTP_BUFFER_NOMEM == alloc) {
     129           0 :                 return PHP_HTTP_BUFFER_NOMEM;
     130             :         }
     131         437 :         return append_len;
     132             : }
     133             : 
     134         111 : PHP_HTTP_BUFFER_API char *php_http_buffer_data(const php_http_buffer_t *buf, char **into, size_t *len)
     135             : {
     136         111 :         char *copy = ecalloc(1, buf->used + 1);
     137         111 :         memcpy(copy, buf->data, buf->used);
     138         111 :         if (into) {
     139         111 :                 *into = copy;
     140             :         }
     141         111 :         if (len) {
     142         111 :                 *len = buf->used;
     143             :         }
     144         111 :         return copy;
     145             : }
     146             : 
     147        1945 : PHP_HTTP_BUFFER_API size_t php_http_buffer_cut(php_http_buffer_t *buf, size_t offset, size_t length)
     148             : {
     149        1945 :         if (offset > buf->used) {
     150           0 :                 return 0;
     151             :         }
     152        1945 :         if (offset + length > buf->used) {
     153          16 :                 length = buf->used - offset;
     154             :         }
     155        1945 :         memmove(buf->data + offset, buf->data + offset + length, buf->used - length - offset);
     156        1945 :         buf->used -= length;
     157        1945 :         buf->free += length;
     158        1945 :         return length;
     159             : }
     160             : 
     161        1064 : PHP_HTTP_BUFFER_API php_http_buffer_t *php_http_buffer_fix(php_http_buffer_t *buf)
     162             : {
     163        1064 :         if (buf->free < 1 && PHP_HTTP_BUFFER_NOMEM == php_http_buffer_resize_ex(buf, 1, 1, 0)) {
     164           0 :                 return NULL;
     165             :         }
     166        1064 :         buf->data[buf->used] = '\0';
     167        1064 :         return buf;
     168             : }
     169             : 
     170         331 : PHP_HTTP_BUFFER_API void php_http_buffer_reset(php_http_buffer_t *buf)
     171             : {
     172         331 :         buf->free += buf->used;
     173         331 :         buf->used = 0;
     174         331 : }
     175             : 
     176         691 : PHP_HTTP_BUFFER_API void php_http_buffer_dtor(php_http_buffer_t *buf)
     177             : {
     178         691 :         if (buf->data) {
     179         489 :                 pefree(buf->data, buf->pmem);
     180         489 :                 buf->data = NULL;
     181             :         }
     182         691 :         buf->used = 0;
     183         691 :         buf->free = 0;
     184         691 : }
     185             : 
     186         263 : PHP_HTTP_BUFFER_API void php_http_buffer_free(php_http_buffer_t **buf)
     187             : {
     188         263 :         if (*buf) {
     189         249 :                 php_http_buffer_dtor(*buf);
     190         249 :                 pefree(*buf, (*buf)->pmem);
     191         249 :                 *buf = NULL;
     192             :         }
     193         263 : }
     194             : 
     195          53 : PHP_HTTP_BUFFER_API size_t php_http_buffer_chunk_buffer(php_http_buffer_t **s, const char *data, size_t data_len, char **chunk, size_t chunk_size)
     196             : {
     197             :         php_http_buffer_t *storage;
     198             :         
     199          53 :         *chunk = NULL;
     200             :         
     201          53 :         if (!*s) {
     202           0 :                 *s = php_http_buffer_init_ex(NULL, chunk_size << 1, chunk_size ? PHP_HTTP_BUFFER_INIT_PREALLOC : 0);
     203             :         }
     204          53 :         storage = *s;
     205             :         
     206          53 :         if (data_len) {
     207          36 :                 php_http_buffer_append(storage, data, data_len);
     208             :         }
     209             :         
     210          53 :         if (!chunk_size) {
     211          14 :                 php_http_buffer_data(storage, chunk, &chunk_size);
     212          14 :                 php_http_buffer_free(s);
     213          14 :                 return chunk_size;
     214             :         }
     215             :         
     216          39 :         if (storage->used >= chunk_size) {
     217           7 :                 *chunk = estrndup(storage->data, chunk_size);
     218           7 :                 php_http_buffer_cut(storage, 0, chunk_size);
     219           7 :                 return chunk_size;
     220             :         }
     221             :         
     222          32 :         return 0;
     223             : }
     224             : 
     225          47 : 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)
     226             : {
     227          47 :         char *chunk = NULL;
     228          47 :         size_t passed = 0, got = 0;
     229             : 
     230         100 :         while ((got = php_http_buffer_chunk_buffer(s, data, data_len, &chunk, chunk_len))) {
     231          20 :                 if (PHP_HTTP_BUFFER_PASS0 == passout(opaque, chunk, got TSRMLS_CC)) {
     232           2 :                         STR_SET(chunk, NULL);
     233           2 :                         return PHP_HTTP_BUFFER_PASS0;
     234             :                 }
     235          18 :                 ++passed;
     236          18 :                 if (!chunk_len) {
     237             :                         /*      we already got the last chunk,
     238             :                                 and freed all resources */
     239          12 :                         break;
     240             :                 }
     241           6 :                 data = NULL;
     242           6 :                 data_len = 0;
     243           6 :                 STR_SET(chunk, NULL);
     244             :         }
     245          45 :         STR_FREE(chunk);
     246          45 :         return passed;
     247             : }
     248             : 
     249           1 : 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)
     250             : {
     251           1 :         size_t passed_on = 0, passed_in = php_http_buffer_chunked_input(s, chunk_size, passin, passin_arg TSRMLS_CC);
     252             : 
     253           1 :         if (passed_in == PHP_HTTP_BUFFER_PASS0) {
     254           0 :                 return passed_in;
     255             :         }
     256           1 :         if (passed_in || (*s)->used) {
     257           1 :                 passed_on = passon(passon_arg, (*s)->data, (*s)->used TSRMLS_CC);
     258             : 
     259           1 :                 if (passed_on == PHP_HTTP_BUFFER_PASS0) {
     260           0 :                         return passed_on;
     261             :                 }
     262             : 
     263           1 :                 if (passed_on) {
     264           1 :                         php_http_buffer_cut(*s, 0, passed_on);
     265             :                 }
     266             :         }
     267             : 
     268           1 :         return passed_on - passed_in;
     269             : }
     270             : 
     271           1 : PHP_HTTP_BUFFER_API size_t php_http_buffer_chunked_input(php_http_buffer_t **s, size_t chunk_size, php_http_buffer_pass_func_t passin, void *opaque TSRMLS_DC)
     272             : {
     273             :         php_http_buffer_t *str;
     274             :         size_t passed;
     275             : 
     276           1 :         if (!*s) {
     277           1 :                 *s = php_http_buffer_init_ex(NULL, chunk_size, chunk_size ? PHP_HTTP_BUFFER_INIT_PREALLOC : 0);
     278             :         }
     279           1 :         str = *s;
     280             : 
     281           1 :         php_http_buffer_resize(str, chunk_size);
     282           1 :         passed = passin(opaque, str->data + str->used, chunk_size TSRMLS_CC);
     283             : 
     284           1 :         if (passed != PHP_HTTP_BUFFER_PASS0) {
     285           1 :                 str->used += passed;
     286           1 :                 str->free -= passed;
     287             :         }
     288             : 
     289           1 :         php_http_buffer_fix(str);
     290             : 
     291           1 :         return passed;
     292             : }
     293             : 
     294             : #ifdef PHP_HTTP_BUFFER_EXTENDED
     295             : 
     296             : PHP_HTTP_BUFFER_API int php_http_buffer_cmp(php_http_buffer_t *left, php_http_buffer_t *right)
     297             : {
     298             :         if (left->used > right->used) {
     299             :                 return -1;
     300             :         } else if (right->used > left->used) {
     301             :                 return 1;
     302             :         } else {
     303             :                 return memcmp(left->data, right->data, left->used);
     304             :         }
     305             : }
     306             : 
     307             : PHP_HTTP_BUFFER_API php_http_buffer_t *php_http_buffer_copy(const php_http_buffer_t *from, php_http_buffer_t *to)
     308             : {
     309             :         int free_to = !to;
     310             : 
     311             :         to = php_http_buffer_clone(from, to);
     312             : 
     313             :         if (PHP_HTTP_BUFFER_NOMEM == php_http_buffer_append(to, from->data, from->used)) {
     314             :                 if (free_to) {
     315             :                         php_http_buffer_free(&to);
     316             :                 } else {
     317             :                         php_http_buffer_dtor(to);
     318             :                 }
     319             :         }
     320             :         return to;
     321             : }
     322             : 
     323             : 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)
     324             : {
     325             :         if (PHP_HTTP_BUFFER_NOMEM == php_http_buffer_resize(buf, insert_len)) {
     326             :                 return PHP_HTTP_BUFFER_NOMEM;
     327             :         }
     328             :         memmove(buf->data + offset + insert_len, buf->data + offset, insert_len);
     329             :         memcpy(buf->data + offset, insert, insert_len);
     330             :         buf->used += insert_len;
     331             :         buf->free -= insert_len;
     332             :         return insert_len;
     333             : }
     334             : 
     335             : PHP_HTTP_BUFFER_API size_t php_http_buffer_insertf(php_http_buffer_t *buf, size_t offset, const char *format, ...)
     336             : {
     337             :         va_list argv;
     338             :         char *insert;
     339             :         size_t insert_len, alloc;
     340             : 
     341             :         va_start(argv, format);
     342             :         insert_len = vspprintf(&insert, 0, format, argv);
     343             :         va_end(argv);
     344             : 
     345             :         alloc = php_http_buffer_insert(buf, insert, insert_len, offset);
     346             :         efree(insert);
     347             : 
     348             :         if (PHP_HTTP_BUFFER_NOMEM == alloc) {
     349             :                 return PHP_HTTP_BUFFER_NOMEM;
     350             :         }
     351             :         return insert_len;
     352             : }
     353             : 
     354             : PHP_HTTP_BUFFER_API size_t php_http_buffer_prepend(php_http_buffer_t *buf, const char *prepend, size_t prepend_len)
     355             : {
     356             :         if (PHP_HTTP_BUFFER_NOMEM == php_http_buffer_resize(buf, prepend_len)) {
     357             :                 return PHP_HTTP_BUFFER_NOMEM;
     358             :         }
     359             :         memmove(buf->data + prepend_len, buf->data, buf->used);
     360             :         memcpy(buf->data, prepend, prepend_len);
     361             :         buf->used += prepend_len;
     362             :         buf->free -= prepend_len;
     363             :         return prepend_len;
     364             : }
     365             : 
     366             : PHP_HTTP_BUFFER_API size_t php_http_buffer_prependf(php_http_buffer_t *buf, const char *format, ...)
     367             : {
     368             :         va_list argv;
     369             :         char *prepend;
     370             :         size_t prepend_len, alloc;
     371             : 
     372             :         va_start(argv, format);
     373             :         prepend_len = vspprintf(&prepend, 0, format, argv);
     374             :         va_end(argv);
     375             : 
     376             :         alloc = php_http_buffer_prepend(buf, prepend, prepend_len);
     377             :         efree(prepend);
     378             : 
     379             :         if (PHP_HTTP_BUFFER_NOMEM == alloc) {
     380             :                 return PHP_HTTP_BUFFER_NOMEM;
     381             :         }
     382             :         return prepend_len;
     383             : }
     384             : 
     385             : PHP_HTTP_BUFFER_API php_http_buffer_t *php_http_buffer_sub(const php_http_buffer_t *buf, size_t offset, size_t length)
     386             : {
     387             :         if (offset >= buf->used) {
     388             :                 return NULL;
     389             :         } else {
     390             :                 size_t need = 1 + ((length + offset) > buf->used ? (buf->used - offset) : (length - offset));
     391             :                 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));
     392             :                 if (sub) {
     393             :                         if (PHP_HTTP_BUFFER_NOMEM == php_http_buffer_append(sub, buf->data + offset, need)) {
     394             :                                 php_http_buffer_free(&sub);
     395             :                         } else {
     396             :                                 sub->size = buf->size;
     397             :                         }
     398             :                 }
     399             :                 return sub;
     400             :         }
     401             : }
     402             : 
     403             : PHP_HTTP_BUFFER_API php_http_buffer_t *php_http_buffer_right(const php_http_buffer_t *buf, size_t length)
     404             : {
     405             :         if (length < buf->used) {
     406             :                 return php_http_buffer_sub(buf, buf->used - length, length);
     407             :         } else {
     408             :                 return php_http_buffer_sub(buf, 0, buf->used);
     409             :         }
     410             : }
     411             : 
     412             : 
     413             : PHP_HTTP_BUFFER_API php_http_buffer_t *php_http_buffer_merge_va(php_http_buffer_t *buf, unsigned argc, va_list argv)
     414             : {
     415             :         unsigned i = 0;
     416             :         buf = php_http_buffer_init(buf);
     417             : 
     418             :         if (buf) {
     419             :                 while (argc > i++) {
     420             :                         php_http_buffer_free_t f = va_arg(argv, php_http_buffer_free_t);
     421             :                         php_http_buffer_t *current = va_arg(argv, php_http_buffer_t *);
     422             :                         php_http_buffer_append(buf, current->data, current->used);
     423             :                         FREE_PHP_HTTP_BUFFER(f, current);
     424             :                 }
     425             :         }
     426             : 
     427             :         return buf;
     428             : }
     429             : 
     430             : PHP_HTTP_BUFFER_API php_http_buffer_t *php_http_buffer_merge_ex(php_http_buffer_t *buf, unsigned argc, ...)
     431             : {
     432             :         va_list argv;
     433             :         php_http_buffer_t *ret;
     434             : 
     435             :         va_start(argv, argc);
     436             :         ret = php_http_buffer_merge_va(buf, argc, argv);
     437             :         va_end(argv);
     438             :         return ret;
     439             : }
     440             : 
     441             : PHP_HTTP_BUFFER_API php_http_buffer_t *php_http_buffer_merge(unsigned argc, ...)
     442             : {
     443             :         va_list argv;
     444             :         php_http_buffer_t *ret;
     445             : 
     446             :         va_start(argv, argc);
     447             :         ret = php_http_buffer_merge_va(NULL, argc, argv);
     448             :         va_end(argv);
     449             :         return ret;
     450             : }
     451             : 
     452             : #endif
     453             : 
     454             : /*
     455             :  * Local variables:
     456             :  * tab-width: 4
     457             :  * c-basic-offset: 4
     458             :  * End:
     459             :  * vim600: sw=4 ts=4 fdm=marker
     460             :  * vim<600: sw=4 ts=4
     461             :  */
     462             : 

Generated by: LCOV version 1.11