1 /******************************************************************************
2  *
3  *  Copyright (C) 2015 Google, Inc.
4  *
5  *  Licensed under the Apache License, Version 2.0 (the "License");
6  *  you may not use this file except in compliance with the License.
7  *  You may obtain a copy of the License at:
8  *
9  *  http://www.apache.org/licenses/LICENSE-2.0
10  *
11  *  Unless required by applicable law or agreed to in writing, software
12  *  distributed under the License is distributed on an "AS IS" BASIS,
13  *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14  *  See the License for the specific language governing permissions and
15  *  limitations under the License.
16  *
17  ******************************************************************************/
18 #define LOG_TAG "hash_map_utils"
19 
20 #include "osi/include/hash_map_utils.h"
21 
22 #include <assert.h>
23 #include <string.h>
24 
25 #include "osi/include/allocator.h"
26 #include "osi/include/hash_functions.h"
27 #include "osi/include/hash_map.h"
28 #include "osi/include/log.h"
29 #include "osi/include/osi.h"
30 
31 static bool string_equals(const void *key_a, const void *key_b);
32 static bool dump_entry(hash_map_entry_t *entry, UNUSED_ATTR void *context);
33 
34 static const size_t BUCKETS_NUM = 5;
35 
hash_map_utils_new_from_string_params(const char * params)36 hash_map_t *hash_map_utils_new_from_string_params(const char *params) {
37   assert(params != NULL);
38 
39   hash_map_t *map = hash_map_new(BUCKETS_NUM, hash_function_string, osi_free,
40                                  osi_free, string_equals);
41   if (!map)
42     return NULL;
43 
44   char *str = osi_strdup(params);
45   if (!str)
46     return NULL;
47 
48   LOG_VERBOSE(LOG_TAG, "%s: source string: '%s'", __func__, str);
49 
50   // Parse |str| and add extracted key-and-value pair(s) in |map|.
51   int items = 0;
52   char *tmpstr;
53   char *kvpair = strtok_r(str, ";", &tmpstr);
54   while (kvpair && *kvpair) {
55     char *eq = strchr(kvpair, '=');
56 
57     if (eq == kvpair)
58       goto next_pair;
59 
60     char *key;
61     char *value;
62     if (eq) {
63       key = osi_strndup(kvpair, eq - kvpair);
64 
65       // The increment of |eq| moves |eq| to the beginning of the value.
66       ++eq;
67       value = (*eq != '\0') ? osi_strdup(eq) : osi_strdup("");
68     } else {
69       key = osi_strdup(kvpair);
70       value = osi_strdup("");
71     }
72 
73     hash_map_set(map, key, value);
74 
75     items++;
76 next_pair:
77     kvpair = strtok_r(NULL, ";", &tmpstr);
78   }
79 
80   if (!items)
81     LOG_VERBOSE(LOG_TAG, "%s: no items found in string\n", __func__);
82 
83   osi_free(str);
84   return map;
85 }
86 
hash_map_utils_dump_string_keys_string_values(hash_map_t * map)87 void hash_map_utils_dump_string_keys_string_values(hash_map_t *map) {
88   if (!map) {
89     LOG_VERBOSE( LOG_TAG, "%s: the given map is NULL\n", __func__);
90     return;
91   }
92   hash_map_foreach(map, dump_entry, NULL);
93 }
94 
string_equals(const void * key_a,const void * key_b)95 static bool string_equals(const void *key_a, const void *key_b) {
96   return !strcmp(key_a, key_b);
97 }
98 
dump_entry(hash_map_entry_t * entry,UNUSED_ATTR void * context)99 static bool dump_entry(hash_map_entry_t *entry, UNUSED_ATTR void *context) {
100   hash_map_entry_t *hash_map_entry = (hash_map_entry_t *)entry;
101   LOG_INFO(LOG_TAG, "key: '%s' value: '%s'\n", (char *)hash_map_entry->key,
102            (char *)hash_map_entry->data);
103   return true;
104 }
105