updated NEWS
[mala.git] / engine / strings.c
bloba35f5e79a2bc9eaaa6132ec46fc4b0c56ef90cb9
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 va_end (ap);
399 return vsscanf(mala_string_cstr (str), fmt, ap);
402 MalaString
403 mala_string_new_print (MalaStringBucket bucket, const char* fmt,...)
405 int n;
406 int size = 64;
407 char *p;
408 va_list ap;
409 MalaString self;
411 if (!(p = malloc (size)))
412 return NULL;
414 while (1) {
415 va_start(ap, fmt);
416 n = vsnprintf (p, size, fmt, ap);
417 va_end(ap);
419 if (n > -1 && n < size)
421 self = string_cstr_ (p);
422 if (!self)
423 return NULL;
425 mala_stringbucket_insert (bucket, &self);
426 return self;
430 if (n > -1)
431 size = n+1;
432 else
433 size *= 2;
435 if ((p = realloc (p, size)) == NULL)
436 return NULL;
440 size_t
441 mala_string_char_find (MalaString self, const char c)
443 char * pos;
445 if (!self)
446 return SIZE_MAX;
448 pos = strchr (self->str, c);
450 return pos?(size_t)(pos-self->str):SIZE_MAX;
453 MalaString
454 mala_string_new_substr (MalaString self, size_t start, size_t end)
456 MalaString nstr;
458 if (start > mala_string_length (self))
459 return NULL;
461 if (end > mala_string_length (self))
462 end = mala_string_length (self);
464 nstr = mala_string_new_n (self->str+start, end - start, self->bucket);
465 return nstr;
469 MalaString
470 mala_string_factory (MalaString_ref dest, const char* src, MalaStringBucket bucket)
472 if (src)
474 return *dest = mala_string_new (src, bucket);
476 else
478 mala_string_free (*dest);
479 return NULL;
494 #if 0 /*TODO below */
503 mala_string (MalaString,)
504 mala_string_substr
505 mala_string (MalaString,)
506 mala_string_at
508 tokenizer
510 void
511 mala_string_tokenize_init (MalaString,char**state);
512 MalaString
513 mala_string_tokenize (MalaString,char**state, MalaStringBucket dest,char*breaks)
516 chop chopl chopr
518 / parsing
519 mala_string (MalaString,)
520 mala_string (MalaString,)
521 mala_string (MalaString,)
522 mala_string (MalaString,)
523 regex
524 regcomp (3) - POSIX regex functions
525 regerror (3) - POSIX regex functions
526 regex (3) - POSIX regex functions
527 regex (7) - POSIX 1003.2 regular expressions
528 regexec (3) - POSIX regex functions
529 regfree (3) - POSIX regex functions
532 mala_string (MalaString,)
533 mala_string (MalaString,)
535 /* Find the first occurrence of C in S. */
536 extern char *strchr (__const char *__s, int __c) __THROW __attribute_pure__;
537 /* Find the last occurrence of C in S. */
538 extern char *strrchr (__const char *__s, int __c) __THROW __attribute_pure__;
539 __END_NAMESPACE_STD
541 /* Return the length of the initial segment of S which
542 consists entirely of characters not in REJECT. */
543 extern size_t strcspn (__const char *__s, __const char *__reject)
544 __THROW __attribute_pure__;
545 /* Return the length of the initial segment of S which
546 consists entirely of characters in ACCEPT. */
547 extern size_t strspn (__const char *__s, __const char *__accept)
548 __THROW __attribute_pure__;
549 /* Find the first occurrence in S of any character in ACCEPT. */
550 extern char *strpbrk (__const char *__s, __const char *__accept)
551 __THROW __attribute_pure__;
552 /* Find the first occurrence of NEEDLE in HAYSTACK. */
553 extern char *strstr (__const char *__haystack, __const char *__needle)
554 __THROW __attribute_pure__;
557 /* Return the next DELM-delimited token from *STRINGP,
558 terminating it with a '\0', and update *STRINGP to point past it. */
559 extern char *strsep (char **__restrict __stringp,
560 __const char *__restrict __delim) __THROW;
565 #endif
569 // Local Variables:
570 // mode: C
571 // c-file-style: "gnu"
572 // End:
573 // arch-tag: 2f6ba215-7cf7-46ba-a09e-e20b4c889234
574 // end_of_file