numhash.c
上传用户:gzpyjq
上传日期:2013-01-31
资源大小:1852k
文件大小:7k
源码类别:

手机WAP编程

开发平台:

WINDOWS

  1. /*
  2.  * numhash.c
  3.  *
  4.  * NUMBER HASH functions
  5.  *
  6.  * functions to add a number to database/hash
  7.  * and functions to retrieve them
  8.  *
  9.  * notes: read header file
  10.  *
  11.  * Kalle Marjola for project Kannel 1999-2000
  12.  */
  13. #include <stdlib.h>
  14. #include <string.h>
  15. #include <ctype.h>
  16. #include <errno.h>
  17. #include "gwlib/gwlib.h"
  18. #include "numhash.h"
  19. #define NUMHASH_AUTO_HASH -1
  20. /* set of pre-calculated prime numbers for hash generation... */
  21. static int primes[] = {
  22.   101, 503, 1009, 2003, 3001, 5003, 7001,
  23.   10007, 20011, 30011, 40009, 50021, 60013, 70001, 80021, 90001,
  24.   100003, 150001, 200003, 300007, 400009, 500009, 600011, 700001,
  25.   800011, 900001, 1000003, 1100009, 1200007, 1300021, 1400017, 1500007,
  26.   1600033, 1700021, 1800017, 1900009, 2000003, 3000017, 4000037, 5000111,
  27.   6000101, 7000127, 8000051, -1
  28. };
  29. struct numhash_table {
  30.   struct numhash_number *numbers;
  31.   long number_total;
  32.   long table_size;
  33.   struct numhash_number **hash;
  34.   long hash_size;
  35. }; /* Numhash */
  36. struct numhash_number {
  37.   long key; /* (hopefully) unique key */
  38.   struct numhash_number *next; /* next in hash table, if any */
  39. };
  40. struct nh_entry {
  41.     Numhash *hash;
  42.     struct nh_entry *next;
  43. };
  44.     
  45. struct numhashes {
  46.     struct nh_entry *first;
  47.     struct nh_entry  *last;
  48. }; /* Multitable */
  49. static int precision = 9; /* the precision (last numbers) used */
  50. /*
  51.  * add new item (number) to hash table
  52.  */
  53. static int add_item(Numhash *table, struct numhash_number *nro)
  54. {
  55.     if (table->hash[nro->key % table->hash_size]) {    /* conflict */
  56. struct numhash_number *ptr = table->hash[nro->key % table->hash_size];
  57. if (ptr->key == nro->key)
  58.     goto duplicate;
  59. while(ptr->next) {
  60.     ptr = ptr->next;
  61.     if (ptr->key == nro->key)
  62. goto duplicate;
  63. }
  64. ptr->next = nro; /* put as last of the linkage */
  65.     } else
  66. table->hash[nro->key % table->hash_size] = nro;
  67.     return 0;
  68. duplicate:
  69.     warning(0, "Duplicate number %ld!", nro->key); 
  70.     return -1;
  71. }
  72. /* Add a new number to number list and hash
  73.  * Return 0 if all went ok, -1 if out of room
  74.  */
  75. static int numhash_add_number(Numhash *table, char *nro)
  76. {
  77.     struct numhash_number *newnro;
  78.     if (table->number_total == table->table_size) {
  79. error(0, "Table limit %ld reached, cannot add %s!",
  80.       table->table_size, nro);
  81. return -1;
  82.     }
  83.     newnro =  &table->numbers[table->number_total++]; /* take the next free */
  84.   
  85.     newnro->key = numhash_get_char_key(nro);
  86.     newnro->next = NULL;
  87.   
  88.     add_item(table, newnro);
  89.   
  90.     return 0;
  91. }
  92. /* Init the number table and hash table with given sizes
  93.  */
  94. static Numhash *numhash_init(int max_numbers, int hash_size)
  95. {
  96.     Numhash *ntable = NULL;
  97.     ntable = gw_malloc(sizeof(Numhash));
  98.     
  99.     if (hash_size > 0)
  100. ntable->hash_size = hash_size;
  101.     else if (hash_size == NUMHASH_AUTO_HASH) {
  102. int i;
  103. for(i=0 ; primes[i] > 0; i++) {
  104.     ntable->hash_size = primes[i];
  105.     if (ntable->hash_size > max_numbers)
  106. break;
  107. }
  108.     } else {
  109. gw_free(ntable);
  110. return NULL;
  111.     }
  112.     ntable->hash = gw_malloc(ntable->hash_size * sizeof(struct numhash_number *));
  113.     memset(ntable->hash, 0, sizeof(struct numhash_number *) * ntable->hash_size);
  114.     ntable->table_size = max_numbers;
  115.     ntable->numbers = gw_malloc(ntable->table_size * sizeof(struct numhash_number));
  116.     ntable->number_total = 0;
  117.   
  118.     /* set our accuracy according to the size of long int
  119.      * Ok, we call this many times if we use multiple tables, but
  120.      * that is not a problem...
  121.      */
  122.     if (sizeof(long)>=8) precision = 18;
  123.     else if (sizeof(long)>=4) precision = 9;
  124.     return ntable;
  125. }
  126. /*------------------------------------------------------
  127.  * PUBLIC FUNCTIONS
  128.  */
  129. int numhash_find_number(Numhash *table, Octstr *nro)
  130. {
  131.     long key = numhash_get_key(nro);
  132.     if (key<0) return key;
  133.     return numhash_find_key(table, key);
  134. }
  135. int numhash_find_key(Numhash *table, long key)
  136. {
  137.     struct numhash_number *ptr;
  138.     ptr = table->hash[key % table->hash_size];
  139.     while (ptr) {
  140. if (ptr->key == key) return 1;
  141. ptr = ptr->next;
  142.     }
  143.     return 0; /* not found */
  144. }
  145. long numhash_get_key(Octstr *nro)
  146. {
  147.     long key;
  148.     if (!nro) return -1;
  149.   
  150.     if (octstr_len(nro) > precision)
  151. key = atoi(octstr_get_cstr(nro) + octstr_len(nro) -precision);
  152.     else
  153. key = atoi(octstr_get_cstr(nro));
  154.     return key;
  155. }
  156. long numhash_get_char_key(char *nro)
  157. {
  158.     int len;
  159.     long key;
  160.     if (!nro) return -1;
  161.     len = strlen(nro);
  162.     
  163.     if (len > precision)
  164. key = atoi(nro + len -precision);
  165.     else
  166. key = atoi(nro);
  167.     return key;
  168. }
  169. void numhash_destroy(Numhash *table)
  170. {
  171.     if (table == NULL)
  172. return;
  173.     gw_free(table->numbers);
  174.     gw_free(table->hash);
  175.     gw_free(table);
  176. }
  177. double numhash_hash_fill(Numhash *table, int *longest)
  178. {
  179.     int i, l, max = 0, tot = 0;
  180.     struct numhash_number *ptr;
  181.     for (i=0; i < table->hash_size; i++)
  182. if (table->hash[i]) {
  183.     tot++;
  184.     ptr = table->hash[i]; 
  185.     for (l=0; ptr->next; ptr = ptr->next)
  186. l++;
  187.     if (l > max)
  188. max = l;
  189. }
  190.     if (longest != NULL)
  191. *longest = max;
  192.     return (double)(tot*100.0/(table->hash_size));
  193. }
  194. int numhash_size(Numhash *table)
  195. {
  196.     return table->number_total;
  197. }
  198. Numhash *numhash_create(char *seek_url)
  199. {
  200.     int loc, lines = 0;
  201.     List *request_headers, *reply_headers;
  202.     Octstr *url, *final_url, *reply_body;
  203.     Octstr *type, *charset;
  204.     
  205.     unsigned char        *data, *ptr, numbuf[100];
  206.     int status;
  207.     Numhash *table;
  208.     url = octstr_create(seek_url);
  209.     request_headers = list_create();
  210.     status = http_get_real(HTTP_METHOD_GET, url, request_headers, &final_url,
  211.     &reply_headers, &reply_body);
  212.     octstr_destroy(url);
  213.     octstr_destroy(final_url);
  214.     list_destroy(request_headers, NULL);
  215.     if (status != HTTP_OK) {
  216. http_destroy_headers(reply_headers);
  217. octstr_destroy(reply_body);
  218. error(0, "Cannot load numhash!");
  219. return NULL;
  220.     }
  221.     http_header_get_content_type(reply_headers, &type, &charset);
  222.     octstr_destroy(charset);
  223.     http_destroy_headers(reply_headers);
  224.     
  225.     if (octstr_str_compare(type, "text/plain") != 0) {
  226.         octstr_destroy(reply_body);
  227.         error(0, "Strange content type <%s> for numhash - expecting 'text/plain'"
  228.                  ", operatiom fails", octstr_get_cstr(type));
  229.         octstr_destroy(type);
  230.         return NULL;
  231.     }
  232.     octstr_destroy(type);
  233.     
  234.     ptr = data = octstr_get_cstr(reply_body);
  235.     while(*ptr) {
  236. if (*ptr == 'n') lines++;
  237. ptr++;
  238.     }
  239.     debug("numhash", 0, "Total %d lines in %s", lines, seek_url);
  240.     table = numhash_init(lines+10, NUMHASH_AUTO_HASH);   /* automatic hash */
  241.     /* now, parse the number information */
  242.     lines = 0;
  243.   
  244.     while((ptr = strchr(data, 'n'))) { /* each line is ended with linefeed */
  245. *ptr = '';
  246. while(*data != '' && isspace(*data))
  247.     data++;
  248. if (*data != '#') {
  249.     loc = 0;
  250.     while (*data != '') {
  251. if (isdigit(*data))
  252.     numbuf[loc++] = *data;
  253. else if (*data == ' ' || *data == '+' || *data == '-')
  254. ;
  255. else break;
  256. data++;
  257.     }
  258.     if (loc) {
  259. numbuf[loc] = '';
  260. numhash_add_number(table, numbuf);
  261. lines++;
  262.     }
  263.     else
  264. warning(0, "Corrupted line '%s'", data);
  265. }
  266. data = ptr+1; /* next row... */
  267.     }
  268.     octstr_destroy(reply_body); 
  269.     info(0, "Read from <%s> total of %ld numbers", seek_url, table->number_total);
  270.     return table;
  271. }