00001
00002 #include <stdio.h>
00003 #include <stdlib.h>
00004 #include <string.h>
00005 #include <unistd.h>
00006
00007 #include "string_cache.h"
00008
00009 unsigned long
00010 string_hash(STRING_CACHE * sc,
00011 char *string)
00012 {
00013 long a, i, mod, mul;
00014
00015 a = 0;
00016 mod = sc->mod;
00017 mul = sc->mul;
00018 for(i = 0; string[i]; i++)
00019 a = (a * mul + (unsigned char)string[i]) % mod;
00020 return a;
00021 }
00022
00023 void
00024 generate_sc_hash(STRING_CACHE * sc)
00025 {
00026 long i;
00027 long hash;
00028
00029 if(sc->string_hash != NULL)
00030 free(sc->string_hash);
00031 if(sc->next_string != NULL)
00032 free(sc->next_string);
00033 sc->string_hash_size = sc->size * 2 + 11;
00034 sc->string_hash = (long *)sc_do_alloc(sc->string_hash_size, sizeof(long));
00035 sc->next_string = (long *)sc_do_alloc(sc->size, sizeof(long));
00036 memset(sc->string_hash, 0xff, sc->string_hash_size * sizeof(long));
00037 memset(sc->next_string, 0xff, sc->size * sizeof(long));
00038 for(i = 0; i < sc->free; i++)
00039 {
00040 hash = string_hash(sc, sc->string[i]) % sc->string_hash_size;
00041 sc->next_string[i] = sc->string_hash[hash];
00042 sc->string_hash[hash] = i;
00043 }
00044 }
00045
00046
00047 STRING_CACHE *
00048 sc_new_string_cache(void)
00049 {
00050 STRING_CACHE *sc;
00051
00052 sc = (STRING_CACHE *)sc_do_alloc(1, sizeof(STRING_CACHE));
00053 sc->size = 100;
00054 sc->string_hash_size = 0;
00055 sc->string_hash = NULL;
00056 sc->next_string = NULL;
00057 sc->free = 0;
00058 sc->string = (char **)sc_do_alloc(sc->size, sizeof(char *));
00059 sc->data = (void **)sc_do_alloc(sc->size, sizeof(void *));
00060 sc->mod = 834535547;
00061 sc->mul = 247999;
00062 generate_sc_hash(sc);
00063 return sc;
00064 }
00065
00066 long
00067 sc_lookup_string(STRING_CACHE * sc,
00068 char *string)
00069 {
00070 long i, hash;
00071
00072 hash = string_hash(sc, string) % sc->string_hash_size;
00073 i = sc->string_hash[hash];
00074 while(i >= 0)
00075 {
00076 if(!strcmp(sc->string[i], string))
00077 return i;
00078 i = sc->next_string[i];
00079 }
00080 return -1;
00081 }
00082
00083 long
00084 sc_add_string(STRING_CACHE * sc,
00085 char *string)
00086 {
00087 long i;
00088 long hash;
00089 void *a;
00090
00091 i = sc_lookup_string(sc, string);
00092 if(i >= 0)
00093 return i;
00094 if(sc->free >= sc->size)
00095 {
00096 sc->size = sc->size * 2 + 10;
00097
00098 a = sc_do_alloc(sc->size, sizeof(char *));
00099 if(sc->free > 0)
00100 memcpy(a, sc->string, sc->free * sizeof(char *));
00101 free(sc->string);
00102 sc->string = (char **)a;
00103
00104 a = sc_do_alloc(sc->size, sizeof(void *));
00105 if(sc->free > 0)
00106 memcpy(a, sc->data, sc->free * sizeof(void *));
00107 free(sc->data);
00108 sc->data = (void **)a;
00109
00110 generate_sc_hash(sc);
00111 }
00112 i = sc->free;
00113 sc->free++;
00114 sc->string[i] = strdup(string);
00115 sc->data[i] = NULL;
00116 hash = string_hash(sc, string) % sc->string_hash_size;
00117 sc->next_string[i] = sc->string_hash[hash];
00118 sc->string_hash[hash] = i;
00119 return i;
00120 }
00121
00122 int
00123 sc_valid_id(STRING_CACHE * sc,
00124 long string_id)
00125 {
00126 if(string_id < 0)
00127 return 0;
00128 if(string_id >= sc->free)
00129 return 0;
00130 return 1;
00131 }
00132
00133 void *
00134 sc_do_alloc(long a,
00135 long b)
00136 {
00137 void *r;
00138
00139 if(a < 1)
00140 a = 1;
00141 if(b < 1)
00142 b = 1;
00143 r = calloc(a, b);
00144 while(r == NULL)
00145 {
00146 fprintf(stderr,
00147 "Failed to allocated %ld chunks of %ld bytes (%ld bytes total)\n",
00148 a, b, a * b);
00149 sleep(1);
00150 r = calloc(a, b);
00151 }
00152 return r;
00153 }
00154
00155 void
00156 sc_free_string_cache(STRING_CACHE * sc)
00157 {
00158 long i;
00159
00160 if(sc == NULL)
00161 return;
00162 for(i = 0; i < sc->free; i++)
00163 if (sc->string != NULL)
00164 free(sc->string[i]);
00165 free(sc->string);
00166 sc->string = NULL;
00167 if(sc->data != NULL)
00168 {
00169
00170 sc->data = NULL;
00171 }
00172 if(sc->string_hash != NULL)
00173 {
00174 free(sc->string_hash);
00175 sc->string_hash = NULL;
00176 }
00177 if(sc->next_string != NULL)
00178 {
00179 free(sc->next_string);
00180 sc->next_string = NULL;
00181 }
00182 free(sc);
00183 }