tinyows 1.2.2
buffer.c
Go to the documentation of this file.
1/*
2 Copyright (c) <2007-2012> <Barbara Philippot - Olivier Courtin>
3
4 Permission is hereby granted, free of charge, to any person obtaining a copy
5 of this software and associated documentation files (the "Software"), to deal
6 in the Software without restriction, including without limitation the rights
7 to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
8 copies of the Software, and to permit persons to whom the Software is
9 furnished to do so, subject to the following conditions:
10
11 The above copyright notice and this permission notice shall be included in
12 all copies or substantial portions of the Software.
13
14 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
17 AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
18 LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
19 FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
20 IN THE SOFTWARE.
21*/
22
23
24#include <stdio.h>
25#include <stdlib.h>
26#include <assert.h>
27#include <ctype.h>
28#include <string.h>
29#include <math.h>
30#include <float.h>
31#include <regex.h>
32
33#include "../ows/ows.h"
34
35
36#ifndef SIZE_MAX
37#define SIZE_MAX (~(size_t)0)
38#endif
39
40/*
41 * Realloc buffer memory space
42 * use an exponential grow size to realloc (less realloc call)
43 */
44static void buffer_realloc(buffer * buf)
45{
46 assert(buf);
47
48 buf->buf = realloc(buf->buf, buf->realloc * sizeof(char));
49 assert(buf->buf);
50
51 buf->size = buf->realloc;
52 buf->realloc *= 4;
53
54 if (buf->realloc >= SIZE_MAX) assert(false);
55}
56
57
58/*
59 * Initialize buffer structure
60 */
62{
63 buffer *buf;
64
65 buf = malloc(sizeof(buffer));
66 assert(buf);
67
68 buf->buf = malloc(BUFFER_SIZE_INIT * sizeof(char));
69 assert(buf->buf);
70
72 buf->realloc = BUFFER_SIZE_INIT * 2;
73 buf->use = 0;
74 buf->buf[0] = '\0';
75
76 return buf;
77}
78
79
80/*
81 * Free a buffer structure and all data in it
82 */
84{
85 assert(buf);
86 assert(buf->buf);
87
88 free(buf->buf);
89 buf->buf = NULL;
90
91 free(buf);
92 buf = NULL;
93}
94
95
96/*
97 * Empty data from a given buffer
98 * (don't release memory, use buffer_free instead)
99 */
101{
102 assert(buf);
103 if (buf->use > 0) buf->buf[0] = '\0';
104 buf->use = 0;
105}
106
107
108/*
109 * Flush all data from a buffer to a stream
110 * Not used *only* to debug purpose ;)
111 */
112void buffer_flush(buffer * buf, FILE * output)
113{
114 assert(buf);
115 assert(output);
116 fprintf(output, "%s", buf->buf);
117}
118
119
120/*
121 * Add a char to the bottom of a buffer
122 */
123void buffer_add(buffer * buf, char c)
124{
125 assert(buf);
126
127 if ((buf->use + 1) >= buf->size) buffer_realloc(buf);
128
129 buf->buf[buf->use] = c;
130 buf->buf[buf->use + 1] = '\0';
131 buf->use++;
132}
133
134
135/*
136 * Return a buffer from a double
137 */
139{
140 buffer *res;
141
142 res = buffer_init();
143 while (res->size < 100) buffer_realloc(res);
144 #ifndef _WIN32
145 snprintf(res->buf, 99, "%f", f);
146 #else
147 _snprintf(res->buf, 99, "%f", f);
148 #endif
149 res->use = strlen(res->buf);
150
151 return res;
152}
153
154
155/*
156 * Add a double to a given buffer
157 */
158void buffer_add_double(buffer * buf, double f)
159{
160 buffer *b;
161
162 assert(buf);
163
164 b = buffer_ftoa(f);
165 buffer_copy(buf, b);
166 buffer_free(b);
167}
168
169
170/*
171 * Add an int to a given buffer
172 */
173void buffer_add_int(buffer * buf, int i)
174{
175 buffer *b;
176
177 assert(buf);
178
179 b = buffer_itoa(i);
180 buffer_copy(buf, b);
181 buffer_free(b);
182}
183
184
185/*
186 * Convert an integer to a buffer (base 10 only)
187 */
189{
190 buffer *res;
191
192 res = buffer_init();
193 /* FIXME use snprintf instead ! */
194 while (res->size < 100) buffer_realloc(res);
195 sprintf(res->buf, "%i", i);
196 res->use = strlen(res->buf);
197
198 return res;
199}
200
201
202buffer *buffer_from_str(const char *str)
203{
204 buffer *b;
205
206 assert(str);
207 b = buffer_init();
208
209 buffer_add_str(b, str);
210 return b;
211}
212
213
214/*
215 * Add a char to the top of a buffer
216 */
217void buffer_add_head(buffer * buf, char c)
218{
219 size_t i;
220
221 assert(buf);
222
223 if ((buf->use + 2) >= buf->size)
224 buffer_realloc(buf);
225
226 if (buf->use > 0)
227 for (i = buf->use; i > 0; i--)
228 buf->buf[i] = buf->buf[i - 1];
229
230 buf->buf[0] = c;
231 buf->buf[buf->use + 1] = '\0';
232 buf->use++;
233}
234
235
236/*
237 * Add a string to the top of a buffer
238 */
239void buffer_add_head_str(buffer * buf, char *str)
240{
241 int i;
242
243 assert(buf);
244 assert(str);
245
246 for (i = strlen(str); i != 0; i--)
247 buffer_add_head(buf, str[i - 1]);
248}
249
250
251/*
252 * Add a string to a buffer
253 */
254void buffer_add_str(buffer * buf, const char *str)
255{
256 assert(buf);
257 assert(str);
258
259 if ((strlen(str) + buf->use) >= buf->size)
260 while ((strlen(str) + buf->use) >= buf->size)
261 buffer_realloc(buf);
262
263 strcat(buf->buf, str);
264 buf->use = buf->use + strlen(str);
265}
266
267
268/*
269 * Add n char from string to a buffer
270 */
271void buffer_add_nstr(buffer * buf, const char *str, size_t n)
272{
273 assert(buf);
274 assert(str);
275 assert(n > 0);
276 assert(n <= strlen(str));
277
278 if ((n + buf->use) >= buf->size)
279 while ((n + buf->use) >= buf->size)
280 buffer_realloc(buf);
281
282 strncat(buf->buf, str, n);
283 buf->use = buf->use + n;
284}
285
286
287/*
288 * Check if a buffer string is the same than another
289 */
290bool buffer_cmp(const buffer * buf, const char *str)
291{
292 size_t i;
293
294 assert(buf);
295 assert(str);
296
297 if (buf->use != strlen(str)) return false;
298
299 for (i = 0; i < buf->use; i++)
300 if (buf->buf[i] != str[i])
301 return false;
302
303 return true;
304}
305
306
307/*
308 * Check if a buffer string is the same than another, on the n first char
309 */
310bool buffer_ncmp(const buffer * buf, const char *str, size_t n)
311{
312 size_t i;
313
314 assert(buf);
315 assert(str);
316
317 if (buf->use < n) return false;
318
319 for (i = 0 ; i < n ; i++)
320 if (buf->buf[i] != str[i])
321 return false;
322
323 return true;
324}
325
326/*
327 * Check if a buffer string is the same than anoter for a specified length
328 * (insensitive case check)
329 */
330bool buffer_case_cmp(const buffer * buf, const char *str)
331{
332 size_t i;
333
334 assert(buf);
335 assert(str);
336
337 if (buf->use != strlen(str)) return false;
338
339 for (i = 0; i < buf->use; i++)
340 if (toupper(buf->buf[i]) != toupper(str[i]))
341 return false;
342
343 return true;
344}
345
346
347/*
348 * Copy data from a buffer to an another
349 */
350void buffer_copy(buffer * dest, const buffer * src)
351{
352 assert(dest);
353 assert(src);
354
355 buffer_add_str(dest, src->buf);
356}
357
358
359/*
360 * Copy the whole buffer struct to an another struct
361 */
363{
364 buffer *b;
365
366 assert(buf);
367 assert(buf->buf);
368
369 b = buffer_init();
370 buffer_copy(b, buf);
371
372 return b;
373}
374
375
376/*
377 * Delete last N chars from a buffer
378 */
379void buffer_pop(buffer * buf, size_t len)
380{
381 assert(buf);
382 assert(len <= buf->use);
383
384 buf->use -= len;
385 buf->buf[buf->use] = '\0';
386}
387
388
389/*
390 * Delete first N chars from a buffer
391 */
392void buffer_shift(buffer * buf, size_t len)
393{
394 size_t i;
395
396 assert(buf);
397 assert(len <= buf->use);
398
399 if (len <= 0) return; /* nothing to do */
400
401 for (i = len; i < buf->use; i++)
402 buf->buf[i - len] = buf->buf[i];
403
404 buf->use -= len;
405 buf->buf[buf->use] = '\0';
406}
407
408
409/*
410 * Replace all occurences of string 'before' inside the buffer by string 'after'
411 */
412buffer *buffer_replace(buffer * buf, char *before, char *after)
413{
414 buffer *new_buf, *rest;
415 size_t length;
416 char *pos;
417
418 assert(before);
419 assert(after);
420 assert(buf);
421
422 if (!strcmp(before, after)) return buf; /* To prevent infinite loop */
423
424 new_buf = buffer_init();
425 buffer_copy(new_buf, buf);
426
427 pos = strstr(new_buf->buf, before); /* Look for first occurence */
428 while (pos) {
429 length = strlen(pos);
430
431 buffer_pop(new_buf, length); /* Copy the first part without occurence */
432 buffer_add_str(new_buf, after); /* Add the string after */
433
434 /* Add the remaining string */
435 rest = buffer_init();
436 buffer_copy(rest, buf);
437 buffer_shift(rest, buf->use - length + strlen(before));
438 buffer_copy(new_buf, rest);
439 buffer_free(rest);
440
441 pos = strstr(new_buf->buf, before); /* Search the next occurence */
442 }
443
444 buffer_empty(buf);
445 buffer_copy(buf, new_buf);
446 buffer_free(new_buf);
447
448 return buf;
449}
450
451
452/*
453 * Retrieve first position inside a buffer of a specific char
454 * or -1 if not found.
455 */
456long int buffer_chr(const buffer * buf, char c)
457{
458 size_t i;
459
460 assert(buf);
461 assert(c);
462
463 for(i=0 ; i < buf->use ; i++) {
464 if (buf->buf[i] == c)
465 return i;
466 }
467
468 return -1;
469}
470
471
472/*
473 * Same as buffer_chr but begin by the end of buffer
474 */
475long int buffer_rchr(const buffer * buf, char c)
476{
477 size_t i;
478
479 assert(buf);
480 assert(c);
481
482 for(i=buf->use ; i > 0 ; i--) {
483 if (buf->buf[i] == c)
484 return i;
485 }
486
487 return -1;
488}
489
490
491/*
492 * Modify string to replace encoded characters by their true value
493 * Function originaly written by Assefa
494 *
495 * The replacements performed are:
496 * & -> &amp;
497 * " -> &quot;
498 * < -> &lt;
499 * > -> &gt;
500 */
502{
503 buffer *buf;
504
505 assert(str);
506 buf = buffer_init();
507
508 for( /* empty */ ; *str ; str++) {
509
510 switch(*str) {
511 case '&':
512 buffer_add_str(buf, "&amp;");
513 break;
514
515 case '<':
516 buffer_add_str(buf, "&lt;");
517 break;
518
519 case '>':
520 buffer_add_str(buf, "&gt;");
521 break;
522
523 case '"':
524 buffer_add_str(buf, "&quot;");
525 break;
526
527 case '\'':
528 buffer_add_str(buf, "&#39;");
529 break;
530
531 default:
532 buffer_add(buf, *str);
533 }
534 }
535
536 return buf;
537}
538
539
540/*
541 * Modify string to replace encoded characters by their true value
542 * for JSON output
543 */
545{
546 buffer *buf;
547
548 assert(str);
549 buf = buffer_init();
550
551 for( /* empty */ ; *str ; str++) {
552 switch(*str) {
553 case '"':
554 buffer_add_str(buf, "\\\"");
555 break;
556
557 case '\n':
558 buffer_add_str(buf, "\\\\n");
559 break;
560
561 case '\r':
562 buffer_add_str(buf, "\\\\r");
563 break;
564
565 case '\t':
566 buffer_add_str(buf, "\\\\t");
567 break;
568
569 case '\\':
570 buffer_add_str(buf, "\\\\");
571 break;
572
573 default:
574 buffer_add(buf, *str);
575 }
576 }
577 return buf;
578}
579
580
581/*
582 * vim: expandtab sw=4 ts=4
583 */
buffer * buffer_encode_xml_entities_str(const char *str)
Definition buffer.c:501
void buffer_add(buffer *buf, char c)
Definition buffer.c:123
void buffer_empty(buffer *buf)
Definition buffer.c:100
buffer * buffer_encode_json_str(const char *str)
Definition buffer.c:544
void buffer_copy(buffer *dest, const buffer *src)
Definition buffer.c:350
static void buffer_realloc(buffer *buf)
Definition buffer.c:44
bool buffer_cmp(const buffer *buf, const char *str)
Definition buffer.c:290
#define SIZE_MAX
Definition buffer.c:37
void buffer_add_str(buffer *buf, const char *str)
Definition buffer.c:254
void buffer_flush(buffer *buf, FILE *output)
Definition buffer.c:112
bool buffer_case_cmp(const buffer *buf, const char *str)
Definition buffer.c:330
long int buffer_rchr(const buffer *buf, char c)
Definition buffer.c:475
long int buffer_chr(const buffer *buf, char c)
Definition buffer.c:456
void buffer_add_double(buffer *buf, double f)
Definition buffer.c:158
void buffer_add_nstr(buffer *buf, const char *str, size_t n)
Definition buffer.c:271
bool buffer_ncmp(const buffer *buf, const char *str, size_t n)
Definition buffer.c:310
void buffer_add_head_str(buffer *buf, char *str)
Definition buffer.c:239
buffer * buffer_replace(buffer *buf, char *before, char *after)
Definition buffer.c:412
void buffer_add_head(buffer *buf, char c)
Definition buffer.c:217
buffer * buffer_from_str(const char *str)
Definition buffer.c:202
void buffer_free(buffer *buf)
Definition buffer.c:83
buffer * buffer_clone(buffer *buf)
Definition buffer.c:362
void buffer_add_int(buffer *buf, int i)
Definition buffer.c:173
void buffer_shift(buffer *buf, size_t len)
Definition buffer.c:392
buffer * buffer_itoa(int i)
Definition buffer.c:188
buffer * buffer_ftoa(double f)
Definition buffer.c:138
void buffer_pop(buffer *buf, size_t len)
Definition buffer.c:379
buffer * buffer_init()
Definition buffer.c:61
struct Buffer buffer
#define BUFFER_SIZE_INIT
Definition ows_struct.h:33
size_t size
size used for data
Definition ows_struct.h:37
char * buf
size to next realloc
Definition ows_struct.h:39
size_t realloc
memory available
Definition ows_struct.h:38
size_t use
Definition ows_struct.h:36

Generated for tinyows by doxygen 1.13.2