new stdmodule file layout
[mala.git] / engine / strings.c
blobfc4a65020306ffc69d951cdcd9fe3758ef07109c
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_cstr_attach (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_ (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 free (cstr);
113 self = *loc;
114 self->refcnt += 4;
117 else
119 /* bucket was NULL, create without bucket */
120 self = string_cstr_ (cstr);
121 if (!self)
122 return NULL;
124 return self;
127 MalaString
128 mala_string_new (const char* cstr, MalaStringBucket bucket)
130 MalaString* loc;
131 MalaString self;
133 MALA_ASSERT(cstr);
135 if (bucket)
137 /*create in bucket*/
138 mala_string tmp = MALA_STRING_AUTO (cstr);
139 loc = (MalaString*) tsearch (&tmp, &bucket->bucket, bucket->cmpfn);
140 if (!loc)
141 return NULL;
143 if (*loc == &tmp)
145 /*not in bucket, allocate new string*/
146 self = string_cstr_ (strdup(cstr));
147 if (!self)
149 tdelete (&tmp, &bucket->bucket, bucket->cmpfn);
150 return NULL;
153 self->bucket = bucket;
154 self->refcnt += 4; /*add a reference for the bucket itself*/
155 *loc = self;
157 else
159 /*string already in bucket*/
160 self = *loc;
161 self->refcnt += 4;
164 else
166 /* bucket was NULL, create without bucket */
167 self = string_cstr_ (strdup(cstr));
168 if (!self)
169 return NULL;
171 return self;
174 MalaString
175 mala_string_new_cat2 (const char* cstr1, const char* cstr2, MalaStringBucket bucket)
177 MalaString* loc;
178 MalaString self;
179 size_t len1;
180 char * cstr;
181 mala_string tmp = MALA_STRING_AUTO (NULL);
183 MALA_ASSERT(cstr1);
184 MALA_ASSERT(cstr2);
186 cstr = malloc ((len1 = strlen (cstr1)) + strlen (cstr2) + 1);
187 if (!cstr)
188 return NULL;
190 tmp.str = cstr;
192 (void) strcpy (cstr, cstr1);
193 (void) strcpy (cstr + len1, cstr2);
195 if (bucket)
197 /*create in bucket*/
198 loc = (MalaString*) tsearch (&tmp, &bucket->bucket, bucket->cmpfn);
199 if (!loc)
200 goto ealloc_tree;
202 if (*loc == &tmp)
204 /*not in bucket, allocate new string*/
205 self = string_cstr_ (cstr);
206 if (!self)
207 goto ealloc_lookup;
209 self->bucket = bucket;
210 self->refcnt += 4; /*add a reference for the bucket itself*/
211 *loc = self;
213 else
215 /*string already in bucket*/
216 self = *loc;
217 self->refcnt += 4;
218 free (cstr);
221 else
223 /* bucket was NULL, create without bucket */
224 self = string_cstr_ (cstr);
225 if (!self)
226 return NULL;
228 return self;
230 ealloc_lookup:
231 tdelete (&tmp, &bucket->bucket, bucket->cmpfn);
232 ealloc_tree:
233 free (cstr);
234 return NULL;
237 MalaString
238 mala_string_new_n (const char* cstr, const size_t n, MalaStringBucket bucket)
240 MalaString self;
241 char * c;
243 self = string_cstr_ ((c = strndup(cstr, n)));
244 if (!self)
245 return NULL;
247 mala_stringbucket_insert (bucket, &self);
248 return self;
251 /*should be stringbucket_find*/
252 MalaString
253 mala_string_find (const char* cstr, MalaStringBucket bucket)
255 MalaString* loc;
257 assert(cstr);
258 assert(bucket);
260 mala_string tmp = MALA_STRING_AUTO (cstr);
261 loc = (MalaString*) tfind (&tmp, &bucket->bucket, bucket->cmpfn);
262 if (!loc)
263 return NULL;
265 return *loc;
268 void
269 mala_string_free (MalaString self)
271 if (!self)
272 return;
274 MALA_ASSERT (self->refcnt < SIZE_MAX>>1);
276 if (self->refcnt >= 4)
277 self->refcnt -= 4;
279 /* if this is the last used string */
280 if (self->refcnt < 4)
282 if (self->user && self->bucket->freefn)
284 self->bucket->freefn (self->user);
286 if (self->bucket && !self->bucket->destroying)
288 tdelete (self, &self->bucket->bucket, self->bucket->cmpfn);
290 if (!(self->refcnt & 0x2))
291 free ((void*) self->str);
292 if (!(self->refcnt & 0x1))
293 free (self);
297 void
298 mala_string_data_free (MalaString self)
300 if (!self)
301 return;
302 MALA_ASSERT(self);
303 MALA_ASSERT(self->str);
304 MALA_ASSERT(self->refcnt >= 4);
306 if (self->user
307 && self->bucket
308 && self->bucket->freefn
309 && self->bucket->destroying)
311 self->bucket->freefn (self->user);
312 self->user = NULL;
317 MalaString
318 mala_string_copy_n (MalaString self, const size_t n)
320 assert(self);
322 if (mala_string_length (self) <= n)
324 self->refcnt += 4;
325 return self;
328 return mala_string_new_n (self->str, n, self->bucket);
331 MalaString
332 mala_string_new_prefix (const char* prefix, MalaString str)
334 MalaString_ref loc;
335 MalaString self;
336 MalaStringBucket bucket = str->bucket;
337 size_t len1;
338 char * cstr;
339 mala_string tmp = MALA_STRING_AUTO (NULL);
341 cstr = malloc ((len1 = strlen (prefix)) + mala_string_length (str) + 1);
342 if (!cstr)
343 return NULL;
345 tmp.str = cstr;
346 (void) strcpy (cstr, prefix);
347 (void) strcpy (cstr + len1, str->str);
349 if (bucket)
351 /*create in bucket*/
352 loc = (MalaString_ref) tsearch (&tmp, &bucket->bucket, bucket->cmpfn);
353 if (!loc)
354 goto ealloc_tree;
356 if (*loc == &tmp)
358 /*not in bucket, allocate new string*/
359 self = string_cstr_ (cstr);
360 if (!self)
361 goto ealloc_lookup;
363 self->bucket = bucket;
364 self->refcnt += 4; /*add a reference for the bucket itself*/
365 *loc = self;
367 else
369 /*string already in bucket*/
370 self = *loc;
371 self->refcnt += 4;
372 free (cstr);
375 else
377 /* bucket was NULL, create without bucket */
378 self = string_cstr_ (cstr);
379 if (!self)
380 return NULL;
382 return self;
384 ealloc_lookup:
385 tdelete (&tmp, &bucket->bucket, bucket->cmpfn);
386 ealloc_tree:
387 free (cstr);
388 return NULL;
393 mala_string_scan (const_MalaString str,const char* fmt,...)
395 va_list ap;
397 va_start(ap, fmt);
398 return vsscanf(mala_string_cstr (str), fmt, ap);
401 MalaString
402 mala_string_new_print (MalaStringBucket bucket, const char* fmt,...)
404 int n;
405 int size = 64;
406 char *p;
407 va_list ap;
408 MalaString self;
410 if (!(p = malloc (size)))
411 return NULL;
413 while (1) {
414 va_start(ap, fmt);
415 n = vsnprintf (p, size, fmt, ap);
416 va_end(ap);
418 if (n > -1 && n < size)
420 self = string_cstr_ (p);
421 if (!self)
422 return NULL;
424 mala_stringbucket_insert (bucket, &self);
425 return self;
429 if (n > -1)
430 size = n+1;
431 else
432 size *= 2;
434 if ((p = realloc (p, size)) == NULL)
435 return NULL;
439 size_t
440 mala_string_char_find (MalaString self, const char c)
442 char * pos;
444 if (!self)
445 return SIZE_MAX;
447 pos = strchr (self->str, c);
449 return pos?(size_t)(pos-self->str):SIZE_MAX;
452 MalaString
453 mala_string_new_substr (MalaString self, size_t start, size_t end)
455 MalaString nstr;
457 if (start > mala_string_length (self))
458 return NULL;
460 if (end > mala_string_length (self))
461 end = mala_string_length (self);
463 nstr = mala_string_new_n (self->str+start, end - start, self->bucket);
464 return nstr;
468 MalaString
469 mala_string_factory (MalaString_ref dest, const char* src, MalaStringBucket bucket)
471 if (src)
473 return *dest = mala_string_new (src, bucket);
475 else
477 mala_string_free (*dest);
478 return NULL;
493 #if 0 /*TODO below */
502 mala_string (MalaString,)
503 mala_string_substr
504 mala_string (MalaString,)
505 mala_string_at
507 tokenizer
509 void
510 mala_string_tokenize_init (MalaString,char**state);
511 MalaString
512 mala_string_tokenize (MalaString,char**state, MalaStringBucket dest,char*breaks)
515 chop chopl chopr
517 / parsing
518 mala_string (MalaString,)
519 mala_string (MalaString,)
520 mala_string (MalaString,)
521 mala_string (MalaString,)
522 regex
523 regcomp (3) - POSIX regex functions
524 regerror (3) - POSIX regex functions
525 regex (3) - POSIX regex functions
526 regex (7) - POSIX 1003.2 regular expressions
527 regexec (3) - POSIX regex functions
528 regfree (3) - POSIX regex functions
531 mala_string (MalaString,)
532 mala_string (MalaString,)
534 /* Find the first occurrence of C in S. */
535 extern char *strchr (__const char *__s, int __c) __THROW __attribute_pure__;
536 /* Find the last occurrence of C in S. */
537 extern char *strrchr (__const char *__s, int __c) __THROW __attribute_pure__;
538 __END_NAMESPACE_STD
540 /* Return the length of the initial segment of S which
541 consists entirely of characters not in REJECT. */
542 extern size_t strcspn (__const char *__s, __const char *__reject)
543 __THROW __attribute_pure__;
544 /* Return the length of the initial segment of S which
545 consists entirely of characters in ACCEPT. */
546 extern size_t strspn (__const char *__s, __const char *__accept)
547 __THROW __attribute_pure__;
548 /* Find the first occurrence in S of any character in ACCEPT. */
549 extern char *strpbrk (__const char *__s, __const char *__accept)
550 __THROW __attribute_pure__;
551 /* Find the first occurrence of NEEDLE in HAYSTACK. */
552 extern char *strstr (__const char *__haystack, __const char *__needle)
553 __THROW __attribute_pure__;
556 /* Return the next DELM-delimited token from *STRINGP,
557 terminating it with a '\0', and update *STRINGP to point past it. */
558 extern char *strsep (char **__restrict __stringp,
559 __const char *__restrict __delim) __THROW;
564 #endif
568 // Local Variables:
569 // mode: C
570 // c-file-style: "gnu"
571 // End:
572 // arch-tag: 2f6ba215-7cf7-46ba-a09e-e20b4c889234
573 // end_of_file