OB.DAAC Logo
NASA Logo
Ocean Color Science Software

ocssw V2022
phash.c
Go to the documentation of this file.
1 // implemented version numbers
2 #define PHASH_IMPLEMENTATION 1002001
3 #define PHASH_IMPLEMENTATION_STR "1.2.0"
4 #define PHASH_API_VERSION 1002000
5 #define PHASH_API_VERSION_STR "1.2.0"
6 #include "phash.h"
7 
8 #include <limits.h>
9 #include <stdint.h>
10 #include <stdlib.h>
11 #include <string.h>
12 
18 #ifndef PHASH_INITIAL_SIZE
19 #define PHASH_INITIAL_SIZE 64
20 #endif
21 
26 #ifndef PHASH_FILLPCT
27 #define PHASH_FILLPCT 66
28 #endif
29 
30 typedef struct phash_bucket phash_bucket;
31 
32 struct phash_bucket {
35  const char *key;
36  void *value;
37  uint32_t hash;
38 };
39 
40 struct phash {
43  int filled;
44  int iter_i;
45  unsigned options;
47 };
48 
49 // Murmur3 32-bit hash stolen from qlibc
50 // https://github.com/wolkykim/qlibc/blob/master/src/utilities/qhash.c
51 static uint32_t compute_hash(const char *key) {
52  if (key == NULL){
53  return 0;
54  }
55  size_t key_length = strlen(key);
56  if (key_length == 0) {
57  return 0;
58  }
59  const uint32_t c1 = 0xcc9e2d51;
60  const uint32_t c2 = 0x1b873593;
61  const unsigned nblocks = (unsigned) (key_length / 4);
62  const uint32_t *blocks = (const uint32_t *) (key);
63  const uint8_t *tail = (const uint8_t *) (key + (nblocks * 4));
64  uint32_t h = 0;
65  unsigned i;
66  uint32_t k;
67  for (i = 0; i < nblocks; i++) {
68  k = blocks[i];
69  k *= c1;
70  k = (k << 15) | (k >> (32 - 15));
71  k *= c2;
72  h ^= k;
73  h = (h << 13) | (h >> (32 - 13));
74  h = (h * 5) + 0xe6546b64;
75  }
76  k = 0;
77  switch (key_length & 3) {
78  case 3:
79  k ^= tail[2] << 16;
80  /* no break */
81  case 2:
82  k ^= tail[1] << 8;
83  /* no break */
84  case 1:
85  k ^= tail[0];
86  k *= c1;
87  k = (k << 15) | (k >> (32 - 15));
88  k *= c2;
89  h ^= k;
90  };
91  h ^= (uint32_t) key_length;
92  h ^= h >> 16;
93  h *= 0x85ebca6b;
94  h ^= h >> 13;
95  h *= 0xc2b2ae35;
96  h ^= h >> 16;
97  return h;
98 }
99 
100 static void phash_zero_out(phash_bucket **buckets, int start, int end) {
101  int i;
102  for (i = start; i <= end; i++) {
103  buckets[i] = NULL;
104  }
105 }
106 
108  phash *h = malloc(sizeof(phash));
109  if (h == NULL) {
110  return NULL;
111  }
112  h->options = options;
113  h->buckets = (phash_bucket**) malloc(PHASH_INITIAL_SIZE * sizeof(phash_bucket*));
114  if (h->buckets == NULL) {
115  free(h);
116  return NULL;
117  }
118  h->filled = 0;
119  h->max_bucket = PHASH_INITIAL_SIZE - 1;
120  phash_rewind(h);
121  phash_zero_out(h->buckets, 0, h->max_bucket);
122  return h;
123 }
124 
125 static int phash_destroy_bucket(phash_bucket *bucket) {
126  if (bucket != NULL) {
127  int ret = phash_destroy_bucket(bucket->next);
128  if (!(bucket->owner->options & PHASH_NO_COPY_KEYS)) {
129  free((char*) bucket->key);
130  }
131  free(bucket);
132  return ret + 1;
133  }
134  return 0;
135 }
137  int i, total_freed = 0;
138  for (i = 0; i <= h->max_bucket; i++) {
139  total_freed += phash_destroy_bucket(h->buckets[i]);
140  }
141  free(h->buckets);
142  free(h);
143  return 0;
144 }
145 
146 int phash_remove(phash *h, const char *key) {
147  if (h == NULL) {
148  return -1;
149  }
150  uint32_t hash = compute_hash(key);
151  phash_bucket **bucket_ptr = &(h->buckets[hash & h->max_bucket]);
152  phash_bucket *cur_bucket = *bucket_ptr;
153 
154  int is_first;
155  for (is_first = 1; cur_bucket != NULL; is_first = 0, bucket_ptr = &cur_bucket->next, cur_bucket = *bucket_ptr) {
156  if (cur_bucket->hash == hash && strcmp(cur_bucket->key, key) == 0) {
157  *bucket_ptr = cur_bucket->next;
158  free(cur_bucket);
159  if (is_first) {
160  h->filled--;
161  }
162  return 0;
163  }
164  }
165  return 1;
166 }
167 
168 static int phash_split(phash *h) {
169  int oldsize = h->max_bucket + 1;
170  int newsize = oldsize << 1;
171  phash_bucket **a = (phash_bucket**) realloc((phash_bucket*) h->buckets, newsize * sizeof(phash_bucket*));
172  if (a == NULL) {
173  return -1;
174  }
175  phash_zero_out(a, oldsize, --newsize);
176 
177  h->max_bucket = newsize;
178  h->buckets = a;
179 
180  phash_bucket **b, **oentry, *entry;
181 
182  int i;
183  for (i = 0; i < oldsize; i++, a++) {
184  if (*a == NULL){
185  continue;
186  }
187  b = a + oldsize;
188  for (oentry = a, entry = *a; entry != NULL; entry = *oentry) {
189  if ((entry->hash & newsize) != (unsigned) i) {
190  *oentry = entry->next;
191  entry->next = *b;
192 // if (*b == NULL)
193 // h->filled++;
194  *b = entry;
195  } else {
196  oentry = &entry->next;
197  }
198  }
199 // if (*a == NULL)
200 // h->filled--;
201  }
202  return 0;
203 }
204 
205 void *phash_get(phash *h, const char *key) {
206  phash_bucket *entry;
207  phash_bucket **oentry;
208 
209  if (h == NULL) {
210  return NULL;
211  }
212 
213  uint32_t hash = compute_hash(key);
214  oentry = &(h->buckets[hash & h->max_bucket]);
215 
216  for (entry = *oentry; entry != NULL; entry = entry->next) {
217  if (entry->hash == hash && strcmp(entry->key, key) == 0) {
218  return entry->value;
219  }
220  }
221  return NULL;
222 }
223 
224 int phash_set(phash *h, const char *key, void *value) {
225  register phash_bucket *entry;
226  register phash_bucket **oentry;
227 
228  if (h == NULL) {
229  return -1;
230  }
231 
232  uint32_t hash = compute_hash(key);
233  oentry = &(h->buckets[hash & h->max_bucket]);
234 
235  for (entry = *oentry; entry != NULL; entry = entry->next) {
236  if (entry->hash == hash && strcmp(entry->key, key) == 0) {
237  entry->value = value;
238  return 1;
239  }
240  }
241  entry = (phash_bucket*) malloc(sizeof(phash_bucket));
242  if (entry == NULL) {
243  return 1;
244  }
245 
246  entry->owner = h;
247  if (!(h->options & PHASH_NO_COPY_KEYS)) {
248  size_t key_size = strlen(key) + 1;
249  entry->key = malloc(key_size * sizeof(char));
250  strncpy((char*) entry->key, key, key_size);
251  } else {
252  entry->key = key;
253  }
254  entry->value = value;
255  entry->hash = hash;
256  entry->next = *oentry;
257  *oentry = entry;
258 
259  h->filled++;
260  if ((h->filled * 100 / (h->max_bucket + 1)) > PHASH_FILLPCT) {
261  if (phash_split(h)) {
262  return -1;
263  }
264  }
265 
266  return 0;
267 }
268 
270  h->iter_i = -1;
271  h->iter = NULL;
272  return h->filled;
273 }
274 
275 int phash_next(phash *h, const char **key, void **value) {
276  if (h == NULL) {
277  return -1;
278  }
279  phash_bucket *b = h->iter;
280  do {
281  if (b != NULL) {
282  b = b->next;
283  }
284  if (b == NULL) {
285  h->iter_i++;
286  if (h->iter_i > h->max_bucket) {
287  h->iter_i = -1;
288  break;
289  }
290  b = h->buckets[h->iter_i];
291  }
292  } while (b == NULL);
293  h->iter = b;
294  if (b == NULL) {
295  if (key != NULL) {
296  *key = NULL;
297  }
298  if (value != NULL) {
299  *value = NULL;
300  }
301  return 1;
302  }
303  if (key != NULL) {
304  *key = b->key;
305  }
306  if (value != NULL) {
307  *value = b->value;
308  }
309  return 0;
310 }
311 
313  return h->filled;
314 }
315 
316 const char *phash_version() {
317  return "phash " PHASH_IMPLEMENTATION_STR ", API " PHASH_API_VERSION_STR;
318 }
int32 value
Definition: Granule.c:1235
#define PHASH_INITIAL_SIZE
Size to initialize hash to upon creation.
Definition: phash.c:19
#define PHASH_NO_COPY_KEYS
Definition: phash.h:30
int iter_i
Definition: phash.c:44
int phash_size(phash *h)
Retrieves the number of key-value pairs in the hash object.
Definition: phash.c:312
#define PHASH_API_VERSION_STR
Definition: phash.c:5
#define NULL
Definition: decode_rs.h:63
phash * owner
Definition: phash.c:33
float h[MODELMAX]
Definition: atrem_corl1.h:131
A simple dictionary library for storing pointers.
phash * phash_create(uint32_t options)
Initialize a phash object.
Definition: phash.c:107
#define PHASH_FILLPCT
How full to get before doubling the size of the hash, 0-99.
Definition: phash.c:27
phash_bucket ** buckets
Definition: phash.c:41
void * value
Definition: phash.c:36
int phash_remove(phash *h, const char *key)
Remove a pointer associated with the given string.
Definition: phash.c:146
int filled
Definition: phash.c:43
#define PHASH_IMPLEMENTATION_STR
Definition: phash.c:3
phash_bucket * iter
Definition: phash.c:46
Implementation-specific, generic type to store the phash object.
Definition: phash.c:40
@ tail
Definition: dataday.h:37
phash_bucket * next
Definition: phash.c:34
int phash_set(phash *h, const char *key, void *value)
Add or overwrite a pointer, associating it with the given key.
Definition: phash.c:224
unsigned options
Definition: phash.c:45
void * phash_get(phash *h, const char *key)
Find a pointer associated with the given string.
Definition: phash.c:205
data_t b[NROOTS+1]
Definition: decode_rs.h:77
uint32_t hash
Definition: phash.c:37
const char * key
Definition: phash.c:35
int max_bucket
Definition: phash.c:42
PARAM_TYPE_NONE Default value No parameter is buried in the product name name_prefix is case insensitive string compared to the product name PARAM_TYPE_VIS_WAVE The visible wavelength bands from the sensor are buried in the product name The product name is compared by appending and name_suffix ie aph_412_giop where prod_ix will be set to PARAM_TYPE_IR_WAVE same search method as PARAM_TYPE_VIS_WAVE except only wavelength above are looped through but prod_ix is still based ie aph_2_giop for the second and prod_ix set to PARAM_TYPE_INT name_prefix is compared with the beginning of the product name If name_suffix is not empty the it must match the end of the product name The characters right after the prefix are read as an integer and prod_ix is set to that number strncpy(l2prod->name_prefix, "myprod", UNITLEN)
const char * phash_version()
Returns the source code version and the implemented API version.
Definition: phash.c:316
int phash_next(phash *h, const char **key, void **value)
Retrieves the next key-value pair in the phash. The order in which the pointers are returned shall be...
Definition: phash.c:275
int phash_destroy(phash *h)
Destroy a phash object, free'ing the memory used.
Definition: phash.c:136
int phash_rewind(phash *h)
Rewind iterator for traversing all the keys and values.
Definition: phash.c:269
int i
Definition: decode_rs.h:71
PGE01 indicating that PGE02 PGE01 V6 for and PGE01 V2 for MOD03 were used to produce the granule By convention adopted in all MODIS Terra PGE02 code versions are The fourth digit of the PGE02 version denotes the LUT version used to produce the granule The source of the metadata environment variable ProcessingCenter was changed from a QA LUT value to the Process Configuration A sign used in error in the second order term was changed to a
Definition: HISTORY.txt:424
int k
Definition: decode_rs.h:73