fix bug where environment was wrongly dropped, loosing type variable information
[hiphop-php.git] / hphp / neo / neo_str.c
blobec7adb8122d2583f7be694a028afb4ce66b10ea4
1 /*
2 * Copyright 2001-2004 Brandon Long
3 * All Rights Reserved.
5 * ClearSilver Templating System
7 * This code is made available under the terms of the ClearSilver License.
8 * http://www.clearsilver.net/license.hdf
12 #include "cs_config.h"
14 #include <ctype.h>
15 #include <stdlib.h>
16 #include <stdio.h>
17 #include <string.h>
18 #include <stdarg.h>
20 #ifdef _MSC_VER
21 #include <io.h>
22 #else
23 #include <unistd.h>
24 #endif
26 #include "neo_bool.h"
27 #include "neo_misc.h"
28 #include "neo_err.h"
29 #include "neo_str.h"
30 #include "ulist.h"
32 #ifndef va_copy
33 #ifdef __va_copy
34 # define va_copy(dest,src) __va_copy(dest,src)
35 #else
36 # define va_copy(dest,src) ((dest) = (src))
37 #endif
38 #endif
40 char *neos_strip (char *s)
42 int x;
44 x = strlen(s) - 1;
45 while (x>=0 && isspace(s[x])) s[x--] = '\0';
47 while (*s && isspace(*s)) s++;
49 return s;
53 void string_init (NEOSTRING *str)
55 str->buf = NULL;
56 str->len = 0;
57 str->max = 0;
60 void string_clear (NEOSTRING *str)
62 if (str->buf != NULL)
63 free(str->buf);
64 string_init(str);
67 static NEOERR* string_check_length (NEOSTRING *str, int l)
69 if (str->buf == NULL)
71 if (l * 10 > 256)
72 str->max = l * 10;
73 else
74 str->max = 256;
75 str->buf = (char *) malloc (sizeof(char) * str->max);
76 if (str->buf == NULL)
77 return nerr_raise (NERR_NOMEM, "Unable to allocate render buf of size %d",
78 str->max);
79 /* ne_warn("Creating string %x at %d (%5.2fK)", str, str->max, (str->max / 1024.0)); */
81 else if (str->len + l >= str->max)
83 void *new_ptr;
84 int new_max = str->max;
87 new_max *= 2;
88 } while (str->len + l >= new_max);
89 new_ptr = realloc (str->buf, sizeof(char) * new_max);
90 if (new_ptr == NULL) {
91 return nerr_raise (NERR_NOMEM, "Unable to allocate NEOSTRING buf of size %d",
92 new_max);
94 str->buf = (char *) new_ptr;
95 str->max = new_max;
96 /* ne_warn("Growing string %x to %d (%5.2fK)", str, str->max, (str->max / 1024.0)); */
98 return STATUS_OK;
101 NEOERR *string_append (NEOSTRING *str, const char *buf)
103 NEOERR *err;
104 int l;
106 l = strlen(buf);
107 err = string_check_length (str, l);
108 if (err != STATUS_OK) return nerr_pass (err);
109 strcpy(str->buf + str->len, buf);
110 str->len += l;
112 return STATUS_OK;
115 NEOERR *string_appendn (NEOSTRING *str, const char *buf, int l)
117 NEOERR *err;
119 err = string_check_length (str, l+1);
120 if (err != STATUS_OK) return nerr_pass (err);
121 memcpy(str->buf + str->len, buf, l);
122 str->len += l;
123 str->buf[str->len] = '\0';
125 return STATUS_OK;
128 /* this is much more efficient with C99 snprintfs... */
129 NEOERR *string_appendvf (NEOSTRING *str, const char *fmt, va_list ap)
131 NEOERR *err;
132 char buf[4096];
133 int bl, size;
134 va_list tmp;
136 va_copy(tmp, ap);
137 /* determine length */
138 size = sizeof (buf);
139 bl = vsnprintf (buf, size, fmt, tmp);
140 if (bl > -1 && bl < size)
141 return string_appendn (str, buf, bl);
143 /* Handle non-C99 snprintfs (requires extra malloc/free and copy) */
144 if (bl == -1)
146 char *a_buf;
148 va_copy(tmp, ap);
149 a_buf = vnsprintf_alloc(size*2, fmt, tmp);
150 if (a_buf == NULL)
151 return nerr_raise(NERR_NOMEM,
152 "Unable to allocate memory for formatted string");
153 err = string_append(str, a_buf);
154 free(a_buf);
155 return nerr_pass(err);
158 err = string_check_length (str, bl+1);
159 if (err != STATUS_OK) return nerr_pass (err);
160 va_copy(tmp, ap);
161 vsprintf (str->buf + str->len, fmt, tmp);
162 str->len += bl;
163 str->buf[str->len] = '\0';
165 return STATUS_OK;
168 NEOERR *string_appendf (NEOSTRING *str, const char *fmt, ...)
170 NEOERR *err;
171 va_list ap;
173 va_start (ap, fmt);
174 err = string_appendvf (str, fmt, ap);
175 va_end (ap);
176 return nerr_pass(err);
179 NEOERR *string_append_char (NEOSTRING *str, char c)
181 NEOERR *err;
182 err = string_check_length (str, 1);
183 if (err != STATUS_OK) return nerr_pass (err);
184 str->buf[str->len] = c;
185 str->buf[str->len + 1] = '\0';
186 str->len += 1;
188 return STATUS_OK;
191 /* Mostly used by vprintf_alloc for non-C99 compliant snprintfs,
192 * this is like vsprintf_alloc except it takes a "suggested" size */
193 int vnisprintf_alloc (char **buf, int start_size, const char *fmt, va_list ap)
195 int bl, size;
196 va_list tmp;
198 *buf = NULL;
199 size = start_size;
201 *buf = (char *) malloc (size * sizeof(char));
202 if (*buf == NULL) return 0;
203 while (1)
205 void *new_ptr;
206 va_copy(tmp, ap);
207 bl = vsnprintf (*buf, size, fmt, tmp);
208 if (bl > -1 && bl < size)
209 return bl;
210 if (bl > -1)
211 size = bl + 1;
212 else
213 size *= 2;
214 new_ptr = realloc (*buf, size * sizeof(char));
215 if (new_ptr == NULL) {
216 free(*buf);
217 *buf = NULL;
218 return 0;
220 *buf = (char *) new_ptr;
224 char *vnsprintf_alloc (int start_size, const char *fmt, va_list ap)
226 char *r;
227 vnisprintf_alloc(&r, start_size, fmt, ap);
228 return r;
231 /* This works better with a C99 compliant vsnprintf, but should work ok
232 * with versions that return a -1 if it overflows the buffer */
233 int visprintf_alloc (char **buf, const char *fmt, va_list ap)
235 char ibuf[4096];
236 int bl, size;
237 va_list tmp;
239 /* PPC doesn't like you re-using a va_list... and it might not be
240 * supposed to work at all */
241 va_copy(tmp, ap);
243 size = sizeof (ibuf);
244 bl = vsnprintf (ibuf, sizeof (ibuf), fmt, tmp);
245 if (bl > -1 && bl < size)
247 *buf = (char *) calloc(bl+1, sizeof(char));
248 if (*buf == NULL) return 0;
249 strncpy(*buf, ibuf, bl);
250 return bl;
253 if (bl > -1)
254 size = bl + 1;
255 else
256 size *= 2;
258 return vnisprintf_alloc(buf, size, fmt, ap);
261 char *vsprintf_alloc (const char *fmt, va_list ap)
263 char *r;
264 visprintf_alloc(&r, fmt, ap);
265 return r;
268 char *repr_string_alloc (const char *s)
270 int l,x,i;
271 int nl = 0;
272 char *rs;
274 if (s == NULL)
276 return strdup("NULL");
279 l = strlen(s);
280 for (x = 0; x < l; x++)
282 if (isprint(s[x]) && s[x] != '"' && s[x] != '\\')
284 nl++;
286 else
288 if (s[x] == '\n' || s[x] == '\t' || s[x] == '\r' || s[x] == '"' ||
289 s[x] == '\\')
291 nl += 2;
293 else nl += 4;
297 rs = (char *) malloc ((nl+3) * sizeof(char));
298 if (rs == NULL)
299 return NULL;
301 i = 0;
302 rs[i++] = '"';
303 for (x = 0; x < l; x++)
305 if (isprint(s[x]) && s[x] != '"' && s[x] != '\\')
307 rs[i++] = s[x];
309 else
311 rs[i++] = '\\';
312 switch (s[x])
314 case '\n':
315 rs[i++] = 'n';
316 break;
317 case '\t':
318 rs[i++] = 't';
319 break;
320 case '\r':
321 rs[i++] = 'r';
322 break;
323 case '"':
324 rs[i++] = '"';
325 break;
326 case '\\':
327 rs[i++] = '\\';
328 break;
329 default:
330 sprintf(&(rs[i]), "%03o", (s[x] & 0377));
331 i += 3;
332 break;
336 rs[i++] = '"';
337 rs[i] = '\0';
338 return rs;