83 }; |
83 }; |
84 |
84 |
85 #define PB_KEY_LIST_BUCKET_COUNT 0x7f // has to be (2^n - 1) |
85 #define PB_KEY_LIST_BUCKET_COUNT 0x7f // has to be (2^n - 1) |
86 |
86 |
87 struct pb_key_list_bucket { |
87 struct pb_key_list_bucket { |
88 pb_key *elements; |
88 pb_key **elements; |
89 unsigned size; |
89 unsigned size; |
90 }; |
90 }; |
91 |
91 |
92 struct pb_key_list { |
92 struct pb_key_list { |
93 struct pb_key_list_bucket buckets[PB_KEY_LIST_BUCKET_COUNT + 1]; |
93 struct pb_key_list_bucket buckets[PB_KEY_LIST_BUCKET_COUNT + 1]; |
94 }; |
94 }; |
95 |
95 |
96 static const pb_key *_pb_key_list_insert(struct pb_key_list *hashList, unsigned int hashval, pb_key* element) { |
96 static void _pb_key_list_insert(struct pb_key_list *hashList, unsigned int hashval, pb_key* element) { |
97 struct pb_key_list_bucket *bucket = &hashList->buckets[hashval & PB_KEY_LIST_BUCKET_COUNT]; |
97 struct pb_key_list_bucket *bucket = &hashList->buckets[hashval & PB_KEY_LIST_BUCKET_COUNT]; |
98 size_t idx = bucket->size; |
98 size_t idx = bucket->size; |
99 bucket->size++; |
99 bucket->size++; |
100 bucket->elements = realloc(bucket->elements, sizeof(pb_key) * bucket->size); |
100 bucket->elements = realloc(bucket->elements, sizeof(pb_key*) * bucket->size); |
101 if (bucket->elements == NULL) abort(); |
101 if (bucket->elements == NULL) abort(); |
102 bucket->elements[idx] = *element; |
102 bucket->elements[idx] = element; |
103 return &bucket->elements[idx]; |
|
104 } |
103 } |
105 |
104 |
106 static struct pb_key_list _pbKeys; |
105 static struct pb_key_list _pbKeys; |
107 |
106 |
108 static const pb_key *_create_key(const char *name) |
107 static const pb_key *_create_key(const char *name) |
109 { |
108 { |
110 /* Create a the new pb_key */ |
109 /* Create a new pb_key */ |
111 pb_key key; |
110 pb_key *key = malloc(sizeof(pb_key)); |
112 key.name = STRDUP(name); |
111 if (key == NULL) abort(); |
113 key.namelen = strlen(name); |
112 key->name = STRDUP(name); |
114 key.hashval = PListHash(name); |
113 key->namelen = strlen(name); |
115 key.sizendx = 0; |
114 key->hashval = PListHash(name); |
116 key.hashndx = key.hashval % PLSIZENDX(0); |
115 key->sizendx = 0; |
|
116 key->hashndx = key->hashval % PLSIZENDX(0); |
117 |
117 |
118 /* Group pb_keys by hashval for later retrieval */ |
118 /* Group pb_keys by hashval for later retrieval */ |
119 return _pb_key_list_insert(&_pbKeys, key.hashval, &key); |
119 _pb_key_list_insert(&_pbKeys, key->hashval, key); |
|
120 |
|
121 return key; |
120 } |
122 } |
121 |
123 |
122 const pb_key *pb_key_accept; |
124 const pb_key *pb_key_accept; |
123 const pb_key *pb_key_accept_charset; |
125 const pb_key *pb_key_accept_charset; |
124 const pb_key *pb_key_accept_encoding; |
126 const pb_key *pb_key_accept_encoding; |
507 pb_key_warning = _create_key("warning"); |
509 pb_key_warning = _create_key("warning"); |
508 } |
510 } |
509 |
511 |
510 NSAPI_PUBLIC void pblock_free_default_keys(void) { |
512 NSAPI_PUBLIC void pblock_free_default_keys(void) { |
511 for (unsigned i = 0 ; i < PB_KEY_LIST_BUCKET_COUNT ; i++) { |
513 for (unsigned i = 0 ; i < PB_KEY_LIST_BUCKET_COUNT ; i++) { |
512 // free(NULL) is defined, so don't worry here |
514 unsigned count = _pbKeys.buckets[i].size; |
513 free(_pbKeys.buckets[i].elements); |
515 if (count > 0) { |
|
516 pb_key **keys = _pbKeys.buckets[i].elements; |
|
517 for (unsigned j = 0 ; j < count ; j++) { |
|
518 free(keys[j]); |
|
519 } |
|
520 free(keys); |
|
521 } |
514 } |
522 } |
515 } |
523 } |
516 |
524 |
517 /* ------------------------------ _find_key ------------------------------- */ |
525 /* ------------------------------ _find_key ------------------------------- */ |
518 |
526 |
519 static inline const pb_key *_find_key(const char *name, unsigned int hashval) |
527 static inline const pb_key *_find_key(const char *name, unsigned int hashval) |
520 { |
528 { |
521 /* Check to see if name corresponds to a pb_key */ |
529 /* Check to see if name corresponds to a pb_key */ |
522 struct pb_key_list_bucket *bucket = &_pbKeys.buckets[hashval & PB_KEY_LIST_BUCKET_COUNT]; |
530 struct pb_key_list_bucket *bucket = &_pbKeys.buckets[hashval & PB_KEY_LIST_BUCKET_COUNT]; |
523 for (unsigned i = 0 ; i < bucket->size ; i++) { |
531 for (unsigned i = 0 ; i < bucket->size ; i++) { |
524 pb_key *key = &bucket->elements[i]; |
532 pb_key *key = bucket->elements[i]; |
525 if (key->hashval == hashval && !strcmp(key->name, name)) { |
533 if (key->hashval == hashval && !strcmp(key->name, name)) { |
526 return key; |
534 return key; |
527 } |
535 } |
528 } |
536 } |
529 return NULL; |
537 return NULL; |