macrodelete_parser fix
[mala.git] / engine / strings.c
blob1e54c212c9febec67c77b3b5057b81a72dcf8963
1 /*
2 strings.c - MaLa string handling
4 Copyright (C) 2004, Christian Thaeter <chth@gmx.net>
6 This program is free software; you can redistribute it and/or modify
7 it under the terms of the GNU General Public License version 2 as
8 published by the Free Software Foundation.
10 This program is distributed in the hope that it will be useful,
11 but WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 GNU General Public License for more details.
15 You should have received a copy of the GNU General Public License
16 along with this program; if not, contact me.
21 * TODO: handle empty strings
23 #define _GNU_SOURCE
25 #include "strings.h"
26 #include <stdlib.h>
27 #include <stdio.h>
28 #include <stdarg.h>
30 /* allocate a mala_string (will be used for pooling in future)*/
31 static MalaString
32 string_alloc_ (MalaStringBucket bucket)
34 MalaString self;
35 (void) bucket;
37 self = malloc(sizeof(mala_string));
38 if (!self)
39 return NULL;
41 self->len = SIZE_MAX;
42 self->bucket = bucket;
43 self->user = NULL;
45 return self;
48 /* free a mala_string (to a pool in future) */
49 /*static void
50 string_free_ (MalaString self)
52 free (self);
56 /* attach allocated cstr to new MalaString, call free(cstr) on error, return NULL on cstr==NULL */
57 static MalaString
58 string_cstr_ (const char* cstr)
60 MalaString self;
62 if (!cstr)
63 return NULL;
65 self = string_alloc_ (NULL);
66 if (!self)
67 goto ealloc_str;
69 self->str = cstr;
70 self->refcnt = 4;
72 return self;
73 ealloc_str:
74 free ((void*) cstr);
75 return NULL;
79 MalaString
80 mala_string_new (const char* cstr, MalaStringBucket bucket)
82 MalaString* loc;
83 MalaString self;
85 MALA_ASSERT(cstr);
87 if (bucket)
89 /*create in bucket*/
90 mala_string tmp = MALA_STRING_AUTO (cstr);
91 loc = (MalaString*) tsearch (&tmp, &bucket->bucket, bucket->cmpfn);
92 if (!loc)
93 return NULL;
95 if (*loc == &tmp)
97 /*not in bucket, allocate new string*/
98 self = string_cstr_ (strdup(cstr));
99 if (!self)
101 tdelete (&tmp, &bucket->bucket, bucket->cmpfn);
102 return NULL;
105 self->bucket = bucket;
106 self->refcnt += 4; /*add a reference for the bucket itself*/
107 *loc = self;
109 else
111 /*string already in bucket*/
112 self = *loc;
113 self->refcnt += 4;
116 else
118 /* bucket was NULL, create without bucket */
119 self = string_cstr_ (strdup(cstr));
120 if (!self)
121 return NULL;
123 return self;
126 MalaString
127 mala_string_new_cat2 (const char* cstr1, const char* cstr2, MalaStringBucket bucket)
129 MalaString* loc;
130 MalaString self;
131 size_t len1;
132 char * cstr;
133 mala_string tmp = MALA_STRING_AUTO (NULL);
135 MALA_ASSERT(cstr1);
136 MALA_ASSERT(cstr2);
138 cstr = malloc ((len1 = strlen (cstr1)) + strlen (cstr2) + 1);
139 if (!cstr)
140 return NULL;
142 tmp.str = cstr;
144 (void) strcpy (cstr, cstr1);
145 (void) strcpy (cstr + len1, cstr2);
147 if (bucket)
149 /*create in bucket*/
150 loc = (MalaString*) tsearch (&tmp, &bucket->bucket, bucket->cmpfn);
151 if (!loc)
152 goto ealloc_tree;
154 if (*loc == &tmp)
156 /*not in bucket, allocate new string*/
157 self = string_cstr_ (cstr);
158 if (!self)
159 goto ealloc_lookup;
161 self->bucket = bucket;
162 self->refcnt += 4; /*add a reference for the bucket itself*/
163 *loc = self;
165 else
167 /*string already in bucket*/
168 self = *loc;
169 self->refcnt += 4;
170 free (cstr);
173 else
175 /* bucket was NULL, create without bucket */
176 self = string_cstr_ (cstr);
177 if (!self)
178 return NULL;
180 return self;
182 ealloc_lookup:
183 tdelete (&tmp, &bucket->bucket, bucket->cmpfn);
184 ealloc_tree:
185 free (cstr);
186 return NULL;
189 MalaString
190 mala_string_new_n (const char* cstr, const size_t n, MalaStringBucket bucket)
192 MalaString self;
193 char * c;
195 self = string_cstr_ ((c = strndup(cstr, n)));
196 if (!self)
197 return NULL;
199 mala_stringbucket_insert (bucket, &self);
200 return self;
203 /*should be stringbucket_find*/
204 MalaString
205 mala_string_find (const char* cstr, MalaStringBucket bucket)
207 MalaString* loc;
209 assert(cstr);
210 assert(bucket);
212 mala_string tmp = MALA_STRING_AUTO (cstr);
213 loc = (MalaString*) tfind (&tmp, &bucket->bucket, bucket->cmpfn);
214 if (!loc)
215 return NULL;
217 return *loc;
220 void
221 mala_string_free (MalaString self)
223 if (!self)
224 return;
226 MALA_ASSERT (self->refcnt < SIZE_MAX>>1);
228 if (self->refcnt >= 4)
229 self->refcnt -= 4;
231 /* if this is the last used string */
232 if (self->refcnt < 4)
234 if (self->user && self->bucket->freefn)
236 self->bucket->freefn (self->user);
238 if (self->bucket && !self->bucket->destroying)
240 tdelete (self, &self->bucket->bucket, self->bucket->cmpfn);
242 if (!(self->refcnt & 0x2))
243 free ((void*) self->str);
244 if (!(self->refcnt & 0x1))
245 free (self);
249 void
250 mala_string_data_free (MalaString self)
252 if (!self)
253 return;
254 MALA_ASSERT(self);
255 MALA_ASSERT(self->str);
256 MALA_ASSERT(self->refcnt >= 4);
258 if (self->user
259 && self->bucket
260 && self->bucket->freefn
261 && self->bucket->destroying)
263 self->bucket->freefn (self->user);
264 self->user = NULL;
269 MalaString
270 mala_string_copy_n (MalaString self, const size_t n)
272 assert(self);
274 if (mala_string_length (self) <= n)
276 self->refcnt += 4;
277 return self;
280 return mala_string_new_n (self->str, n, self->bucket);
283 MalaString
284 mala_string_new_prefix (const char* prefix, MalaString str)
286 MalaString_ref loc;
287 MalaString self;
288 MalaStringBucket bucket = str->bucket;
289 size_t len1;
290 char * cstr;
291 mala_string tmp = MALA_STRING_AUTO (NULL);
293 cstr = malloc ((len1 = strlen (prefix)) + mala_string_length (str) + 1);
294 if (!cstr)
295 return NULL;
297 tmp.str = cstr;
298 (void) strcpy (cstr, prefix);
299 (void) strcpy (cstr + len1, str->str);
301 if (bucket)
303 /*create in bucket*/
304 loc = (MalaString_ref) tsearch (&tmp, &bucket->bucket, bucket->cmpfn);
305 if (!loc)
306 goto ealloc_tree;
308 if (*loc == &tmp)
310 /*not in bucket, allocate new string*/
311 self = string_cstr_ (cstr);
312 if (!self)
313 goto ealloc_lookup;
315 self->bucket = bucket;
316 self->refcnt += 4; /*add a reference for the bucket itself*/
317 *loc = self;
319 else
321 /*string already in bucket*/
322 self = *loc;
323 self->refcnt += 4;
324 free (cstr);
327 else
329 /* bucket was NULL, create without bucket */
330 self = string_cstr_ (cstr);
331 if (!self)
332 return NULL;
334 return self;
336 ealloc_lookup:
337 tdelete (&tmp, &bucket->bucket, bucket->cmpfn);
338 ealloc_tree:
339 free (cstr);
340 return NULL;
345 mala_string_scan (const_MalaString str,const char* fmt,...)
347 va_list ap;
349 va_start(ap, fmt);
350 return vsscanf(mala_string_cstr (str), fmt, ap);
353 MalaString
354 mala_string_new_print (MalaStringBucket bucket, const char* fmt,...)
356 int n;
357 int size = 64;
358 char *p;
359 va_list ap;
360 MalaString self;
362 if (!(p = malloc (size)))
363 return NULL;
365 while (1) {
366 va_start(ap, fmt);
367 n = vsnprintf (p, size, fmt, ap);
368 va_end(ap);
370 if (n > -1 && n < size)
372 self = string_cstr_ (p);
373 if (!self)
374 return NULL;
376 mala_stringbucket_insert (bucket, &self);
377 return self;
381 if (n > -1)
382 size = n+1;
383 else
384 size *= 2;
386 if ((p = realloc (p, size)) == NULL)
387 return NULL;
391 size_t
392 mala_string_char_find (MalaString self, const char c)
394 char * pos;
396 if (!self)
397 return SIZE_MAX;
399 pos = strchr (self->str, c);
401 return pos?(size_t)(pos-self->str):SIZE_MAX;
404 MalaString
405 mala_string_new_substr (MalaString self, size_t start, size_t end)
407 MalaString nstr;
409 if (start > mala_string_length (self))
410 return NULL;
412 if (end > mala_string_length (self))
413 end = mala_string_length (self);
415 nstr = mala_string_new_n (self->str+start, end - start, self->bucket);
416 return nstr;
420 MalaString
421 mala_string_factory (MalaString_ref dest, const char* src, MalaStringBucket bucket)
423 if (src)
425 return *dest = mala_string_new (src, bucket);
427 else
429 mala_string_free (*dest);
430 return NULL;
445 #if 0 /*TODO below */
454 mala_string (MalaString,)
455 mala_string_substr
456 mala_string (MalaString,)
457 mala_string_at
459 tokenizer
461 void
462 mala_string_tokenize_init (MalaString,char**state);
463 MalaString
464 mala_string_tokenize (MalaString,char**state, MalaStringBucket dest,char*breaks)
467 chop chopl chopr
469 / parsing
470 mala_string (MalaString,)
471 mala_string (MalaString,)
472 mala_string (MalaString,)
473 mala_string (MalaString,)
474 regex
475 regcomp (3) - POSIX regex functions
476 regerror (3) - POSIX regex functions
477 regex (3) - POSIX regex functions
478 regex (7) - POSIX 1003.2 regular expressions
479 regexec (3) - POSIX regex functions
480 regfree (3) - POSIX regex functions
483 mala_string (MalaString,)
484 mala_string (MalaString,)
486 /* Find the first occurrence of C in S. */
487 extern char *strchr (__const char *__s, int __c) __THROW __attribute_pure__;
488 /* Find the last occurrence of C in S. */
489 extern char *strrchr (__const char *__s, int __c) __THROW __attribute_pure__;
490 __END_NAMESPACE_STD
492 /* Return the length of the initial segment of S which
493 consists entirely of characters not in REJECT. */
494 extern size_t strcspn (__const char *__s, __const char *__reject)
495 __THROW __attribute_pure__;
496 /* Return the length of the initial segment of S which
497 consists entirely of characters in ACCEPT. */
498 extern size_t strspn (__const char *__s, __const char *__accept)
499 __THROW __attribute_pure__;
500 /* Find the first occurrence in S of any character in ACCEPT. */
501 extern char *strpbrk (__const char *__s, __const char *__accept)
502 __THROW __attribute_pure__;
503 /* Find the first occurrence of NEEDLE in HAYSTACK. */
504 extern char *strstr (__const char *__haystack, __const char *__needle)
505 __THROW __attribute_pure__;
508 /* Return the next DELM-delimited token from *STRINGP,
509 terminating it with a '\0', and update *STRINGP to point past it. */
510 extern char *strsep (char **__restrict __stringp,
511 __const char *__restrict __delim) __THROW;
516 #endif
520 // Local Variables:
521 // mode: C
522 // c-file-style: "gnu"
523 // End:
524 // arch-tag: 2f6ba215-7cf7-46ba-a09e-e20b4c889234
525 // end_of_file