Back to home page

Enduro/X

 
 

    


0001 /*
0002 Copyright (c) 2008-2018, Troy D. Hanson   http://troydhanson.github.com/uthash/
0003 All rights reserved.
0004 
0005 Redistribution and use in source and binary forms, with or without
0006 modification, are permitted provided that the following conditions are met:
0007 
0008     * Redistributions of source code must retain the above copyright
0009       notice, this list of conditions and the following disclaimer.
0010 
0011 THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
0012 IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
0013 TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
0014 PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER
0015 OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
0016 EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
0017 PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
0018 PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
0019 LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
0020 NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
0021 SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
0022 */
0023 
0024 /* a dynamic string implementation using macros
0025  */
0026 #ifndef EXSTRING_H
0027 #define EXSTRING_H
0028 
0029 #define EXSTRING_VERSION 2.1.0
0030 
0031 #include <stdlib.h>
0032 #include <string.h>
0033 #include <stdio.h>
0034 #include <stdarg.h>
0035 
0036 #ifdef __GNUC__
0037 #define EXSTRING_UNUSED __attribute__((__unused__))
0038 #else
0039 #define EXSTRING_UNUSED
0040 #endif
0041 
0042 #ifndef oom
0043 #define oom() exit(-1)
0044 #endif
0045 
0046 typedef struct {
0047     char *d;  /* pointer to allocated buffer */
0048     size_t n; /* allocated capacity */
0049     size_t i; /* index of first unused byte */
0050 } EX_string;
0051 
0052 #define exstring_reserve(s,amt)                            \
0053 do {                                                       \
0054   if (((s)->n - (s)->i) < (size_t)(amt)) {                 \
0055     char *exstring_tmp = (char*)realloc(                   \
0056       (s)->d, (s)->n + (amt));                             \
0057     if (exstring_tmp == NULL) oom();                       \
0058     (s)->d = exstring_tmp;                                 \
0059     (s)->n += (amt);                                       \
0060   }                                                        \
0061 } while(0)
0062 
0063 #define exstring_init(s)                                   \
0064 do {                                                       \
0065   (s)->n = 0; (s)->i = 0; (s)->d = NULL;                   \
0066   exstring_reserve(s,100);                                 \
0067   (s)->d[0] = '\0';                                        \
0068 } while(0)
0069 
0070 #define exstring_done(s)                                   \
0071 do {                                                       \
0072   if ((s)->d != NULL) free((s)->d);                        \
0073   (s)->n = 0;                                              \
0074 } while(0)
0075 
0076 #define exstring_free(s)                                   \
0077 do {                                                       \
0078   exstring_done(s);                                        \
0079   free(s);                                                 \
0080 } while(0)
0081 
0082 #define exstring_new(s)                                    \
0083 do {                                                       \
0084    (s) = (EX_string*)malloc(sizeof(EX_string));            \
0085    if (!(s)) oom();                                        \
0086    exstring_init(s);                                       \
0087 } while(0)
0088 
0089 #define exstring_renew(s)                                  \
0090 do {                                                       \
0091    if (s) {                                                \
0092      exstring_clear(s);                                    \
0093    } else {                                                \
0094      exstring_new(s);                                      \
0095    }                                                       \
0096 } while(0)
0097 
0098 #define exstring_clear(s)                                  \
0099 do {                                                       \
0100   (s)->i = 0;                                              \
0101   (s)->d[0] = '\0';                                        \
0102 } while(0)
0103 
0104 #define exstring_bincpy(s,b,l)                             \
0105 do {                                                       \
0106   exstring_reserve((s),(l)+1);                             \
0107   if (l) memcpy(&(s)->d[(s)->i], b, l);                    \
0108   (s)->i += (l);                                           \
0109   (s)->d[(s)->i]='\0';                                     \
0110 } while(0)
0111 
0112 #define exstring_concat(dst,src)                                 \
0113 do {                                                             \
0114   exstring_reserve((dst),((src)->i)+1);                          \
0115   if ((src)->i) memcpy(&(dst)->d[(dst)->i], (src)->d, (src)->i); \
0116   (dst)->i += (src)->i;                                          \
0117   (dst)->d[(dst)->i]='\0';                                       \
0118 } while(0)
0119 
0120 /* Patched for Enduro/X */
0121 #define exstring_strcat(dst,src)                                     \
0122 do {                                                                 \
0123   int exstring_itmp = strlen(src);                                   \
0124   exstring_reserve((dst),exstring_itmp+1);                           \
0125   if (exstring_itmp) memcpy(&(dst)->d[(dst)->i], src, exstring_itmp);\
0126   (dst)->i += exstring_itmp;                                         \
0127   (dst)->d[(dst)->i]='\0';                                           \
0128 } while(0)
0129 
0130 
0131 #define exstring_len(s) ((s)->i)
0132 
0133 #define exstring_body(s) ((s)->d)
0134 
0135 EXSTRING_UNUSED static void exstring_printf_va(EX_string *s, const char *fmt, va_list ap) {
0136    int n;
0137    va_list cp;
0138    for (;;) {
0139 #ifdef _WIN32
0140       cp = ap;
0141 #else
0142       va_copy(cp, ap);
0143 #endif
0144       n = vsnprintf (&s->d[s->i], s->n-s->i, fmt, cp);
0145       va_end(cp);
0146 
0147       if ((n > -1) && ((size_t) n < (s->n-s->i))) {
0148         s->i += n;
0149         return;
0150       }
0151 
0152       /* Else try again with more space. */
0153       if (n > -1) exstring_reserve(s,n+1); /* exact */
0154       else exstring_reserve(s,(s->n)*2);   /* 2x */
0155    }
0156 }
0157 #ifdef __GNUC__
0158 /* support printf format checking (2=the format string, 3=start of varargs) */
0159 static void exstring_printf(EX_string *s, const char *fmt, ...)
0160   __attribute__ (( format( printf, 2, 3) ));
0161 #endif
0162 EXSTRING_UNUSED static void exstring_printf(EX_string *s, const char *fmt, ...) {
0163    va_list ap;
0164    va_start(ap,fmt);
0165    exstring_printf_va(s,fmt,ap);
0166    va_end(ap);
0167 }
0168 
0169 /*******************************************************************************
0170  * begin substring search functions                                            *
0171  ******************************************************************************/
0172 /* Build KMP table from left to right. */
0173 EXSTRING_UNUSED static void _exstring_BuildTable(
0174     const char *P_Needle,
0175     size_t P_NeedleLen,
0176     long *P_KMP_Table)
0177 {
0178     long i, j;
0179 
0180     i = 0;
0181     j = i - 1;
0182     P_KMP_Table[i] = j;
0183     while (i < (long) P_NeedleLen)
0184     {
0185         while ( (j > -1) && (P_Needle[i] != P_Needle[j]) )
0186         {
0187            j = P_KMP_Table[j];
0188         }
0189         i++;
0190         j++;
0191         if (i < (long) P_NeedleLen)
0192         {
0193             if (P_Needle[i] == P_Needle[j])
0194             {
0195                 P_KMP_Table[i] = P_KMP_Table[j];
0196             }
0197             else
0198             {
0199                 P_KMP_Table[i] = j;
0200             }
0201         }
0202         else
0203         {
0204             P_KMP_Table[i] = j;
0205         }
0206     }
0207 
0208     return;
0209 }
0210 
0211 
0212 /* Build KMP table from right to left. */
0213 EXSTRING_UNUSED static void _exstring_BuildTableR(
0214     const char *P_Needle,
0215     size_t P_NeedleLen,
0216     long *P_KMP_Table)
0217 {
0218     long i, j;
0219 
0220     i = P_NeedleLen - 1;
0221     j = i + 1;
0222     P_KMP_Table[i + 1] = j;
0223     while (i >= 0)
0224     {
0225         while ( (j < (long) P_NeedleLen) && (P_Needle[i] != P_Needle[j]) )
0226         {
0227            j = P_KMP_Table[j + 1];
0228         }
0229         i--;
0230         j--;
0231         if (i >= 0)
0232         {
0233             if (P_Needle[i] == P_Needle[j])
0234             {
0235                 P_KMP_Table[i + 1] = P_KMP_Table[j + 1];
0236             }
0237             else
0238             {
0239                 P_KMP_Table[i + 1] = j;
0240             }
0241         }
0242         else
0243         {
0244             P_KMP_Table[i + 1] = j;
0245         }
0246     }
0247 
0248     return;
0249 }
0250 
0251 
0252 /* Search data from left to right. ( Multiple search mode. ) */
0253 EXSTRING_UNUSED static long _exstring_find(
0254     const char *P_Haystack,
0255     size_t P_HaystackLen,
0256     const char *P_Needle,
0257     size_t P_NeedleLen,
0258     long *P_KMP_Table)
0259 {
0260     long i, j;
0261     long V_FindPosition = -1;
0262 
0263     /* Search from left to right. */
0264     i = j = 0;
0265     while ( (j < (int)P_HaystackLen) && (((P_HaystackLen - j) + i) >= P_NeedleLen) )
0266     {
0267         while ( (i > -1) && (P_Needle[i] != P_Haystack[j]) )
0268         {
0269             i = P_KMP_Table[i];
0270         }
0271         i++;
0272         j++;
0273         if (i >= (int)P_NeedleLen)
0274         {
0275             /* Found. */
0276             V_FindPosition = j - i;
0277             break;
0278         }
0279     }
0280 
0281     return V_FindPosition;
0282 }
0283 
0284 
0285 /* Search data from right to left. ( Multiple search mode. ) */
0286 EXSTRING_UNUSED static long _exstring_findR(
0287     const char *P_Haystack,
0288     size_t P_HaystackLen,
0289     const char *P_Needle,
0290     size_t P_NeedleLen,
0291     long *P_KMP_Table)
0292 {
0293     long i, j;
0294     long V_FindPosition = -1;
0295 
0296     /* Search from right to left. */
0297     j = (P_HaystackLen - 1);
0298     i = (P_NeedleLen - 1);
0299     while ( (j >= 0) && (j >= i) )
0300     {
0301         while ( (i < (int)P_NeedleLen) && (P_Needle[i] != P_Haystack[j]) )
0302         {
0303             i = P_KMP_Table[i + 1];
0304         }
0305         i--;
0306         j--;
0307         if (i < 0)
0308         {
0309             /* Found. */
0310             V_FindPosition = j + 1;
0311             break;
0312         }
0313     }
0314 
0315     return V_FindPosition;
0316 }
0317 
0318 
0319 /* Search data from left to right. ( One time search mode. ) */
0320 EXSTRING_UNUSED static long exstring_find(
0321     EX_string *s,
0322     long P_StartPosition,   /* Start from 0. -1 means last position. */
0323     const char *P_Needle,
0324     size_t P_NeedleLen)
0325 {
0326     long V_StartPosition;
0327     long V_HaystackLen;
0328     long *V_KMP_Table;
0329     long V_FindPosition = -1;
0330 
0331     if (P_StartPosition < 0)
0332     {
0333         V_StartPosition = s->i + P_StartPosition;
0334     }
0335     else
0336     {
0337         V_StartPosition = P_StartPosition;
0338     }
0339     V_HaystackLen = s->i - V_StartPosition;
0340     if ( (V_HaystackLen >= (long) P_NeedleLen) && (P_NeedleLen > 0) )
0341     {
0342         V_KMP_Table = (long *)malloc(sizeof(long) * (P_NeedleLen + 1));
0343         if (V_KMP_Table != NULL)
0344         {
0345             _exstring_BuildTable(P_Needle, P_NeedleLen, V_KMP_Table);
0346 
0347             V_FindPosition = _exstring_find(s->d + V_StartPosition,
0348                                             V_HaystackLen,
0349                                             P_Needle,
0350                                             P_NeedleLen,
0351                                             V_KMP_Table);
0352             if (V_FindPosition >= 0)
0353             {
0354                 V_FindPosition += V_StartPosition;
0355             }
0356 
0357             free(V_KMP_Table);
0358         }
0359     }
0360 
0361     return V_FindPosition;
0362 }
0363 
0364 
0365 /* Search data from right to left. ( One time search mode. ) */
0366 EXSTRING_UNUSED static long exstring_findR(
0367     EX_string *s,
0368     long P_StartPosition,   /* Start from 0. -1 means last position. */
0369     const char *P_Needle,
0370     size_t P_NeedleLen)
0371 {
0372     long V_StartPosition;
0373     long V_HaystackLen;
0374     long *V_KMP_Table;
0375     long V_FindPosition = -1;
0376 
0377     if (P_StartPosition < 0)
0378     {
0379         V_StartPosition = s->i + P_StartPosition;
0380     }
0381     else
0382     {
0383         V_StartPosition = P_StartPosition;
0384     }
0385     V_HaystackLen = V_StartPosition + 1;
0386     if ( (V_HaystackLen >= (long) P_NeedleLen) && (P_NeedleLen > 0) )
0387     {
0388         V_KMP_Table = (long *)malloc(sizeof(long) * (P_NeedleLen + 1));
0389         if (V_KMP_Table != NULL)
0390         {
0391             _exstring_BuildTableR(P_Needle, P_NeedleLen, V_KMP_Table);
0392 
0393             V_FindPosition = _exstring_findR(s->d,
0394                                              V_HaystackLen,
0395                                              P_Needle,
0396                                              P_NeedleLen,
0397                                              V_KMP_Table);
0398 
0399             free(V_KMP_Table);
0400         }
0401     }
0402 
0403     return V_FindPosition;
0404 }
0405 /*******************************************************************************
0406  * end substring search functions                                              *
0407  ******************************************************************************/
0408 
0409 #endif /* EXSTRING_H */