blob: 448bc49f47b43a6a02bd2daa8253b8fd2f5ddeb4 [file] [log] [blame]
Mayank Groverf3b78182017-12-19 13:31:30 +05301
2#include "libufdt.h"
3#include "ufdt_util.h"
4
5/*
6 * BEGIN of Hash table internal implementations.
7 */
8
9#define DICT_LIMIT_NUM 2
10#define DICT_LIMIT_DEN 3
11
12static bool _ufdt_node_dict_is_too_full(struct ufdt_node_dict *dict) {
13 /*
14 * We say a dict is too full if it's DICT_LIMIT_NUM / DICT_LIMIT_DEN full.
15 */
16 if (dict->num_used * DICT_LIMIT_DEN > dict->mem_size * DICT_LIMIT_NUM)
17 return true;
18 return false;
19}
20
21/*
22 * If collision happened, use linear probing to find idx in the hash table.
23 */
24static int _ufdt_node_dict_find_index_by_name_len(struct ufdt_node **hash_table,
25 int size, const char *name,
26 int len) {
27 if (!name || !size) return -1;
28 /*
29 * All size should be 2^k for some k
30 */
31 int hsh = get_hash_len(name, len);
32 int idx = hsh & (size - 1);
33 for (int cnt = 0; cnt < size; ++cnt) {
34 if (hash_table[idx] == NULL) return idx;
35 if (node_name_eq(hash_table[idx], name, len) == 1) return idx;
36 ++idx;
37 idx &= (size - 1);
38 }
39 return -1;
40}
41
42static int _ufdt_node_dict_find_index_by_name(struct ufdt_node **hash_table,
43 int size, const char *name) {
44 return _ufdt_node_dict_find_index_by_name_len(hash_table, size, name,
45 dto_strlen(name));
46}
47
48static int _ufdt_node_dict_find_index_in_ht(struct ufdt_node **hash_table,
49 int size, struct ufdt_node *x) {
50 if (x == NULL) return -1;
51 return _ufdt_node_dict_find_index_by_name(hash_table, size, name_of(x));
52}
53
54/*
55 * END of Hash table internal implementations.
56 */
57
58/*
59 * ufdt_node_dict methods.
60 */
61
62struct ufdt_node_dict ufdt_node_dict_construct() {
63 struct ufdt_node_dict res;
64 res.mem_size = DTNL_INIT_SZ;
65 res.num_used = 0;
66 res.nodes = dto_malloc(DTNL_INIT_SZ * sizeof(struct ufdt_node *));
67 if (res.nodes == NULL) {
68 res.mem_size = 0;
69 return res;
70 }
71 dto_memset(res.nodes, 0, DTNL_INIT_SZ * sizeof(struct ufdt_node *));
72 return res;
73}
74
75void ufdt_node_dict_destruct(struct ufdt_node_dict *dict) {
76 if (dict == NULL) return;
77 dto_free(dict->nodes);
78 dict->mem_size = dict->num_used = 0;
79}
80
81static int ufdt_node_dict_resize(struct ufdt_node_dict *dict) {
82 if (dict == NULL) return -1;
83
84 int new_size = dict->mem_size << 1;
85
86 struct ufdt_node **new_nodes =
87 dto_malloc(new_size * sizeof(struct ufdt_node *));
88
89 dto_memset(new_nodes, 0, new_size * sizeof(struct ufdt_node *));
90
91 for (int i = 0; i < dict->mem_size; i++) {
92 struct ufdt_node *node = dict->nodes[i];
93 if (node == NULL) continue;
94 int idx = _ufdt_node_dict_find_index_in_ht(new_nodes, new_size, node);
95 if (idx < 0) {
96 dto_error(
97 "failed to find new index in ufdt_node_dict resize for entry :%s:\n",
98 name_of(node));
99 dto_free(new_nodes);
100 return -1;
101 }
102 new_nodes[idx] = node;
103 }
104
105 dto_free(dict->nodes);
106
107 dict->mem_size = new_size;
108 dict->nodes = new_nodes;
109 return 0;
110}
111
112int ufdt_node_dict_add(struct ufdt_node_dict *dict, struct ufdt_node *node) {
113 if (node == NULL) return -1;
114 if (dict == NULL) return -1;
115
116 int idx = _ufdt_node_dict_find_index_in_ht(dict->nodes, dict->mem_size, node);
117 if (idx < 0) {
118 dto_error("failed to find new index in ufdt_node_dict add for entry :%s:\n",
119 name_of(node));
120 return -1;
121 }
122
123 if (dict->nodes[idx] == NULL) ++dict->num_used;
124 dict->nodes[idx] = node;
125
126 /*
127 * When the hash table is too full, double the size and rehashing.
128 */
129 int err = 0;
130 if (_ufdt_node_dict_is_too_full(dict)) {
131 err = ufdt_node_dict_resize(dict);
132 }
133
134 return err;
135}
136
137/*
138 * BEGIN of ufdt_dict searching related methods.
139 */
140
141/*
142 * return a pointer to the hash table entry
143 */
144struct ufdt_node **ufdt_node_dict_find_len(struct ufdt_node_dict *dict,
145 const char *name, int len) {
146 if (dict == NULL) return NULL;
147 int idx = _ufdt_node_dict_find_index_by_name_len(dict->nodes, dict->mem_size,
148 name, len);
149 if (idx < 0) return NULL;
150 if (dict->nodes[idx] == NULL) return NULL;
151 return dict->nodes + idx;
152}
153
154struct ufdt_node **ufdt_node_dict_find(struct ufdt_node_dict *dict,
155 const char *name) {
156 return ufdt_node_dict_find_len(dict, name, dto_strlen(name));
157}
158
159struct ufdt_node *ufdt_node_dict_find_node_len(struct ufdt_node_dict *dict,
160 const char *name, int len) {
161 struct ufdt_node **res = ufdt_node_dict_find_len(dict, name, len);
162 if (res == NULL) return NULL;
163 return *res;
164}
165
166struct ufdt_node *ufdt_node_dict_find_node(struct ufdt_node_dict *dict,
167 const char *name) {
168 return ufdt_node_dict_find_node_len(dict, name, dto_strlen(name));
169}
170
171/*
172 * END of ufdt_dict searching related methods.
173 */
174
175void ufdt_node_dict_print(struct ufdt_node_dict *dict) {
176 struct ufdt_node **it;
177 for_each(it, dict) dto_print("%ld -> %s\n", it - dict->nodes, name_of(*it));
178}