1 | /* |
2 | * Copyright (c) 2009-2012 Petri Lehtinen <petri@digip.org> |
3 | * |
4 | * Jansson is free software; you can redistribute it and/or modify |
5 | * it under the terms of the MIT license. See LICENSE for details. |
6 | */ |
7 | |
8 | #ifndef _GNU_SOURCE |
9 | #define _GNU_SOURCE |
10 | #endif |
11 | |
12 | #include <stdlib.h> |
13 | #include <string.h> |
14 | #include "jansson_private.h" |
15 | #include "strbuffer.h" |
16 | |
17 | #define STRBUFFER_MIN_SIZE 16 |
18 | #define STRBUFFER_FACTOR 2 |
19 | #define STRBUFFER_SIZE_MAX ((size_t)-1) |
20 | |
21 | int strbuffer_init(strbuffer_t *strbuff) |
22 | { |
23 | strbuff->size = STRBUFFER_MIN_SIZE; |
24 | strbuff->length = 0; |
25 | |
26 | strbuff->value = jsonp_malloc(strbuff->size); |
27 | if(!strbuff->value) |
28 | return -1; |
29 | |
30 | /* initialize to empty */ |
31 | strbuff->value[0] = '\0'; |
32 | return 0; |
33 | } |
34 | |
35 | void strbuffer_close(strbuffer_t *strbuff) |
36 | { |
37 | jsonp_free(strbuff->value); |
38 | strbuff->size = 0; |
39 | strbuff->length = 0; |
40 | strbuff->value = NULL; |
41 | } |
42 | |
43 | void strbuffer_clear(strbuffer_t *strbuff) |
44 | { |
45 | strbuff->length = 0; |
46 | strbuff->value[0] = '\0'; |
47 | } |
48 | |
49 | const char *strbuffer_value(const strbuffer_t *strbuff) |
50 | { |
51 | return strbuff->value; |
52 | } |
53 | |
54 | char *strbuffer_steal_value(strbuffer_t *strbuff) |
55 | { |
56 | char *result = strbuff->value; |
57 | strbuffer_init(strbuff); |
58 | return result; |
59 | } |
60 | |
61 | int strbuffer_append(strbuffer_t *strbuff, const char *string) |
62 | { |
63 | return strbuffer_append_bytes(strbuff, string, strlen(string)); |
64 | } |
65 | |
66 | int strbuffer_append_byte(strbuffer_t *strbuff, char byte) |
67 | { |
68 | return strbuffer_append_bytes(strbuff, &byte, 1); |
69 | } |
70 | |
71 | int strbuffer_append_bytes(strbuffer_t *strbuff, const char *data, size_t size) |
72 | { |
73 | if(size >= strbuff->size - strbuff->length) |
74 | { |
75 | size_t new_size; |
76 | char *new_value; |
77 | |
78 | /* avoid integer overflow */ |
79 | if (strbuff->size > STRBUFFER_SIZE_MAX / STRBUFFER_FACTOR |
80 | || size > STRBUFFER_SIZE_MAX - 1 |
81 | || strbuff->length > STRBUFFER_SIZE_MAX - 1 - size) |
82 | return -1; |
83 | |
84 | new_size = max(strbuff->size * STRBUFFER_FACTOR, |
85 | strbuff->length + size + 1); |
86 | |
87 | new_value = jsonp_malloc(new_size); |
88 | if(!new_value) |
89 | return -1; |
90 | |
91 | memcpy(new_value, strbuff->value, strbuff->length); |
92 | |
93 | jsonp_free(strbuff->value); |
94 | strbuff->value = new_value; |
95 | strbuff->size = new_size; |
96 | } |
97 | |
98 | memcpy(strbuff->value + strbuff->length, data, size); |
99 | strbuff->length += size; |
100 | strbuff->value[strbuff->length] = '\0'; |
101 | |
102 | return 0; |
103 | } |
104 | |
105 | char strbuffer_pop(strbuffer_t *strbuff) |
106 | { |
107 | if(strbuff->length > 0) { |
108 | char c = strbuff->value[--strbuff->length]; |
109 | strbuff->value[strbuff->length] = '\0'; |
110 | return c; |
111 | } |
112 | else |
113 | return '\0'; |
114 | } |
115 | |