cb22561995-10-11Fredrik Hübinette (Hubbe) /*\
06983f1996-09-22Fredrik Hübinette (Hubbe) ||| This file a part of Pike, and is copyright by Fredrik Hubinette ||| Pike is distributed as GPL (General Public License)
cb22561995-10-11Fredrik Hübinette (Hubbe) ||| See the files COPYING and DISCLAIMER for more information. \*/
5267b71995-08-09Fredrik Hübinette (Hubbe) #include "global.h" #include "memory.h" #include "error.h"
bb55f81997-03-16Fredrik Hübinette (Hubbe) #include "pike_macros.h"
5267b71995-08-09Fredrik Hübinette (Hubbe)  char *xalloc(SIZE_T size) { char *ret; if(!size) return 0; ret=(char *)malloc(size); if(ret) return ret; error("Out of memory.\n"); return 0; }
36feac1997-03-06Fredrik Hübinette (Hubbe) void swap(char *a, char *b, INT32 size) { int tmp; char tmpbuf[1024]; while(size) { tmp=MINIMUM((long)sizeof(tmpbuf), size); MEMCPY(tmpbuf,a,tmp); MEMCPY(b,a,tmp); MEMCPY(b,tmpbuf,tmp); size-=tmp; a+=tmp; b+=tmp; } } void reverse(char *memory, INT32 nitems, INT32 size) { #define DOSIZE(X,Y) \ case X: \ { \ struct Y { char tt[X]; }; \ struct Y tmp; \ struct Y *start=(struct Y *) memory; \ struct Y *end=start+nitems-1; \ while(start<end){tmp=*start;*(start++)=*end;*(end--)=tmp;} \ break; \ } switch(size) { DOSIZE(1,TMP1) DOSIZE(2,TMP2) DOSIZE(4,TMP4) DOSIZE(8,TMP8) default: { char *start = (char *) memory; char *end=start+(nitems-1)*size; while(start<end) { swap(start,end,size); start+=size; end-=size; } } } }
b0ddc51996-06-21Fredrik Hübinette (Hubbe)  /* * 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);
36feac1997-03-06Fredrik Hübinette (Hubbe) #undef DOSIZE
b0ddc51996-06-21Fredrik Hübinette (Hubbe) #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); }
5267b71995-08-09Fredrik Hübinette (Hubbe) 
b0ddc51996-06-21Fredrik Hübinette (Hubbe)  MEMCPY(memory, tmp, size * nitems); free(tmp); }
5267b71995-08-09Fredrik Hübinette (Hubbe)  unsigned INT32 hashmem(const unsigned char *a,INT32 len,INT32 mlen) { unsigned INT32 ret; ret=9248339*len; if(len<mlen) mlen=len; switch(mlen&7) { case 7: ret^=*(a++); case 6: ret^=(ret<<4)+*(a++); case 5: ret^=(ret<<7)+*(a++); case 4: ret^=(ret<<6)+*(a++); case 3: ret^=(ret<<3)+*(a++); case 2: ret^=(ret<<7)+*(a++); case 1: ret^=(ret<<5)+*(a++); } #ifdef HANDLES_UNALIGNED_MEMORY_ACCESS {
cb22561995-10-11Fredrik Hübinette (Hubbe)  unsigned int *b; b=(unsigned int *)a; for(mlen>>=3;--mlen>=0;) { ret^=(ret<<7)+*(b++); ret^=(ret>>6)+*(b++); }
5267b71995-08-09Fredrik Hübinette (Hubbe)  } #else for(mlen>>=3;--mlen>=0;) { ret^=(ret<<7)+((((((*(a++)<<3)+*(a++))<<4)+*(a++))<<5)+*(a++)); ret^=(ret>>6)+((((((*(a++)<<3)+*(a++))<<4)+*(a++))<<5)+*(a++)); } #endif return ret; } unsigned INT32 hashstr(const unsigned char *str,INT32 maxn) { unsigned INT32 ret,c; ret=str++[0]; for(; maxn>=0; maxn--) { c=str++[0]; if(!c) break; ret ^= ( ret << 4 ) + c ; ret &= 0x7fffffff; } return ret; }
b0ddc51996-06-21Fredrik Hübinette (Hubbe)  /* * 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;
d63edd1996-08-06Fredrik Hübinette (Hubbe)  unsigned char *q;
b0ddc51996-06-21Fredrik Hübinette (Hubbe)  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];
d63edd1996-08-06Fredrik Hübinette (Hubbe)  q=(unsigned char *)needle;
b0ddc51996-06-21Fredrik Hübinette (Hubbe)  #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
d63edd1996-08-06Fredrik Hübinette (Hubbe)  tmp=EXTRACT_INT(q);
b0ddc51996-06-21Fredrik Hübinette (Hubbe)  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;
7022d81997-04-06Fredrik Hübinette (Hubbe)  end=haystack+haystacklen;
b0ddc51996-06-21Fredrik Hübinette (Hubbe)  q=haystack + s->max - sizeof(INT32); q=(char *)( ((long)q) & -sizeof(INT32));
7022d81997-04-06Fredrik Hübinette (Hubbe)  for(;q<=end-sizeof(INT32);q+=s->max)
b0ddc51996-06-21Fredrik Hübinette (Hubbe)  { 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); }
9dd5001996-12-06Fredrik Hübinette (Hubbe)  void memfill(char *to, INT32 tolen, char *from, INT32 fromlen, INT32 offset) { if(fromlen==1) { MEMSET(to, *from, tolen); } else if(tolen>0) { INT32 tmp=MINIMUM(tolen, fromlen - offset); MEMCPY(to, from + offset, tmp); to+=tmp; tolen-=tmp; if(tolen > 0) { tmp=MINIMUM(tolen, fromlen); MEMCPY(to, from, tmp); from=to; to+=tmp; tolen-=tmp; while(tolen>0) { tmp=MINIMUM(tolen, fromlen); MEMCPY(to, from, MINIMUM(tolen, fromlen)); fromlen+=tmp; tolen-=tmp; to+=tmp; } } } }