numhash.c
资源名称:gateway-1.2.1 [点击查看]
上传用户:gzpyjq
上传日期:2013-01-31
资源大小:1852k
文件大小:7k
源码类别:
手机WAP编程
开发平台:
WINDOWS
- /*
- * numhash.c
- *
- * NUMBER HASH functions
- *
- * functions to add a number to database/hash
- * and functions to retrieve them
- *
- * notes: read header file
- *
- * Kalle Marjola for project Kannel 1999-2000
- */
- #include <stdlib.h>
- #include <string.h>
- #include <ctype.h>
- #include <errno.h>
- #include "gwlib/gwlib.h"
- #include "numhash.h"
- #define NUMHASH_AUTO_HASH -1
- /* set of pre-calculated prime numbers for hash generation... */
- static int primes[] = {
- 101, 503, 1009, 2003, 3001, 5003, 7001,
- 10007, 20011, 30011, 40009, 50021, 60013, 70001, 80021, 90001,
- 100003, 150001, 200003, 300007, 400009, 500009, 600011, 700001,
- 800011, 900001, 1000003, 1100009, 1200007, 1300021, 1400017, 1500007,
- 1600033, 1700021, 1800017, 1900009, 2000003, 3000017, 4000037, 5000111,
- 6000101, 7000127, 8000051, -1
- };
- struct numhash_table {
- struct numhash_number *numbers;
- long number_total;
- long table_size;
- struct numhash_number **hash;
- long hash_size;
- }; /* Numhash */
- struct numhash_number {
- long key; /* (hopefully) unique key */
- struct numhash_number *next; /* next in hash table, if any */
- };
- struct nh_entry {
- Numhash *hash;
- struct nh_entry *next;
- };
- struct numhashes {
- struct nh_entry *first;
- struct nh_entry *last;
- }; /* Multitable */
- static int precision = 9; /* the precision (last numbers) used */
- /*
- * add new item (number) to hash table
- */
- static int add_item(Numhash *table, struct numhash_number *nro)
- {
- if (table->hash[nro->key % table->hash_size]) { /* conflict */
- struct numhash_number *ptr = table->hash[nro->key % table->hash_size];
- if (ptr->key == nro->key)
- goto duplicate;
- while(ptr->next) {
- ptr = ptr->next;
- if (ptr->key == nro->key)
- goto duplicate;
- }
- ptr->next = nro; /* put as last of the linkage */
- } else
- table->hash[nro->key % table->hash_size] = nro;
- return 0;
- duplicate:
- warning(0, "Duplicate number %ld!", nro->key);
- return -1;
- }
- /* Add a new number to number list and hash
- * Return 0 if all went ok, -1 if out of room
- */
- static int numhash_add_number(Numhash *table, char *nro)
- {
- struct numhash_number *newnro;
- if (table->number_total == table->table_size) {
- error(0, "Table limit %ld reached, cannot add %s!",
- table->table_size, nro);
- return -1;
- }
- newnro = &table->numbers[table->number_total++]; /* take the next free */
- newnro->key = numhash_get_char_key(nro);
- newnro->next = NULL;
- add_item(table, newnro);
- return 0;
- }
- /* Init the number table and hash table with given sizes
- */
- static Numhash *numhash_init(int max_numbers, int hash_size)
- {
- Numhash *ntable = NULL;
- ntable = gw_malloc(sizeof(Numhash));
- if (hash_size > 0)
- ntable->hash_size = hash_size;
- else if (hash_size == NUMHASH_AUTO_HASH) {
- int i;
- for(i=0 ; primes[i] > 0; i++) {
- ntable->hash_size = primes[i];
- if (ntable->hash_size > max_numbers)
- break;
- }
- } else {
- gw_free(ntable);
- return NULL;
- }
- ntable->hash = gw_malloc(ntable->hash_size * sizeof(struct numhash_number *));
- memset(ntable->hash, 0, sizeof(struct numhash_number *) * ntable->hash_size);
- ntable->table_size = max_numbers;
- ntable->numbers = gw_malloc(ntable->table_size * sizeof(struct numhash_number));
- ntable->number_total = 0;
- /* set our accuracy according to the size of long int
- * Ok, we call this many times if we use multiple tables, but
- * that is not a problem...
- */
- if (sizeof(long)>=8) precision = 18;
- else if (sizeof(long)>=4) precision = 9;
- return ntable;
- }
- /*------------------------------------------------------
- * PUBLIC FUNCTIONS
- */
- int numhash_find_number(Numhash *table, Octstr *nro)
- {
- long key = numhash_get_key(nro);
- if (key<0) return key;
- return numhash_find_key(table, key);
- }
- int numhash_find_key(Numhash *table, long key)
- {
- struct numhash_number *ptr;
- ptr = table->hash[key % table->hash_size];
- while (ptr) {
- if (ptr->key == key) return 1;
- ptr = ptr->next;
- }
- return 0; /* not found */
- }
- long numhash_get_key(Octstr *nro)
- {
- long key;
- if (!nro) return -1;
- if (octstr_len(nro) > precision)
- key = atoi(octstr_get_cstr(nro) + octstr_len(nro) -precision);
- else
- key = atoi(octstr_get_cstr(nro));
- return key;
- }
- long numhash_get_char_key(char *nro)
- {
- int len;
- long key;
- if (!nro) return -1;
- len = strlen(nro);
- if (len > precision)
- key = atoi(nro + len -precision);
- else
- key = atoi(nro);
- return key;
- }
- void numhash_destroy(Numhash *table)
- {
- if (table == NULL)
- return;
- gw_free(table->numbers);
- gw_free(table->hash);
- gw_free(table);
- }
- double numhash_hash_fill(Numhash *table, int *longest)
- {
- int i, l, max = 0, tot = 0;
- struct numhash_number *ptr;
- for (i=0; i < table->hash_size; i++)
- if (table->hash[i]) {
- tot++;
- ptr = table->hash[i];
- for (l=0; ptr->next; ptr = ptr->next)
- l++;
- if (l > max)
- max = l;
- }
- if (longest != NULL)
- *longest = max;
- return (double)(tot*100.0/(table->hash_size));
- }
- int numhash_size(Numhash *table)
- {
- return table->number_total;
- }
- Numhash *numhash_create(char *seek_url)
- {
- int loc, lines = 0;
- List *request_headers, *reply_headers;
- Octstr *url, *final_url, *reply_body;
- Octstr *type, *charset;
- unsigned char *data, *ptr, numbuf[100];
- int status;
- Numhash *table;
- url = octstr_create(seek_url);
- request_headers = list_create();
- status = http_get_real(HTTP_METHOD_GET, url, request_headers, &final_url,
- &reply_headers, &reply_body);
- octstr_destroy(url);
- octstr_destroy(final_url);
- list_destroy(request_headers, NULL);
- if (status != HTTP_OK) {
- http_destroy_headers(reply_headers);
- octstr_destroy(reply_body);
- error(0, "Cannot load numhash!");
- return NULL;
- }
- http_header_get_content_type(reply_headers, &type, &charset);
- octstr_destroy(charset);
- http_destroy_headers(reply_headers);
- if (octstr_str_compare(type, "text/plain") != 0) {
- octstr_destroy(reply_body);
- error(0, "Strange content type <%s> for numhash - expecting 'text/plain'"
- ", operatiom fails", octstr_get_cstr(type));
- octstr_destroy(type);
- return NULL;
- }
- octstr_destroy(type);
- ptr = data = octstr_get_cstr(reply_body);
- while(*ptr) {
- if (*ptr == 'n') lines++;
- ptr++;
- }
- debug("numhash", 0, "Total %d lines in %s", lines, seek_url);
- table = numhash_init(lines+10, NUMHASH_AUTO_HASH); /* automatic hash */
- /* now, parse the number information */
- lines = 0;
- while((ptr = strchr(data, 'n'))) { /* each line is ended with linefeed */
- *ptr = ' ';
- while(*data != ' ' && isspace(*data))
- data++;
- if (*data != '#') {
- loc = 0;
- while (*data != ' ') {
- if (isdigit(*data))
- numbuf[loc++] = *data;
- else if (*data == ' ' || *data == '+' || *data == '-')
- ;
- else break;
- data++;
- }
- if (loc) {
- numbuf[loc] = ' ';
- numhash_add_number(table, numbuf);
- lines++;
- }
- else
- warning(0, "Corrupted line '%s'", data);
- }
- data = ptr+1; /* next row... */
- }
- octstr_destroy(reply_body);
- info(0, "Read from <%s> total of %ld numbers", seek_url, table->number_total);
- return table;
- }