1 /*
2
3 Copyright (c) 2010-2012 NFG Net Facilities Group BV support@nfg.nl
4
5 This program is free software; you can redistribute it and/or
6 modify it under the terms of the GNU General Public License
7 as published by the Free Software Foundation; either
8 version 2 of the License, or (at your option) any later
9 version.
10
11 This program is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 GNU General Public License for more details.
15
16 You should have received a copy of the GNU General Public License
17 along with this program; if not, write to the Free Software
18 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
19 */
20
21 #include <string.h>
22 #include <stdlib.h>
23 #include <assert.h>
24 #include <glib.h>
25
26 #include "dm_string.h"
27 #include "dm_debug.h"
28
29 #define THIS_MODULE "String"
30
31 /*
32 * implements the Sorted Set interface using GTree
33 */
34
35 #define T String_T
36
37 #define SIZE(s) (sizeof(char) * (s->len + 1))
38
39 #define FREE(s) mempool_push(s->pool, s->str, SIZE(s))
40
41 struct T {
42 Mempool_T pool;
43 char *str;
44 size_t len;
45 size_t used;
46 };
47
48 #define STRLEN 255
append(T S,const char * s,va_list ap)49 static inline void append(T S, const char *s, va_list ap)
50 {
51 va_list ap_copy;
52 size_t oldsize;
53
54 while (true) {
55 va_copy(ap_copy, ap);
56 int n = vsnprintf((char *)(S->str + S->used), S->len - S->used, s, ap_copy);
57 va_end(ap_copy);
58 if ((S->used + n) < S->len) {
59 S->used += n;
60 break;
61 }
62 oldsize = SIZE(S);
63 S->len += STRLEN + n;
64 S->str = mempool_resize(S->pool, S->str, oldsize, SIZE(S));
65 }
66 }
67
p_string_new(Mempool_T pool,const char * s)68 T p_string_new(Mempool_T pool, const char * s)
69 {
70 T S;
71 assert(pool);
72 assert(s);
73 size_t l = strlen(s);
74 S = mempool_pop(pool, sizeof(*S));
75 S->pool = pool;
76 S->len = l;
77 S->str = (char *)mempool_pop(S->pool, SIZE(S));
78 memcpy(S->str, s, l);
79 S->used = l;
80 return S;
81 }
82
p_string_assign(T S,const char * s)83 T p_string_assign(T S, const char *s)
84 {
85 size_t oldsize, newsize;
86 size_t l = strlen(s);
87 S->used = 0;
88 memset(S->str, 0, SIZE(S));
89 oldsize = SIZE(S);
90 newsize = (sizeof(char) * (l + 1));
91 if (newsize > oldsize) {
92 S->len = l;
93 S->str = mempool_resize(S->pool, S->str, oldsize, SIZE(S));
94 }
95 memset(S->str, 0, SIZE(S));
96 memcpy(S->str, s, l);
97 S->used = l;
98 return S;
99 }
100
p_string_printf(T S,const char * s,...)101 void p_string_printf(T S, const char * s, ...)
102 {
103 S->used = 0;
104 memset(S->str, 0, SIZE(S));
105 va_list ap;
106 va_start(ap, s);
107 append(S, s, ap);
108 va_end(ap);
109 }
110
p_string_append_printf(T S,const char * s,...)111 void p_string_append_printf(T S, const char *s, ...)
112 {
113 va_list ap;
114 va_start(ap, s);
115 append(S, s, ap);
116 va_end(ap);
117 }
118
p_string_append_vprintf(T S,const char * s,va_list ap)119 void p_string_append_vprintf(T S, const char *s, va_list ap)
120 {
121 va_list ap_copy;
122 va_copy(ap_copy, ap);
123 append(S, s, ap_copy);
124 va_end(ap_copy);
125 }
126
p_string_append_len(T S,const char * s,size_t l)127 void p_string_append_len(T S, const char *s, size_t l)
128 {
129 if ((S->used + l) > S->len) {
130 size_t oldsize = SIZE(S);
131 S->len += l;
132 S->str = mempool_resize(S->pool, S->str, oldsize, SIZE(S));
133 assert(S->str);
134 }
135 char *dest = S->str;
136 dest += S->used;
137 memcpy(dest, s, l);
138 S->used += l;
139 S->str[S->used] = '\0';
140 }
141
p_string_len(T S)142 uint64_t p_string_len(T S)
143 {
144 return S->used;
145 }
146
p_string_str(T S)147 const char * p_string_str(T S)
148 {
149 return S->str;
150 }
151
p_string_erase(T S,size_t pos,int len)152 T p_string_erase(T S, size_t pos, int len)
153 {
154 assert(S);
155 assert(pos <= S->used);
156
157 if (len < 0)
158 len = S->used - pos;
159 else {
160 assert (pos + len <= S->used);
161
162 if (pos + len < S->used)
163 memmove (S->str + pos, S->str + pos + len, S->used - (pos + len));
164 }
165
166 S->used -= len;
167
168 S->str[S->used] = 0;
169
170 return S;
171 }
172
p_string_truncate(T S,size_t l)173 T p_string_truncate(T S, size_t l)
174 {
175 if (l >= S->used)
176 return S;
177 S->str[l] = '\0';
178 S->used = l;
179 return S;
180 }
181
p_string_unescape(T S)182 void p_string_unescape(T S)
183 {
184 char *s = S->str;
185 char *head = s, *this = s, *next = s;
186 char found_escape = 0;
187 while (*this) {
188 next = this+1;
189 if (!found_escape && *this && *next && (*this == '\\') && (*next == '"' || *next == '\\')) {
190 found_escape = 1;
191 S->used--;
192 this++;
193 continue;
194 }
195 found_escape = 0;
196 *head++ = *this++;
197 }
198 *head = 0;
199 }
200
p_string_free(T S,gboolean free_block)201 char * p_string_free(T S, gboolean free_block)
202 {
203 char *s = NULL;
204 Mempool_T pool = S->pool;
205 if (free_block) {
206 FREE(S);
207 } else {
208 s = S->str;
209 }
210 mempool_push(pool, S, sizeof(*S));
211 return s;
212 }
213
214
p_ltrim(char * str,const char * seps)215 char *p_ltrim(char *str, const char *seps)
216 {
217 size_t totrim;
218 if (seps == NULL) {
219 seps = "\t\n\v\f\r ";
220 }
221 totrim = strspn(str, seps);
222 if (totrim > 0) {
223 size_t len = strlen(str);
224 if (totrim == len) {
225 str[0] = '\0';
226 }
227 else {
228 memmove(str, str + totrim, len + 1 - totrim);
229 }
230 }
231 return str;
232 }
233
p_rtrim(char * str,const char * seps)234 char *p_rtrim(char *str, const char *seps)
235 {
236 int i;
237 if (seps == NULL) {
238 seps = "\t\n\v\f\r ";
239 }
240 i = strlen(str) - 1;
241 while (i >= 0 && strchr(seps, str[i]) != NULL) {
242 str[i] = '\0';
243 i--;
244 }
245 return str;
246 }
247
p_trim(char * str,const char * seps)248 char *p_trim(char *str, const char *seps)
249 {
250 return p_ltrim(p_rtrim(str, seps), seps);
251 }
252
253 #undef T
254