- fix PHP4 build (has no only_exceptions INI setting
[m6w6/ext-http] / phpstr / phpstr.c
1
2 /* $Id$ */
3
4 #include "php.h"
5 #include "phpstr.h"
6
7 #ifndef PHPSTR_DEFAULT_SIZE
8 #define PHPSTR_DEFAULT_SIZE 256
9 #endif
10
11 PHPSTR_API phpstr *phpstr_init_ex(phpstr *buf, size_t chunk_size, zend_bool pre_alloc)
12 {
13 if (!buf) {
14 buf = emalloc(sizeof(phpstr));
15 }
16
17 buf->size = chunk_size > 0 ? chunk_size : PHPSTR_DEFAULT_SIZE;
18 buf->data = pre_alloc ? emalloc(buf->size) : NULL;
19 buf->free = pre_alloc ? buf->size : 0;
20 buf->used = 0;
21
22 return buf;
23 }
24
25 PHPSTR_API phpstr *phpstr_from_string_ex(phpstr *buf, const char *string, size_t length)
26 {
27 buf = phpstr_init(buf);
28 phpstr_append(buf, string, length);
29 return buf;
30 }
31
32 PHPSTR_API void phpstr_resize_ex(phpstr *buf, size_t len, size_t override_size)
33 {
34 if (buf->free < len) {
35 size_t size = override_size ? override_size : buf->size;
36 while ((size + buf->free) < len) {
37 size *= 2;
38 }
39 if (buf->data) {
40 buf->data = erealloc(buf->data, buf->used + buf->free + size);
41 } else {
42 buf->data = emalloc(size);
43 }
44 buf->free += size;
45 }
46 }
47
48 PHPSTR_API size_t phpstr_append(phpstr *buf, const char *append, size_t append_len)
49 {
50 phpstr_resize(buf, append_len);
51 memcpy(buf->data + buf->used, append, append_len);
52 buf->used += append_len;
53 buf->free -= append_len;
54 return append_len;
55 }
56
57 PHPSTR_API size_t phpstr_appendf(phpstr *buf, const char *format, ...)
58 {
59 va_list argv;
60 char *append;
61 size_t append_len;
62
63 va_start(argv, format);
64 append_len = vspprintf(&append, 0, format, argv);
65 va_end(argv);
66
67 phpstr_append(buf, append, append_len);
68 efree(append);
69
70 return append_len;
71 }
72
73 PHPSTR_API size_t phpstr_insert(phpstr *buf, const char *insert, size_t insert_len, size_t offset)
74 {
75 phpstr_resize(buf, insert_len);
76 memmove(buf->data + offset + insert_len, buf->data + offset, insert_len);
77 memcpy(buf->data + offset, insert, insert_len);
78 buf->used += insert_len;
79 buf->free -= insert_len;
80 return insert_len;
81 }
82
83 PHPSTR_API size_t phpstr_insertf(phpstr *buf, size_t offset, const char *format, ...)
84 {
85 va_list argv;
86 char *insert;
87 size_t insert_len;
88
89 va_start(argv, format);
90 insert_len = vspprintf(&insert, 0, format, argv);
91 va_end(argv);
92
93 phpstr_insert(buf, insert, insert_len, offset);
94 efree(insert);
95
96 return insert_len;
97 }
98
99 PHPSTR_API size_t phpstr_prepend(phpstr *buf, const char *prepend, size_t prepend_len)
100 {
101 phpstr_resize(buf, prepend_len);
102 memmove(buf->data + prepend_len, buf->data, buf->used);
103 memcpy(buf->data, prepend, prepend_len);
104 buf->used += prepend_len;
105 buf->free -= prepend_len;
106 return prepend_len;
107 }
108
109 PHPSTR_API size_t phpstr_prependf(phpstr *buf, const char *format, ...)
110 {
111 va_list argv;
112 char *prepend;
113 size_t prepend_len;
114
115 va_start(argv, format);
116 prepend_len = vspprintf(&prepend, 0, format, argv);
117 va_end(argv);
118
119 phpstr_prepend(buf, prepend, prepend_len);
120 efree(prepend);
121
122 return prepend_len;
123 }
124
125 PHPSTR_API char *phpstr_data(const phpstr *buf, char **into, size_t *len)
126 {
127 char *copy = ecalloc(1, buf->used + 1);
128 memcpy(copy, buf->data, buf->used);
129 if (into) {
130 *into = copy;
131 }
132 if (len) {
133 *len = buf->used;
134 }
135 return copy;
136 }
137
138 PHPSTR_API phpstr *phpstr_dup(const phpstr *buf)
139 {
140 phpstr *dup = phpstr_clone(buf);
141 phpstr_append(dup, buf->data, buf->used);
142 return dup;
143 }
144
145 PHPSTR_API size_t phpstr_cut(phpstr *buf, size_t offset, size_t length)
146 {
147 if (offset >= buf->used) {
148 return 0;
149 }
150 if (offset + length > buf->used) {
151 length = buf->used - offset;
152 }
153 memmove(buf->data + offset, buf->data + offset + length, buf->used - length);
154 buf->used -= length;
155 buf->free += length;
156 return length;
157 }
158
159 PHPSTR_API phpstr *phpstr_sub(const phpstr *buf, size_t offset, size_t length)
160 {
161 if (offset >= buf->used) {
162 return NULL;
163 } else {
164 size_t need = (length + offset) > buf->used ? (buf->used - offset) : (length - offset);
165 phpstr *sub = phpstr_init_ex(NULL, need, 1);
166 phpstr_append(sub, buf->data + offset, need);
167 sub->size = buf->size;
168 return sub;
169 }
170 }
171
172 PHPSTR_API phpstr *phpstr_right(const phpstr *buf, size_t length)
173 {
174 if (length < buf->used) {
175 return phpstr_sub(buf, buf->used - length, length);
176 } else {
177 return phpstr_sub(buf, 0, buf->used);
178 }
179 }
180
181
182 PHPSTR_API phpstr *phpstr_merge_va(phpstr *buf, unsigned argc, va_list argv)
183 {
184 unsigned i = 0;
185 buf = phpstr_init(buf);
186
187 while (argc > i++) {
188 phpstr_free_t f = va_arg(argv, phpstr_free_t);
189 phpstr *current = va_arg(argv, phpstr *);
190 phpstr_append(buf, current->data, current->used);
191 FREE_PHPSTR(f, current);
192 }
193
194 return buf;
195 }
196
197 PHPSTR_API phpstr *phpstr_merge_ex(phpstr *buf, unsigned argc, ...)
198 {
199 va_list argv;
200 phpstr *ret;
201
202 va_start(argv, argc);
203 ret = phpstr_merge_va(buf, argc, argv);
204 va_end(argv);
205 return ret;
206 }
207
208 PHPSTR_API phpstr *phpstr_merge(unsigned argc, ...)
209 {
210 va_list argv;
211 phpstr *ret;
212
213 va_start(argv, argc);
214 ret = phpstr_merge_va(NULL, argc, argv);
215 va_end(argv);
216 return ret;
217 }
218
219 PHPSTR_API void phpstr_fix(phpstr *buf)
220 {
221 phpstr_resize_ex(buf, 1, 1);
222 buf->data[buf->used] = '\0';
223 }
224
225 PHPSTR_API int phpstr_cmp(phpstr *left, phpstr *right)
226 {
227 if (left->used > right->used) {
228 return -1;
229 } else if (right->used > left->used) {
230 return 1;
231 } else {
232 return memcmp(left->data, right->data, left->used);
233 }
234 }
235
236 PHPSTR_API void phpstr_dtor(phpstr *buf)
237 {
238 if (buf->data) {
239 efree(buf->data);
240 buf->data = NULL;
241 }
242 buf->used = 0;
243 buf->free = 0;
244 }
245
246 PHPSTR_API void phpstr_free(phpstr *buf)
247 {
248 if (buf) {
249 phpstr_dtor(buf);
250 efree(buf);
251 }
252 }
253
254 /*
255 * Local variables:
256 * tab-width: 4
257 * c-basic-offset: 4
258 * End:
259 * vim600: sw=4 ts=4 fdm=marker
260 * vim<600: sw=4 ts=4
261 */
262