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