2 /* $Id: php_http_buffer_t.c 211942 2006-04-24 17:17:09Z mike $ */
5 #include "php_http_buffer.h"
7 PHP_HTTP_BUFFER_API php_http_buffer_t
*php_http_buffer_init_ex(php_http_buffer_t
*buf
, size_t chunk_size
, int flags
)
10 buf
= pemalloc(sizeof(*buf
), flags
& PHP_HTTP_BUFFER_INIT_PERSISTENT
);
14 buf
->size
= (chunk_size
) ? chunk_size
: PHP_HTTP_BUFFER_DEFAULT_SIZE
;
15 buf
->pmem
= (flags
& PHP_HTTP_BUFFER_INIT_PERSISTENT
) ? 1 : 0;
16 buf
->data
= (flags
& PHP_HTTP_BUFFER_INIT_PREALLOC
) ? pemalloc(buf
->size
, buf
->pmem
) : NULL
;
17 buf
->free
= (flags
& PHP_HTTP_BUFFER_INIT_PREALLOC
) ? buf
->size
: 0;
24 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
)
26 if ((buf
= php_http_buffer_init(buf
))) {
27 if (PHP_HTTP_BUFFER_NOMEM
== php_http_buffer_append(buf
, string
, length
)) {
28 pefree(buf
, buf
->pmem
);
35 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
)
39 fprintf(stderr
, "RESIZE: len=%lu, size=%lu, used=%lu, free=%lu\n", len
, buf
->size
, buf
->used
, buf
->free
);
41 if (buf
->free
< len
) {
42 size_t size
= override_size
? override_size
: buf
->size
;
44 while ((size
+ buf
->free
) < len
) {
49 ptr
= perealloc_recoverable(buf
->data
, buf
->used
+ buf
->free
+ size
, buf
->pmem
);
51 ptr
= perealloc(buf
->data
, buf
->used
+ buf
->free
+ size
, buf
->pmem
);
57 return PHP_HTTP_BUFFER_NOMEM
;
66 PHP_HTTP_BUFFER_API
size_t php_http_buffer_shrink(php_http_buffer_t
*buf
)
68 /* avoid another realloc on fixation */
70 char *ptr
= perealloc(buf
->data
, buf
->used
+ 1, buf
->pmem
);
75 return PHP_HTTP_BUFFER_NOMEM
;
82 PHP_HTTP_BUFFER_API
size_t php_http_buffer_append(php_http_buffer_t
*buf
, const char *append
, size_t append_len
)
84 if (PHP_HTTP_BUFFER_NOMEM
== php_http_buffer_resize(buf
, append_len
)) {
85 return PHP_HTTP_BUFFER_NOMEM
;
87 memcpy(buf
->data
+ buf
->used
, append
, append_len
);
88 buf
->used
+= append_len
;
89 buf
->free
-= append_len
;
93 PHP_HTTP_BUFFER_API
size_t php_http_buffer_appendf(php_http_buffer_t
*buf
, const char *format
, ...)
97 size_t append_len
, alloc
;
99 va_start(argv
, format
);
100 append_len
= vspprintf(&append
, 0, format
, argv
);
103 alloc
= php_http_buffer_append(buf
, append
, append_len
);
106 if (PHP_HTTP_BUFFER_NOMEM
== alloc
) {
107 return PHP_HTTP_BUFFER_NOMEM
;
112 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
)
114 if (PHP_HTTP_BUFFER_NOMEM
== php_http_buffer_resize(buf
, insert_len
)) {
115 return PHP_HTTP_BUFFER_NOMEM
;
117 memmove(buf
->data
+ offset
+ insert_len
, buf
->data
+ offset
, insert_len
);
118 memcpy(buf
->data
+ offset
, insert
, insert_len
);
119 buf
->used
+= insert_len
;
120 buf
->free
-= insert_len
;
124 PHP_HTTP_BUFFER_API
size_t php_http_buffer_insertf(php_http_buffer_t
*buf
, size_t offset
, const char *format
, ...)
128 size_t insert_len
, alloc
;
130 va_start(argv
, format
);
131 insert_len
= vspprintf(&insert
, 0, format
, argv
);
134 alloc
= php_http_buffer_insert(buf
, insert
, insert_len
, offset
);
137 if (PHP_HTTP_BUFFER_NOMEM
== alloc
) {
138 return PHP_HTTP_BUFFER_NOMEM
;
143 PHP_HTTP_BUFFER_API
size_t php_http_buffer_prepend(php_http_buffer_t
*buf
, const char *prepend
, size_t prepend_len
)
145 if (PHP_HTTP_BUFFER_NOMEM
== php_http_buffer_resize(buf
, prepend_len
)) {
146 return PHP_HTTP_BUFFER_NOMEM
;
148 memmove(buf
->data
+ prepend_len
, buf
->data
, buf
->used
);
149 memcpy(buf
->data
, prepend
, prepend_len
);
150 buf
->used
+= prepend_len
;
151 buf
->free
-= prepend_len
;
155 PHP_HTTP_BUFFER_API
size_t php_http_buffer_prependf(php_http_buffer_t
*buf
, const char *format
, ...)
159 size_t prepend_len
, alloc
;
161 va_start(argv
, format
);
162 prepend_len
= vspprintf(&prepend
, 0, format
, argv
);
165 alloc
= php_http_buffer_prepend(buf
, prepend
, prepend_len
);
168 if (PHP_HTTP_BUFFER_NOMEM
== alloc
) {
169 return PHP_HTTP_BUFFER_NOMEM
;
174 PHP_HTTP_BUFFER_API
char *php_http_buffer_data(const php_http_buffer_t
*buf
, char **into
, size_t *len
)
176 char *copy
= ecalloc(1, buf
->used
+ 1);
177 memcpy(copy
, buf
->data
, buf
->used
);
187 PHP_HTTP_BUFFER_API php_http_buffer_t
*php_http_buffer_copy(const php_http_buffer_t
*from
, php_http_buffer_t
*to
)
191 to
= php_http_buffer_clone(from
, to
);
193 if (PHP_HTTP_BUFFER_NOMEM
== php_http_buffer_append(to
, from
->data
, from
->used
)) {
195 php_http_buffer_free(&to
);
197 php_http_buffer_dtor(to
);
203 PHP_HTTP_BUFFER_API
size_t php_http_buffer_cut(php_http_buffer_t
*buf
, size_t offset
, size_t length
)
205 if (offset
> buf
->used
) {
208 if (offset
+ length
> buf
->used
) {
209 length
= buf
->used
- offset
;
211 memmove(buf
->data
+ offset
, buf
->data
+ offset
+ length
, buf
->used
- length
- offset
);
217 PHP_HTTP_BUFFER_API php_http_buffer_t
*php_http_buffer_sub(const php_http_buffer_t
*buf
, size_t offset
, size_t length
)
219 if (offset
>= buf
->used
) {
222 size_t need
= 1 + ((length
+ offset
) > buf
->used
? (buf
->used
- offset
) : (length
- offset
));
223 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));
225 if (PHP_HTTP_BUFFER_NOMEM
== php_http_buffer_append(sub
, buf
->data
+ offset
, need
)) {
226 php_http_buffer_free(&sub
);
228 sub
->size
= buf
->size
;
235 PHP_HTTP_BUFFER_API php_http_buffer_t
*php_http_buffer_right(const php_http_buffer_t
*buf
, size_t length
)
237 if (length
< buf
->used
) {
238 return php_http_buffer_sub(buf
, buf
->used
- length
, length
);
240 return php_http_buffer_sub(buf
, 0, buf
->used
);
245 PHP_HTTP_BUFFER_API php_http_buffer_t
*php_http_buffer_merge_va(php_http_buffer_t
*buf
, unsigned argc
, va_list argv
)
248 buf
= php_http_buffer_init(buf
);
252 php_http_buffer_free_t f
= va_arg(argv
, php_http_buffer_free_t
);
253 php_http_buffer_t
*current
= va_arg(argv
, php_http_buffer_t
*);
254 php_http_buffer_append(buf
, current
->data
, current
->used
);
255 FREE_PHP_HTTP_BUFFER(f
, current
);
262 PHP_HTTP_BUFFER_API php_http_buffer_t
*php_http_buffer_merge_ex(php_http_buffer_t
*buf
, unsigned argc
, ...)
265 php_http_buffer_t
*ret
;
267 va_start(argv
, argc
);
268 ret
= php_http_buffer_merge_va(buf
, argc
, argv
);
273 PHP_HTTP_BUFFER_API php_http_buffer_t
*php_http_buffer_merge(unsigned argc
, ...)
276 php_http_buffer_t
*ret
;
278 va_start(argv
, argc
);
279 ret
= php_http_buffer_merge_va(NULL
, argc
, argv
);
284 PHP_HTTP_BUFFER_API php_http_buffer_t
*php_http_buffer_fix(php_http_buffer_t
*buf
)
286 if (PHP_HTTP_BUFFER_NOMEM
== php_http_buffer_resize_ex(buf
, 1, 1, 0)) {
289 buf
->data
[buf
->used
] = '\0';
293 PHP_HTTP_BUFFER_API
int php_http_buffer_cmp(php_http_buffer_t
*left
, php_http_buffer_t
*right
)
295 if (left
->used
> right
->used
) {
297 } else if (right
->used
> left
->used
) {
300 return memcmp(left
->data
, right
->data
, left
->used
);
304 PHP_HTTP_BUFFER_API
void php_http_buffer_reset(php_http_buffer_t
*buf
)
306 buf
->free
+= buf
->used
;
310 PHP_HTTP_BUFFER_API
void php_http_buffer_dtor(php_http_buffer_t
*buf
)
313 pefree(buf
->data
, buf
->pmem
);
320 PHP_HTTP_BUFFER_API
void php_http_buffer_free(php_http_buffer_t
**buf
)
323 php_http_buffer_dtor(*buf
);
324 pefree(*buf
, (*buf
)->pmem
);
329 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
)
331 php_http_buffer_t
*storage
;
336 *s
= php_http_buffer_init_ex(NULL
, chunk_size
<< 1, chunk_size
? PHP_HTTP_BUFFER_INIT_PREALLOC
: 0);
341 php_http_buffer_append(storage
, data
, data_len
);
345 php_http_buffer_data(storage
, chunk
, &chunk_size
);
346 php_http_buffer_free(s
);
350 if (storage
->used
>= (chunk_size
= storage
->size
>> 1)) {
351 *chunk
= estrndup(storage
->data
, chunk_size
);
352 php_http_buffer_cut(storage
, 0, chunk_size
);
359 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
)
364 while ((got
= php_http_buffer_chunk_buffer(s
, data
, data_len
, &chunk
, chunk_len
))) {
365 passout(opaque
, chunk
, got TSRMLS_CC
);
367 /* we already got the last chunk,
368 and freed all resources */
373 STR_SET(chunk
, NULL
);
378 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
)
380 size_t passed_on
= 0, passed_in
= php_http_buffer_chunked_input(&s
, chunk_size
, passin
, passin_arg TSRMLS_CC
);
382 if (passed_in
== PHP_HTTP_BUFFER_PASS0
) {
386 passed_on
= passon(passon_arg
, s
->data
, passed_in TSRMLS_CC
);
388 if (passed_on
== PHP_HTTP_BUFFER_PASS0
) {
393 php_http_buffer_cut(s
, 0, passed_on
);
397 return passed_on
- passed_in
;
400 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
)
402 php_http_buffer_t
*str
;
406 *s
= php_http_buffer_init_ex(NULL
, chunk_size
, chunk_size
? PHP_HTTP_BUFFER_INIT_PREALLOC
: 0);
410 php_http_buffer_resize(str
, chunk_size
);
411 passed
= passin(opaque
, str
->data
+ str
->used
, chunk_size TSRMLS_CC
);
413 if (passed
!= PHP_HTTP_BUFFER_PASS0
) {
418 php_http_buffer_fix(str
);
428 * vim600: sw=4 ts=4 fdm=marker