2 Copyright (c) 2008-2013, Troy D. Hanson http://troydhanson.github.com/uthash/
5 Redistribution and use in source and binary forms, with or without
6 modification, are permitted provided that the following conditions are met:
8 * Redistributions of source code must retain the above copyright
9 notice, this list of conditions and the following disclaimer.
11 THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
12 IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
13 TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
14 PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER
15 OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
16 EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
17 PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
18 PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
19 LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
20 NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
21 SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
24 /* a dynamic string implementation using macros
29 #define UTSTRING_VERSION 1.9.8
32 #define _UNUSED_ __attribute__ ((__unused__))
42 #define oom() exit(-1)
47 size_t n; /* allocd size */
48 size_t i; /* index of first unused byte */
51 #define utstring_reserve(s,amt) \
53 if (((s)->n - (s)->i) < (size_t)(amt)) { \
54 (s)->d = (char*)realloc((s)->d, (s)->n + amt); \
55 if ((s)->d == NULL) oom(); \
60 #define utstring_init(s) \
62 (s)->n = 0; (s)->i = 0; (s)->d = NULL; \
63 utstring_reserve(s,128); \
67 #define utstring_done(s) \
69 if ((s)->d != NULL) free((s)->d); \
73 #define utstring_free(s) \
79 #define utstring_new(s) \
81 s = (UT_string*)calloc(sizeof(UT_string),1); \
86 #define utstring_renew(s) \
95 #define utstring_clear(s) \
101 #define utstring_bincpy(s,b,l) \
103 utstring_reserve((s),(l)+1); \
104 if (l) memcpy(&(s)->d[(s)->i], b, l); \
106 (s)->d[(s)->i]='\0'; \
109 #define utstring_concat(dst,src) \
111 utstring_reserve((dst),((src)->i)+1); \
112 if ((src)->i) memcpy(&(dst)->d[(dst)->i], (src)->d, (src)->i); \
113 (dst)->i += (src)->i; \
114 (dst)->d[(dst)->i]='\0'; \
117 #define utstring_len(s) ((unsigned)((s)->i))
119 #define utstring_body(s) ((s)->d)
121 _UNUSED_ static void utstring_printf_va(UT_string *s, const char *fmt, va_list ap) {
130 n = vsnprintf (&s->d[s->i], s->n-s->i, fmt, cp);
133 if ((n > -1) && (n < (int)(s->n-s->i))) {
138 /* Else try again with more space. */
139 if (n > -1) utstring_reserve(s,n+1); /* exact */
140 else utstring_reserve(s,(s->n)*2); /* 2x */
144 /* support printf format checking (2=the format string, 3=start of varargs) */
145 static void utstring_printf(UT_string *s, const char *fmt, ...)
146 __attribute__ (( format( printf, 2, 3) ));
148 _UNUSED_ static void utstring_printf(UT_string *s, const char *fmt, ...) {
151 utstring_printf_va(s,fmt,ap);
155 #define utstring_append_len(dst, src, len) \
157 while ((dst)->n-(dst)->i <= (len)) utstring_reserve((dst),((dst)->n)*2); \
158 memcpy(&(dst)->d[(dst)->i], (src), (len)); \
160 (dst)->d[(dst)->i]='\0'; \
163 #define utstring_append_c(dst, c) \
165 if ((dst)->n-(dst)->i < 2) utstring_reserve((dst),((dst)->n)*2); \
166 (dst)->d[(dst)->i++] = (c); \
167 (dst)->d[(dst)->i]='\0'; \
170 /*******************************************************************************
171 * begin substring search functions *
172 ******************************************************************************/
173 /* Build KMP table from left to right. */
174 _UNUSED_ static void _utstring_BuildTable(
175 const char *P_Needle,
184 while (i < P_NeedleLen)
186 while ( (j > -1) && (P_Needle[i] != P_Needle[j]) )
194 if (P_Needle[i] == P_Needle[j])
196 P_KMP_Table[i] = P_KMP_Table[j];
213 /* Build KMP table from right to left. */
214 _UNUSED_ static void _utstring_BuildTableR(
215 const char *P_Needle,
223 P_KMP_Table[i + 1] = j;
226 while ( (j < P_NeedleLen) && (P_Needle[i] != P_Needle[j]) )
228 j = P_KMP_Table[j + 1];
234 if (P_Needle[i] == P_Needle[j])
236 P_KMP_Table[i + 1] = P_KMP_Table[j + 1];
240 P_KMP_Table[i + 1] = j;
245 P_KMP_Table[i + 1] = j;
253 /* Search data from left to right. ( Multiple search mode. ) */
254 _UNUSED_ static long _utstring_find(
255 const char *P_Haystack,
256 size_t P_HaystackLen,
257 const char *P_Needle,
262 long V_FindPosition = -1;
264 /* Search from left to right. */
266 while ( (j < (int)P_HaystackLen) && (((P_HaystackLen - j) + i) >= P_NeedleLen) )
268 while ( (i > -1) && (P_Needle[i] != P_Haystack[j]) )
274 if (i >= (int)P_NeedleLen)
277 V_FindPosition = j - i;
282 return V_FindPosition;
286 /* Search data from right to left. ( Multiple search mode. ) */
287 _UNUSED_ static long _utstring_findR(
288 const char *P_Haystack,
289 size_t P_HaystackLen,
290 const char *P_Needle,
295 long V_FindPosition = -1;
297 /* Search from right to left. */
298 j = (P_HaystackLen - 1);
299 i = (P_NeedleLen - 1);
300 while ( (j >= 0) && (j >= i) )
302 while ( (i < (int)P_NeedleLen) && (P_Needle[i] != P_Haystack[j]) )
304 i = P_KMP_Table[i + 1];
311 V_FindPosition = j + 1;
316 return V_FindPosition;
320 /* Search data from left to right. ( One time search mode. ) */
321 _UNUSED_ static long utstring_find(
323 long P_StartPosition, /* Start from 0. -1 means last position. */
324 const char *P_Needle,
327 long V_StartPosition;
330 long V_FindPosition = -1;
332 if (P_StartPosition < 0)
334 V_StartPosition = s->i + P_StartPosition;
338 V_StartPosition = P_StartPosition;
340 V_HaystackLen = s->i - V_StartPosition;
341 if ( (V_HaystackLen >= P_NeedleLen) && (P_NeedleLen > 0) )
343 V_KMP_Table = (long *)malloc(sizeof(long) * (P_NeedleLen + 1));
344 if (V_KMP_Table != NULL)
346 _utstring_BuildTable(P_Needle, P_NeedleLen, V_KMP_Table);
348 V_FindPosition = _utstring_find(s->d + V_StartPosition,
353 if (V_FindPosition >= 0)
355 V_FindPosition += V_StartPosition;
362 return V_FindPosition;
366 /* Search data from right to left. ( One time search mode. ) */
367 _UNUSED_ static long utstring_findR(
369 long P_StartPosition, /* Start from 0. -1 means last position. */
370 const char *P_Needle,
373 long V_StartPosition;
376 long V_FindPosition = -1;
378 if (P_StartPosition < 0)
380 V_StartPosition = s->i + P_StartPosition;
384 V_StartPosition = P_StartPosition;
386 V_HaystackLen = V_StartPosition + 1;
387 if ( (V_HaystackLen >= P_NeedleLen) && (P_NeedleLen > 0) )
389 V_KMP_Table = (long *)malloc(sizeof(long) * (P_NeedleLen + 1));
390 if (V_KMP_Table != NULL)
392 _utstring_BuildTableR(P_Needle, P_NeedleLen, V_KMP_Table);
394 V_FindPosition = _utstring_findR(s->d,
404 return V_FindPosition;
406 /*******************************************************************************
407 * end substring search functions *
408 ******************************************************************************/
410 #endif /* UTSTRING_H */