/ external / libucl / uthash / utstring.h
utstring.h
  1  /*
  2  Copyright (c) 2008-2013, Troy D. Hanson   http://troydhanson.github.com/uthash/
  3  All rights reserved.
  4  
  5  Redistribution and use in source and binary forms, with or without
  6  modification, are permitted provided that the following conditions are met:
  7  
  8      * Redistributions of source code must retain the above copyright
  9        notice, this list of conditions and the following disclaimer.
 10  
 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.
 22  */
 23  
 24  /* a dynamic string implementation using macros 
 25   */
 26  #ifndef UTSTRING_H
 27  #define UTSTRING_H
 28  
 29  #define UTSTRING_VERSION 1.9.8
 30  
 31  #ifdef __GNUC__
 32  #define _UNUSED_ __attribute__ ((__unused__)) 
 33  #else
 34  #define _UNUSED_ 
 35  #endif
 36  
 37  #include <stdlib.h>
 38  #include <string.h>
 39  #include <stdarg.h>
 40  
 41  #ifndef oom
 42  #define oom abort
 43  #endif
 44  
 45  typedef struct {
 46      char *d;
 47      void **pd;
 48      size_t n; /* allocd size */
 49      size_t i; /* index of first unused byte */
 50  } UT_string;
 51  
 52  #define utstring_reserve(s,amt)                            \
 53  do {                                                       \
 54    if (((s)->n - (s)->i) < (size_t)(amt)) {                 \
 55       (s)->d = (char*)realloc((s)->d, (s)->n + amt);        \
 56       if ((s)->d == NULL) oom();                            \
 57       else {(s)->n += amt;                                  \
 58       if ((s)->pd) *((s)->pd) = (s)->d;}                    \
 59    }                                                        \
 60  } while(0)
 61  
 62  #define utstring_init(s)                                   \
 63  do {                                                       \
 64    (s)->n = 0; (s)->i = 0; (s)->d = NULL;                   \
 65    utstring_reserve(s,128);                                 \
 66    (s)->d[0] = '\0'; \
 67  } while(0)
 68  
 69  #define utstring_done(s)                                   \
 70  do {                                                       \
 71    if ((s)->d != NULL) free((s)->d);                        \
 72    (s)->n = 0;                                              \
 73  } while(0)
 74  
 75  #define utstring_free(s)                                   \
 76  do {                                                       \
 77    utstring_done(s);                                        \
 78    free(s);                                                 \
 79  } while(0)
 80  
 81  #define utstring_new(s)                                    \
 82  do {                                                       \
 83     s = (UT_string*)calloc(1, sizeof(UT_string));          \
 84     if (!s) oom();                                          \
 85     else utstring_init(s);                                  \
 86  } while(0)
 87  
 88  #define utstring_renew(s)                                  \
 89  do {                                                       \
 90     if (s) {                                                \
 91       utstring_clear(s);                                    \
 92     } else {                                                \
 93       utstring_new(s);                                      \
 94     }                                                       \
 95  } while(0)
 96  
 97  #define utstring_clear(s)                                  \
 98  do {                                                       \
 99    (s)->i = 0;                                              \
100    (s)->d[0] = '\0';                                        \
101  } while(0)
102  
103  #define utstring_bincpy(s,b,l)                             \
104  do {                                                       \
105    utstring_reserve((s),(l)+1);                               \
106    if (l) memcpy(&(s)->d[(s)->i], b, l);                    \
107    (s)->i += l;                                               \
108    (s)->d[(s)->i]='\0';                                         \
109  } while(0)
110  
111  #define utstring_concat(dst,src)                                 \
112  do {                                                             \
113    utstring_reserve((dst),((src)->i)+1);                          \
114    if ((src)->i) memcpy(&(dst)->d[(dst)->i], (src)->d, (src)->i); \
115    (dst)->i += (src)->i;                                          \
116    (dst)->d[(dst)->i]='\0';                                       \
117  } while(0)
118  
119  #define utstring_len(s) ((unsigned)((s)->i))
120  
121  #define utstring_body(s) ((s)->d)
122  
123  _UNUSED_ static void utstring_printf_va(UT_string *s, const char *fmt, va_list ap) {
124     int n;
125     va_list cp;
126     while (1) {
127  #ifdef _WIN32
128        cp = ap;
129  #else
130        va_copy(cp, ap);
131  #endif
132        n = vsnprintf (&s->d[s->i], s->n-s->i, fmt, cp);
133        va_end(cp);
134  
135        if ((n > -1) && (n < (int)(s->n-s->i))) {
136          s->i += n;
137          return;
138        }
139  
140        /* Else try again with more space. */
141        if (n > -1) utstring_reserve(s,n+1); /* exact */
142        else utstring_reserve(s,(s->n)*2);   /* 2x */
143     }
144  }
145  #ifdef __GNUC__
146  /* support printf format checking (2=the format string, 3=start of varargs) */
147  static void utstring_printf(UT_string *s, const char *fmt, ...)
148    __attribute__ (( format( printf, 2, 3) ));
149  #endif
150  _UNUSED_ static void utstring_printf(UT_string *s, const char *fmt, ...) {
151     va_list ap;
152     va_start(ap,fmt);
153     utstring_printf_va(s,fmt,ap);
154     va_end(ap);
155  }
156  
157  #define utstring_append_len(dst, src, len)                                    \
158  do {                                                                           \
159      while ((dst)->n-(dst)->i <= (len)) utstring_reserve((dst),((dst)->n)*2);   \
160      memcpy(&(dst)->d[(dst)->i], (src), (len));                                 \
161      (dst)->i+=(len);                                                           \
162      (dst)->d[(dst)->i]='\0';                                                   \
163  } while(0)
164  
165  #define utstring_append_c(dst, c)                                             \
166  do {                                                                           \
167      if ((dst)->n-(dst)->i < 2) utstring_reserve((dst),((dst)->n)*2);            \
168      (dst)->d[(dst)->i++] = (c);                                                \
169      (dst)->d[(dst)->i]='\0';                                                   \
170  } while(0)
171  
172  /*******************************************************************************
173   * begin substring search functions                                            *
174   ******************************************************************************/
175  /* Build KMP table from left to right. */
176  _UNUSED_ static void _utstring_BuildTable(
177      const char *P_Needle, 
178      ssize_t P_NeedleLen, 
179      long *P_KMP_Table)
180  {
181      long i, j;
182  
183      i = 0;
184      j = i - 1;
185      P_KMP_Table[i] = j;
186      while (i < P_NeedleLen)
187      {
188          while ( (j > -1) && (P_Needle[i] != P_Needle[j]) )
189          {
190             j = P_KMP_Table[j];
191          }
192          i++;
193          j++;
194          if (i < P_NeedleLen)
195          {
196              if (P_Needle[i] == P_Needle[j])
197              {
198                  P_KMP_Table[i] = P_KMP_Table[j];
199              }
200              else
201              {
202                  P_KMP_Table[i] = j;
203              }
204          }
205          else
206          {
207              P_KMP_Table[i] = j;
208          }
209      }
210  
211      return;
212  }
213  
214  
215  /* Build KMP table from right to left. */
216  _UNUSED_ static void _utstring_BuildTableR(
217      const char *P_Needle, 
218      ssize_t P_NeedleLen, 
219      long *P_KMP_Table)
220  {
221      long i, j;
222  
223      i = P_NeedleLen - 1;
224      j = i + 1;
225      P_KMP_Table[i + 1] = j;
226      while (i >= 0)
227      {
228          while ( (j < P_NeedleLen) && (P_Needle[i] != P_Needle[j]) )
229          {
230             j = P_KMP_Table[j + 1];
231          }
232          i--;
233          j--;
234          if (i >= 0)
235          {
236              if (P_Needle[i] == P_Needle[j])
237              {
238                  P_KMP_Table[i + 1] = P_KMP_Table[j + 1];
239              }
240              else
241              {
242                  P_KMP_Table[i + 1] = j;
243              }
244          }
245          else
246          {
247              P_KMP_Table[i + 1] = j;
248          }
249      }
250  
251      return;
252  }
253  
254  
255  /* Search data from left to right. ( Multiple search mode. ) */
256  _UNUSED_ static long _utstring_find(
257      const char *P_Haystack, 
258      size_t P_HaystackLen, 
259      const char *P_Needle, 
260      size_t P_NeedleLen, 
261      long *P_KMP_Table)
262  {
263      long i, j;
264      long V_FindPosition = -1;
265  
266      /* Search from left to right. */
267      i = j = 0;
268      while ( (j < (int)P_HaystackLen) && (((P_HaystackLen - j) + i) >= P_NeedleLen) )
269      {
270          while ( (i > -1) && (P_Needle[i] != P_Haystack[j]) )
271          {
272              i = P_KMP_Table[i];
273          }
274          i++;
275          j++;
276          if (i >= (int)P_NeedleLen)
277          {
278              /* Found. */
279              V_FindPosition = j - i;
280              break;
281          }
282      }
283  
284      return V_FindPosition;
285  }
286  
287  
288  /* Search data from right to left. ( Multiple search mode. ) */
289  _UNUSED_ static long _utstring_findR(
290      const char *P_Haystack, 
291      size_t P_HaystackLen, 
292      const char *P_Needle, 
293      size_t P_NeedleLen, 
294      long *P_KMP_Table)
295  {
296      long i, j;
297      long V_FindPosition = -1;
298  
299      /* Search from right to left. */
300      j = (P_HaystackLen - 1);
301      i = (P_NeedleLen - 1);
302      while ( (j >= 0) && (j >= i) )
303      {
304          while ( (i < (int)P_NeedleLen) && (P_Needle[i] != P_Haystack[j]) )
305          {
306              i = P_KMP_Table[i + 1];
307          }
308          i--;
309          j--;
310          if (i < 0)
311          {
312              /* Found. */
313              V_FindPosition = j + 1;
314              break;
315          }
316      }
317  
318      return V_FindPosition;
319  }
320  
321  
322  /* Search data from left to right. ( One time search mode. ) */
323  _UNUSED_ static long utstring_find(
324      UT_string *s, 
325      long P_StartPosition,   /* Start from 0. -1 means last position. */
326      const char *P_Needle, 
327      ssize_t P_NeedleLen)
328  {
329      long V_StartPosition;
330      long V_HaystackLen;
331      long *V_KMP_Table;
332      long V_FindPosition = -1;
333  
334      if (P_StartPosition < 0)
335      {
336          V_StartPosition = s->i + P_StartPosition;
337      }
338      else
339      {
340          V_StartPosition = P_StartPosition;
341      }
342      V_HaystackLen = s->i - V_StartPosition;
343      if ( (V_HaystackLen >= P_NeedleLen) && (P_NeedleLen > 0) )
344      {
345          V_KMP_Table = (long *)malloc(sizeof(long) * (P_NeedleLen + 1));
346          if (V_KMP_Table != NULL)
347          {
348              _utstring_BuildTable(P_Needle, P_NeedleLen, V_KMP_Table);
349  
350              V_FindPosition = _utstring_find(s->d + V_StartPosition, 
351                                              V_HaystackLen, 
352                                              P_Needle, 
353                                              P_NeedleLen, 
354                                              V_KMP_Table);
355              if (V_FindPosition >= 0)
356              {
357                  V_FindPosition += V_StartPosition;
358              }
359  
360              free(V_KMP_Table);
361          }
362      }
363  
364      return V_FindPosition;
365  }
366  
367  
368  /* Search data from right to left. ( One time search mode. ) */
369  _UNUSED_ static long utstring_findR(
370      UT_string *s, 
371      long P_StartPosition,   /* Start from 0. -1 means last position. */
372      const char *P_Needle, 
373      ssize_t P_NeedleLen)
374  {
375      long V_StartPosition;
376      long V_HaystackLen;
377      long *V_KMP_Table;
378      long V_FindPosition = -1;
379  
380      if (P_StartPosition < 0)
381      {
382          V_StartPosition = s->i + P_StartPosition;
383      }
384      else
385      {
386          V_StartPosition = P_StartPosition;
387      }
388      V_HaystackLen = V_StartPosition + 1;
389      if ( (V_HaystackLen >= P_NeedleLen) && (P_NeedleLen > 0) )
390      {
391          V_KMP_Table = (long *)malloc(sizeof(long) * (P_NeedleLen + 1));
392          if (V_KMP_Table != NULL)
393          {
394              _utstring_BuildTableR(P_Needle, P_NeedleLen, V_KMP_Table);
395  
396              V_FindPosition = _utstring_findR(s->d, 
397                                               V_HaystackLen, 
398                                               P_Needle, 
399                                               P_NeedleLen, 
400                                               V_KMP_Table);
401  
402              free(V_KMP_Table);
403          }
404      }
405  
406      return V_FindPosition;
407  }
408  /*******************************************************************************
409   * end substring search functions                                              *
410   ******************************************************************************/
411  
412  #endif /* UTSTRING_H */