cb2256 | 1995-10-11 | Fredrik Hübinette (Hubbe) | | |
06983f | 1996-09-22 | Fredrik Hübinette (Hubbe) | | ||| This file a part of Pike, and is copyright by Fredrik Hubinette
||| Pike is distributed as GPL (General Public License)
|
cb2256 | 1995-10-11 | Fredrik Hübinette (Hubbe) | | ||| See the files COPYING and DISCLAIMER for more information.
\*/
|
5267b7 | 1995-08-09 | Fredrik Hübinette (Hubbe) | | #include "global.h"
#include "stralloc.h"
#include "macros.h"
#include "dynamic_buffer.h"
#include "macros.h"
#include "memory.h"
#include "error.h"
|
06983f | 1996-09-22 | Fredrik Hübinette (Hubbe) | | static struct pike_string *base_table[HTABLE_SIZE];
|
5267b7 | 1995-08-09 | Fredrik Hübinette (Hubbe) | | static unsigned INT32 full_hash_value;
static unsigned int StrHash(const char *s,int len)
{
full_hash_value=hashmem((unsigned char *)s, len, 20);
return full_hash_value % HTABLE_SIZE;
}
#ifdef DEBUG
|
06983f | 1996-09-22 | Fredrik Hübinette (Hubbe) | | void check_string(struct pike_string *s)
|
5267b7 | 1995-08-09 | Fredrik Hübinette (Hubbe) | | {
|
dd1981 | 1996-08-12 | Fredrik Hübinette (Hubbe) | | StrHash(s->str, s->len);
if(full_hash_value != s->hval)
fatal("Hash value changed?\n");
|
5267b7 | 1995-08-09 | Fredrik Hübinette (Hubbe) | | if(debug_findstring(s) !=s)
fatal("Shared string not shared.\n");
|
0d202a | 1995-10-20 | Fredrik Hübinette (Hubbe) | | if(s->str[s->len])
fatal("Shared string is not zero terminated properly.\n");
|
5267b7 | 1995-08-09 | Fredrik Hübinette (Hubbe) | | }
|
624d09 | 1996-02-24 | Fredrik Hübinette (Hubbe) | | void verify_shared_strings_tables()
|
5267b7 | 1995-08-09 | Fredrik Hübinette (Hubbe) | | {
unsigned int e, h;
|
06983f | 1996-09-22 | Fredrik Hübinette (Hubbe) | | struct pike_string *s;
|
5267b7 | 1995-08-09 | Fredrik Hübinette (Hubbe) | |
for(e=0;e<HTABLE_SIZE;e++)
{
h=0;
for(s=base_table[e];s;s=s->next)
{
h++;
if(s->len < 0)
fatal("Shared string shorter than zero bytes.\n");
if(s->refs <= 0)
fatal("Shared string had too few references.\n");
if(s->str[s->len])
fatal("Shared string didn't end with a zero.\n");
if(StrHash(s->str, s->len) != e)
fatal("Shared string hashed to wrong place.\n");
if(s->hval != full_hash_value)
fatal("Shared string hashed to other number.\n");
if(h>10000)
{
|
06983f | 1996-09-22 | Fredrik Hübinette (Hubbe) | | struct pike_string *s2;
|
5267b7 | 1995-08-09 | Fredrik Hübinette (Hubbe) | | for(s2=s;s2;s2=s2->next)
if(s2 == s)
fatal("Shared string table is cyclic.\n");
h=0;
}
}
}
}
#endif
|
06983f | 1996-09-22 | Fredrik Hübinette (Hubbe) | | static struct pike_string *internal_findstring(const char *s,int len,int h)
|
5267b7 | 1995-08-09 | Fredrik Hübinette (Hubbe) | | {
|
06983f | 1996-09-22 | Fredrik Hübinette (Hubbe) | | struct pike_string *curr,**prev, **base;
|
5267b7 | 1995-08-09 | Fredrik Hübinette (Hubbe) | |
for(base = prev = base_table + h;( curr=*prev ); prev=&curr->next)
{
#ifdef DEBUG
if(curr->refs<1)
fatal("String with no references.\n");
#endif
if (full_hash_value == curr->hval &&
len==curr->len &&
!MEMCMP(curr->str, s,len))
{
*prev = curr->next;
curr->next = *base;
*base = curr;
return curr;
}
}
return 0;
}
|
ca74dd | 1996-10-08 | Fredrik Hübinette (Hubbe) | | struct pike_string *binary_findstring(const char *foo, INT32 l)
|
5267b7 | 1995-08-09 | Fredrik Hübinette (Hubbe) | | {
return internal_findstring(foo, l, StrHash(foo,l));
}
|
ca74dd | 1996-10-08 | Fredrik Hübinette (Hubbe) | | struct pike_string *findstring(const char *foo)
{
return binary_findstring(foo, strlen(foo));
}
|
5267b7 | 1995-08-09 | Fredrik Hübinette (Hubbe) | |
|
06983f | 1996-09-22 | Fredrik Hübinette (Hubbe) | | static struct pike_string *propagate_shared_string(const struct pike_string *s,int h)
|
5267b7 | 1995-08-09 | Fredrik Hübinette (Hubbe) | | {
|
06983f | 1996-09-22 | Fredrik Hübinette (Hubbe) | | struct pike_string *curr, **prev, **base;
|
5267b7 | 1995-08-09 | Fredrik Hübinette (Hubbe) | |
for(base = prev = base_table + h;( curr=*prev ); prev=&curr->next)
{
if (curr == s)
{
*prev=curr->next;
curr->next=*base;
*base=curr;
return curr;
}
#ifdef DEBUG
if(curr->refs<1)
fatal("String with no references.\n");
#endif
}
return 0;
}
#ifdef DEBUG
|
06983f | 1996-09-22 | Fredrik Hübinette (Hubbe) | | struct pike_string *debug_findstring(const struct pike_string *foo)
|
5267b7 | 1995-08-09 | Fredrik Hübinette (Hubbe) | | {
|
dd1981 | 1996-08-12 | Fredrik Hübinette (Hubbe) | | return propagate_shared_string(foo, foo->hval % HTABLE_SIZE);
|
5267b7 | 1995-08-09 | Fredrik Hübinette (Hubbe) | | }
#endif
|
06983f | 1996-09-22 | Fredrik Hübinette (Hubbe) | | struct pike_string *begin_shared_string(int len)
|
5267b7 | 1995-08-09 | Fredrik Hübinette (Hubbe) | | {
|
06983f | 1996-09-22 | Fredrik Hübinette (Hubbe) | | struct pike_string *t;
t=(struct pike_string *)xalloc(len + sizeof(struct pike_string));
|
ca74dd | 1996-10-08 | Fredrik Hübinette (Hubbe) | | t->str[len]=0;
|
5267b7 | 1995-08-09 | Fredrik Hübinette (Hubbe) | | t->len=len;
return t;
}
|
06983f | 1996-09-22 | Fredrik Hübinette (Hubbe) | | struct pike_string *end_shared_string(struct pike_string *s)
|
5267b7 | 1995-08-09 | Fredrik Hübinette (Hubbe) | | {
int len,h;
|
06983f | 1996-09-22 | Fredrik Hübinette (Hubbe) | | struct pike_string *s2;
|
5267b7 | 1995-08-09 | Fredrik Hübinette (Hubbe) | |
len=s->len;
h=StrHash(s->str,len);
s2=internal_findstring(s->str,len,h);
if(s2)
{
free((char *)s);
s=s2;
}else{
s->refs = 0;
s->next = base_table[h];
base_table[h] = s;
s->hval=full_hash_value;
}
s->refs++;
return s;
}
|
06983f | 1996-09-22 | Fredrik Hübinette (Hubbe) | | struct pike_string * make_shared_binary_string(const char *str,int len)
|
5267b7 | 1995-08-09 | Fredrik Hübinette (Hubbe) | | {
|
06983f | 1996-09-22 | Fredrik Hübinette (Hubbe) | | struct pike_string *s;
|
5267b7 | 1995-08-09 | Fredrik Hübinette (Hubbe) | | int h=StrHash(str,len);
s = internal_findstring(str,len,h);
if (!s)
{
s=begin_shared_string(len);
MEMCPY(s->str, str, len);
s->str[len] = 0;
s->refs = 0;
s->next = base_table[h];
base_table[h] = s;
s->hval=full_hash_value;
}
s->refs++;
return s;
}
|
06983f | 1996-09-22 | Fredrik Hübinette (Hubbe) | | struct pike_string *make_shared_string(const char *str)
|
5267b7 | 1995-08-09 | Fredrik Hübinette (Hubbe) | | {
return make_shared_binary_string(str, strlen(str));
}
int low_quick_binary_strcmp(char *a,INT32 alen,
char *b,INT32 blen)
{
int tmp;
if(alen > blen)
{
tmp=MEMCMP(a, b, blen);
if(tmp) return tmp;
return 1;
}else if(alen < blen){
tmp=MEMCMP(a, b, alen);
if(tmp) return tmp;
return -1;
}else{
return MEMCMP(a, b, alen);
}
}
#ifndef HAVE_STRCOLL
static int low_binary_strcmp(char *a,INT32 alen,
char *b,INT32 blen)
{
low_quick_binary_strcmp(a,alen,b,blen);
}
#else
static int low_binary_strcmp(char *a,INT32 alen,
char *b,INT32 blen)
{
INT32 tmp;
while(alen>0 && blen>0)
{
tmp=strcoll(a,b);
if(tmp) return (int)tmp;
tmp=strlen(a)+1;
a+=tmp;
b+=tmp;
alen-=tmp;
blen-=tmp;
}
if(alen==blen) return 0;
if(alen > blen) return 1;
return -1;
}
#endif
|
06983f | 1996-09-22 | Fredrik Hübinette (Hubbe) | | int my_quick_strcmp(struct pike_string *a,struct pike_string *b)
|
5267b7 | 1995-08-09 | Fredrik Hübinette (Hubbe) | | {
if(a==b) return 0;
return low_quick_binary_strcmp(a->str,a->len,b->str,b->len);
}
|
06983f | 1996-09-22 | Fredrik Hübinette (Hubbe) | | int my_strcmp(struct pike_string *a,struct pike_string *b)
|
5267b7 | 1995-08-09 | Fredrik Hübinette (Hubbe) | | {
if(a==b) return 0;
return low_binary_strcmp(a->str,a->len,b->str,b->len);
}
|
0a3d60 | 1996-10-09 | Fredrik Hübinette (Hubbe) | | void unlink_pike_string(struct pike_string *s)
|
5267b7 | 1995-08-09 | Fredrik Hübinette (Hubbe) | | {
int h;
h=StrHash(s->str,s->len);
propagate_shared_string(s,h);
base_table[h]=s->next;
|
0a3d60 | 1996-10-09 | Fredrik Hübinette (Hubbe) | | }
void really_free_string(struct pike_string *s)
{
unlink_pike_string(s);
|
5267b7 | 1995-08-09 | Fredrik Hübinette (Hubbe) | | free((char *)s);
}
|
06983f | 1996-09-22 | Fredrik Hübinette (Hubbe) | | struct pike_string *add_string_status(int verbose)
|
5267b7 | 1995-08-09 | Fredrik Hübinette (Hubbe) | | {
char b[200];
init_buf();
if (verbose)
{
int allocd_strings=0;
int allocd_bytes=0;
int num_distinct_strings=0;
int bytes_distinct_strings=0;
int overhead_bytes=0;
int e;
|
06983f | 1996-09-22 | Fredrik Hübinette (Hubbe) | | struct pike_string *p;
|
5267b7 | 1995-08-09 | Fredrik Hübinette (Hubbe) | | for(e=0;e<HTABLE_SIZE;e++)
{
for(p=base_table[e];p;p=p->next)
{
num_distinct_strings++;
|
f90e54 | 1995-08-17 | Fredrik Hübinette (Hubbe) | | bytes_distinct_strings+=MY_ALIGN(p->len);
|
5267b7 | 1995-08-09 | Fredrik Hübinette (Hubbe) | | allocd_strings+=p->refs;
|
f90e54 | 1995-08-17 | Fredrik Hübinette (Hubbe) | | allocd_bytes+=p->refs*MY_ALIGN(p->len+3);
|
5267b7 | 1995-08-09 | Fredrik Hübinette (Hubbe) | | }
}
|
06983f | 1996-09-22 | Fredrik Hübinette (Hubbe) | | overhead_bytes=(sizeof(struct pike_string)-1)*num_distinct_strings;
|
5267b7 | 1995-08-09 | Fredrik Hübinette (Hubbe) | | my_strcat("\nShared string hash table:\n");
my_strcat("-------------------------\t Strings Bytes\n");
sprintf(b,"Total asked for\t\t\t%8ld %8ld\n",
(long)allocd_strings, (long)allocd_bytes);
my_strcat(b);
sprintf(b,"Strings malloced\t\t%8ld %8ld + %ld overhead\n",
(long)num_distinct_strings,
(long)bytes_distinct_strings,
(long)overhead_bytes);
my_strcat(b);
sprintf(b,"Space actually required/total string bytes %d%%\n",
(bytes_distinct_strings + overhead_bytes)*100 / allocd_bytes);
my_strcat(b);
}
return free_buf();
}
void dump_stralloc_strings()
{
int e;
|
06983f | 1996-09-22 | Fredrik Hübinette (Hubbe) | | struct pike_string *p;
|
5267b7 | 1995-08-09 | Fredrik Hübinette (Hubbe) | | for(e=0;e<HTABLE_SIZE;e++)
for(p=base_table[e];p;p=p->next)
|
f90e54 | 1995-08-17 | Fredrik Hübinette (Hubbe) | | printf("%ld refs \"%s\"\n",(long)p->refs,p->str);
|
5267b7 | 1995-08-09 | Fredrik Hübinette (Hubbe) | | }
|
06983f | 1996-09-22 | Fredrik Hübinette (Hubbe) | | struct pike_string *add_shared_strings(struct pike_string *a,
struct pike_string *b)
|
5267b7 | 1995-08-09 | Fredrik Hübinette (Hubbe) | | {
INT32 size;
|
06983f | 1996-09-22 | Fredrik Hübinette (Hubbe) | | struct pike_string *ret;
|
5267b7 | 1995-08-09 | Fredrik Hübinette (Hubbe) | | char *buf;
size = a->len + b->len;
ret=begin_shared_string(size);
buf=ret->str;
MEMCPY(buf,a->str,a->len);
MEMCPY(buf+a->len,b->str,b->len);
ret=end_shared_string(ret);
return ret;
}
|
06983f | 1996-09-22 | Fredrik Hübinette (Hubbe) | | struct pike_string *string_replace(struct pike_string *str,
struct pike_string *del,
struct pike_string *to)
|
5267b7 | 1995-08-09 | Fredrik Hübinette (Hubbe) | | {
|
06983f | 1996-09-22 | Fredrik Hübinette (Hubbe) | | struct pike_string *ret;
|
5267b7 | 1995-08-09 | Fredrik Hübinette (Hubbe) | | INT32 delimeters;
char *s,*tmp,*r,*end;
|
310899 | 1996-06-21 | Fredrik Hübinette (Hubbe) | | struct mem_searcher searcher;
|
5267b7 | 1995-08-09 | Fredrik Hübinette (Hubbe) | |
s=str->str;
end=s+str->len;
delimeters=0;
|
310899 | 1996-06-21 | Fredrik Hübinette (Hubbe) | | init_memsearch(&searcher, del->str, del->len, str->len * 2);
while((s=memory_search(&searcher,s,end-s)))
|
5267b7 | 1995-08-09 | Fredrik Hübinette (Hubbe) | | {
delimeters++;
s+=del->len;
}
if(!delimeters)
{
str->refs++;
return str;
}
ret=begin_shared_string(str->len + (to->len-del->len)*delimeters);
s=str->str;
r=ret->str;
|
310899 | 1996-06-21 | Fredrik Hübinette (Hubbe) | | while((tmp=memory_search(&searcher,s,end-s)))
|
5267b7 | 1995-08-09 | Fredrik Hübinette (Hubbe) | | {
MEMCPY(r,s,tmp-s);
r+=tmp-s;
MEMCPY(r,to->str,to->len);
r+=to->len;
s=tmp+del->len;
}
MEMCPY(r,s,end-s);
return end_shared_string(ret);
}
void cleanup_shared_string_table()
{
int e;
|
06983f | 1996-09-22 | Fredrik Hübinette (Hubbe) | | struct pike_string *s,*next;
|
5267b7 | 1995-08-09 | Fredrik Hübinette (Hubbe) | | for(e=0;e<HTABLE_SIZE;e++)
{
for(s=base_table[e];s;s=next)
{
next=s->next;
#ifdef REALLY_FREE
free((char *)s);
#else
s->next=0;
#endif
}
base_table[e]=0;
}
}
|