123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394 |
- /*
- Copyright (c) 2008-2014, Troy D. Hanson http://troydhanson.github.com/uthash/
- All rights reserved.
- Redistribution and use in source and binary forms, with or without
- modification, are permitted provided that the following conditions are met:
- * Redistributions of source code must retain the above copyright
- notice, this list of conditions and the following disclaimer.
- THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
- IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
- TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
- PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER
- OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
- EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
- PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
- PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
- LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
- NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
- SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
- /* a dynamic string implementation using macros
- */
- #ifndef UTSTRING_H
- #define UTSTRING_H
- #define UTSTRING_VERSION 1.9.9
- #ifdef __GNUC__
- #define _UNUSED_ __attribute__ ((__unused__))
- #else
- #define _UNUSED_
- #endif
- #include <stdlib.h>
- #include <string.h>
- #include <stdio.h>
- #include <stdarg.h>
- #define oom() exit(-1)
- typedef struct {
- char *d;
- size_t n; /* allocd size */
- size_t i; /* index of first unused byte */
- } UT_string;
- #define utstring_reserve(s,amt) \
- do { \
- if (((s)->n - (s)->i) < (size_t)(amt)) { \
- (s)->d = (char*)realloc((s)->d, (s)->n + amt); \
- if ((s)->d == NULL) oom(); \
- (s)->n += amt; \
- } \
- } while(0)
- #define utstring_init(s) \
- do { \
- (s)->n = 0; (s)->i = 0; (s)->d = NULL; \
- utstring_reserve(s,100); \
- (s)->d[0] = '\0'; \
- } while(0)
- #define utstring_done(s) \
- do { \
- if ((s)->d != NULL) free((s)->d); \
- (s)->n = 0; \
- } while(0)
- #define utstring_free(s) \
- do { \
- utstring_done(s); \
- free(s); \
- } while(0)
- #define utstring_new(s) \
- do { \
- s = (UT_string*)calloc(sizeof(UT_string),1); \
- if (!s) oom(); \
- utstring_init(s); \
- } while(0)
- #define utstring_renew(s) \
- do { \
- if (s) { \
- utstring_clear(s); \
- } else { \
- utstring_new(s); \
- } \
- } while(0)
- #define utstring_clear(s) \
- do { \
- (s)->i = 0; \
- (s)->d[0] = '\0'; \
- } while(0)
- #define utstring_bincpy(s,b,l) \
- do { \
- utstring_reserve((s),(l)+1); \
- if (l) memcpy(&(s)->d[(s)->i], b, l); \
- (s)->i += l; \
- (s)->d[(s)->i]='\0'; \
- } while(0)
- #define utstring_concat(dst,src) \
- do { \
- utstring_reserve((dst),((src)->i)+1); \
- if ((src)->i) memcpy(&(dst)->d[(dst)->i], (src)->d, (src)->i); \
- (dst)->i += (src)->i; \
- (dst)->d[(dst)->i]='\0'; \
- } while(0)
- #define utstring_len(s) ((unsigned)((s)->i))
- #define utstring_body(s) ((s)->d)
- _UNUSED_ static void utstring_printf_va(UT_string *s, const char *fmt, va_list ap) {
- int n;
- va_list cp;
- while (1) {
- #ifdef _WIN32
- cp = ap;
- #else
- va_copy(cp, ap);
- #endif
- n = vsnprintf (&s->d[s->i], s->n-s->i, fmt, cp);
- va_end(cp);
- if ((n > -1) && ((size_t) n < (s->n-s->i))) {
- s->i += n;
- return;
- }
- /* Else try again with more space. */
- if (n > -1) utstring_reserve(s,n+1); /* exact */
- else utstring_reserve(s,(s->n)*2); /* 2x */
- }
- }
- #ifdef __GNUC__
- /* support printf format checking (2=the format string, 3=start of varargs) */
- static void utstring_printf(UT_string *s, const char *fmt, ...)
- __attribute__ (( format( printf, 2, 3) ));
- #endif
- _UNUSED_ static void utstring_printf(UT_string *s, const char *fmt, ...) {
- va_list ap;
- va_start(ap,fmt);
- utstring_printf_va(s,fmt,ap);
- va_end(ap);
- }
- /*******************************************************************************
- * begin substring search functions *
- ******************************************************************************/
- /* Build KMP table from left to right. */
- _UNUSED_ static void _utstring_BuildTable(
- const char *P_Needle,
- size_t P_NeedleLen,
- long *P_KMP_Table)
- {
- long i, j;
- i = 0;
- j = i - 1;
- P_KMP_Table[i] = j;
- while (i < (long) P_NeedleLen)
- {
- while ( (j > -1) && (P_Needle[i] != P_Needle[j]) )
- {
- j = P_KMP_Table[j];
- }
- i++;
- j++;
- if (i < (long) P_NeedleLen)
- {
- if (P_Needle[i] == P_Needle[j])
- {
- P_KMP_Table[i] = P_KMP_Table[j];
- }
- else
- {
- P_KMP_Table[i] = j;
- }
- }
- else
- {
- P_KMP_Table[i] = j;
- }
- }
- return;
- }
- /* Build KMP table from right to left. */
- _UNUSED_ static void _utstring_BuildTableR(
- const char *P_Needle,
- size_t P_NeedleLen,
- long *P_KMP_Table)
- {
- long i, j;
- i = P_NeedleLen - 1;
- j = i + 1;
- P_KMP_Table[i + 1] = j;
- while (i >= 0)
- {
- while ( (j < (long) P_NeedleLen) && (P_Needle[i] != P_Needle[j]) )
- {
- j = P_KMP_Table[j + 1];
- }
- i--;
- j--;
- if (i >= 0)
- {
- if (P_Needle[i] == P_Needle[j])
- {
- P_KMP_Table[i + 1] = P_KMP_Table[j + 1];
- }
- else
- {
- P_KMP_Table[i + 1] = j;
- }
- }
- else
- {
- P_KMP_Table[i + 1] = j;
- }
- }
- return;
- }
- /* Search data from left to right. ( Multiple search mode. ) */
- _UNUSED_ static long _utstring_find(
- const char *P_Haystack,
- size_t P_HaystackLen,
- const char *P_Needle,
- size_t P_NeedleLen,
- long *P_KMP_Table)
- {
- long i, j;
- long V_FindPosition = -1;
- /* Search from left to right. */
- i = j = 0;
- while ( (j < (int)P_HaystackLen) && (((P_HaystackLen - j) + i) >= P_NeedleLen) )
- {
- while ( (i > -1) && (P_Needle[i] != P_Haystack[j]) )
- {
- i = P_KMP_Table[i];
- }
- i++;
- j++;
- if (i >= (int)P_NeedleLen)
- {
- /* Found. */
- V_FindPosition = j - i;
- break;
- }
- }
- return V_FindPosition;
- }
- /* Search data from right to left. ( Multiple search mode. ) */
- _UNUSED_ static long _utstring_findR(
- const char *P_Haystack,
- size_t P_HaystackLen,
- const char *P_Needle,
- size_t P_NeedleLen,
- long *P_KMP_Table)
- {
- long i, j;
- long V_FindPosition = -1;
- /* Search from right to left. */
- j = (P_HaystackLen - 1);
- i = (P_NeedleLen - 1);
- while ( (j >= 0) && (j >= i) )
- {
- while ( (i < (int)P_NeedleLen) && (P_Needle[i] != P_Haystack[j]) )
- {
- i = P_KMP_Table[i + 1];
- }
- i--;
- j--;
- if (i < 0)
- {
- /* Found. */
- V_FindPosition = j + 1;
- break;
- }
- }
- return V_FindPosition;
- }
- /* Search data from left to right. ( One time search mode. ) */
- _UNUSED_ static long utstring_find(
- UT_string *s,
- long P_StartPosition, /* Start from 0. -1 means last position. */
- const char *P_Needle,
- size_t P_NeedleLen)
- {
- long V_StartPosition;
- long V_HaystackLen;
- long *V_KMP_Table;
- long V_FindPosition = -1;
- if (P_StartPosition < 0)
- {
- V_StartPosition = s->i + P_StartPosition;
- }
- else
- {
- V_StartPosition = P_StartPosition;
- }
- V_HaystackLen = s->i - V_StartPosition;
- if ( (V_HaystackLen >= (long) P_NeedleLen) && (P_NeedleLen > 0) )
- {
- V_KMP_Table = (long *)malloc(sizeof(long) * (P_NeedleLen + 1));
- if (V_KMP_Table != NULL)
- {
- _utstring_BuildTable(P_Needle, P_NeedleLen, V_KMP_Table);
- V_FindPosition = _utstring_find(s->d + V_StartPosition,
- V_HaystackLen,
- P_Needle,
- P_NeedleLen,
- V_KMP_Table);
- if (V_FindPosition >= 0)
- {
- V_FindPosition += V_StartPosition;
- }
- free(V_KMP_Table);
- }
- }
- return V_FindPosition;
- }
- /* Search data from right to left. ( One time search mode. ) */
- _UNUSED_ static long utstring_findR(
- UT_string *s,
- long P_StartPosition, /* Start from 0. -1 means last position. */
- const char *P_Needle,
- size_t P_NeedleLen)
- {
- long V_StartPosition;
- long V_HaystackLen;
- long *V_KMP_Table;
- long V_FindPosition = -1;
- if (P_StartPosition < 0)
- {
- V_StartPosition = s->i + P_StartPosition;
- }
- else
- {
- V_StartPosition = P_StartPosition;
- }
- V_HaystackLen = V_StartPosition + 1;
- if ( (V_HaystackLen >= (long) P_NeedleLen) && (P_NeedleLen > 0) )
- {
- V_KMP_Table = (long *)malloc(sizeof(long) * (P_NeedleLen + 1));
- if (V_KMP_Table != NULL)
- {
- _utstring_BuildTableR(P_Needle, P_NeedleLen, V_KMP_Table);
- V_FindPosition = _utstring_findR(s->d,
- V_HaystackLen,
- P_Needle,
- P_NeedleLen,
- V_KMP_Table);
- free(V_KMP_Table);
- }
- }
- return V_FindPosition;
- }
- /*******************************************************************************
- * end substring search functions *
- ******************************************************************************/
- #endif /* UTSTRING_H */
|