diff --git a/src/memory.c b/src/memory.c index b02eb73c2fc9799e6cc5c2bff8431a71f36b45a6..a130aa5185dc0f913b2b43672113ff6a153d7b9c 100644 --- a/src/memory.c +++ b/src/memory.c @@ -6,6 +6,7 @@ #include "global.h" #include "memory.h" #include "error.h" +#include "macros.h" char *xalloc(SIZE_T size) { @@ -75,7 +76,9 @@ void reorder(char *memory,INT32 nitems,INT32 size,INT32 *order) } } -#else +#endif + +#if 0 /* * This function may NOT change 'order' * This function is probably too slow, but it does not use @@ -259,7 +262,45 @@ void reorder(char *memory, INT32 nitems, INT32 size,INT32 *order) } } } +#endif + +#if 1 +/* + * This function may NOT change 'order' + * This function is hopefully fast enough... + */ +void reorder(char *memory, INT32 nitems, INT32 size,INT32 *order) +{ + INT32 e; + char *tmp; + tmp=xalloc(size * nitems); + +#define DOSIZE(X,Y) \ + case X: \ + { \ + struct Y { char tt[X]; }; \ + struct Y *from=(struct Y *) memory; \ + struct Y *to=(struct Y *) tmp; \ + for(e=0;e<nitems;e++) to[e]=from[order[e]]; \ + break; \ + } + + + switch(size) + { + DOSIZE(1,TMP1) + DOSIZE(2,TMP2) + DOSIZE(4,TMP4) + DOSIZE(8,TMP8) + DOSIZE(16,TMP16) + + default: + for(e=0;e<nitems;e++) MEMCPY(tmp+e*size, memory+order[e]*size, size); + } + MEMCPY(memory, tmp, size * nitems); + free(tmp); +} #endif unsigned INT32 hashmem(const unsigned char *a,INT32 len,INT32 mlen) @@ -315,3 +356,172 @@ unsigned INT32 hashstr(const unsigned char *str,INT32 maxn) return ret; } + + +/* + * a quick memory search function. + * Written by Fredrik Hubinette (hubbe@lysator.liu.se) + */ +void init_memsearch(struct mem_searcher *s, + char *needle, + SIZE_T needlelen, + SIZE_T max_haystacklen) +{ + s->needle=needle; + s->needlelen=needlelen; + + switch(needlelen) + { + case 0: s->method=no_search; break; + case 1: s->method=use_memchr; break; + case 2: + case 3: + case 4: + case 5: + case 6: s->method=memchr_and_memcmp; break; + default: + if(max_haystacklen <= needlelen + 64) + { + s->method=memchr_and_memcmp; + }else{ + INT32 tmp, h; + unsigned INT32 hsize, e, max; + char *q; + struct link *ptr; + + hsize=52+(max_haystacklen >> 7) - (needlelen >> 8); + max =13+(max_haystacklen >> 4) - (needlelen >> 5); + + if(hsize > NELEM(s->set)) + { + hsize=NELEM(s->set); + }else{ + for(e=8;e<hsize;e+=e); + hsize=e; + } + + for(e=0;e<hsize;e++) s->set[e]=0; + hsize--; + + if(max > needlelen) max=needlelen; + max=(max-sizeof(INT32)+1) & -sizeof(INT32); + if(max > MEMSEARCH_LINKS) max=MEMSEARCH_LINKS; + + ptr=& s->links[0]; + + q=needle; + +#if BYTEORDER == 4321 + for(tmp=e=0;e<sizeof(INT32)-1;e++) + { + tmp<<=8; + tmp|=*(q++); + } +#endif + + for(e=0;e<max;e++) + { +#if BYTEORDER == 4321 + tmp<<=8; + tmp|=*(q++); +#else + tmp=EXTRACT_INT((unsigned char *)q); + q++; +#endif + h=tmp; + h+=h>>7; + h+=h>>17; + h&=hsize; + + ptr->offset=e; + ptr->key=tmp; + ptr->next=s->set[h]; + s->set[h]=ptr; + ptr++; + } + s->hsize=hsize; + s->max=max; + s->method=hubbe_search; + } + } +} + + +char *memory_search(struct mem_searcher *s, + char *haystack, + SIZE_T haystacklen) +{ + if(s->needlelen > haystacklen) return 0; + + switch(s->method) + { + case no_search: + return haystack; + + case use_memchr: + return MEMCHR(haystack,s->needle[0],haystacklen); + + case memchr_and_memcmp: + { + char *end,c,*needle; + SIZE_T needlelen; + + needle=s->needle; + needlelen=s->needlelen; + + end=haystack + haystacklen - needlelen+1; + c=needle[0]; + needle++; + needlelen--; + while((haystack=MEMCHR(haystack,c,end-haystack))) + if(!MEMCMP(++haystack,needle,needlelen)) + return haystack-1; + + return 0; + } + + case hubbe_search: + { + INT32 tmp, h; + char *q, *end; + register struct link *ptr; + + end=haystack+haystacklen+1; + q=haystack + s->max - sizeof(INT32); + q=(char *)( ((long)q) & -sizeof(INT32)); + for(;q<end-sizeof(INT32)+1;q+=s->max) + { + h=tmp=*(INT32 *)q; + + h+=h>>7; + h+=h>>17; + h&=s->hsize; + + for(ptr=s->set[h];ptr;ptr=ptr->next) + { + char *where; + + if(ptr->key != tmp) continue; + + where=q-ptr->offset; + if(where<haystack) continue; + if(where+s->needlelen>end) return 0; + + if(!MEMCMP(where,s->needle,s->needlelen)) + return where; + } + } + } + } + return 0; +} + +char *my_memmem(char *needle, + SIZE_T needlelen, + char *haystack, + SIZE_T haystacklen) +{ + struct mem_searcher tmp; + init_memsearch(&tmp, needle, needlelen, haystacklen); + return memory_search(&tmp, haystack, haystacklen); +} diff --git a/src/memory.h b/src/memory.h index b93106c27fcde7d6b1d3083f75a760eade4087fc..b93be67a42f7913d4010618d833552a2bd0c787b 100644 --- a/src/memory.h +++ b/src/memory.h @@ -8,11 +8,48 @@ #include "types.h" +#define MEMSEARCH_LINKS 512 + +struct link +{ + struct link *next; + INT32 key, offset; +}; + +enum methods { + no_search, + use_memchr, + memchr_and_memcmp, + hubbe_search +}; + +struct mem_searcher +{ + enum methods method; + char *needle; + SIZE_T needlelen; + unsigned INT32 hsize, max; + struct link links[MEMSEARCH_LINKS]; + struct link *set[MEMSEARCH_LINKS]; +}; + /* Prototypes begin here */ char *xalloc(SIZE_T size); void reorder(char *memory,INT32 nitems,INT32 size,INT32 *order); +void reorder(char *memory, INT32 nitems, INT32 size,INT32 *order); unsigned INT32 hashmem(const unsigned char *a,INT32 len,INT32 mlen); unsigned INT32 hashstr(const unsigned char *str,INT32 maxn); +void init_memsearch(struct mem_searcher *s, + char *needle, + SIZE_T needlelen, + SIZE_T max_haystacklen); +char *memory_search(struct mem_searcher *s, + char *haystack, + SIZE_T haystacklen); +char *my_memmem(char *needle, + SIZE_T needlelen, + char *haystack, + SIZE_T haystacklen); /* Prototypes end here */ #endif