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