0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011
0012
0013
0014
0015
0016
0017
0018
0019
0020
0021
0022
0023
0024
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;
0048 size_t n;
0049 size_t i;
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
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
0153 if (n > -1) exstring_reserve(s,n+1);
0154 else exstring_reserve(s,(s->n)*2);
0155 }
0156 }
0157 #ifdef __GNUC__
0158
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
0171
0172
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
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
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
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
0276 V_FindPosition = j - i;
0277 break;
0278 }
0279 }
0280
0281 return V_FindPosition;
0282 }
0283
0284
0285
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
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
0310 V_FindPosition = j + 1;
0311 break;
0312 }
0313 }
0314
0315 return V_FindPosition;
0316 }
0317
0318
0319
0320 EXSTRING_UNUSED static long exstring_find(
0321 EX_string *s,
0322 long P_StartPosition,
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
0366 EXSTRING_UNUSED static long exstring_findR(
0367 EX_string *s,
0368 long P_StartPosition,
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
0407
0408
0409 #endif