• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2022 Huawei Device Co., Ltd.
3  * Licensed under the Apache License, Version 2.0 (the "License");
4  * you may not use this file except in compliance with the License.
5  * You may obtain a copy of the License at
6  *
7  * http://www.apache.org/licenses/LICENSE-2.0
8  *
9  * Unless required by applicable law or agreed to in writing, software
10  * distributed under the License is distributed on an "AS IS" BASIS,
11  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12  * See the License for the specific language governing permissions and
13  * limitations under the License.
14  */
15 #include "init_hashmap.h"
16 
17 typedef struct {
18     HashNodeCompare nodeCompare;
19     HashKeyCompare keyCompare;
20     HashNodeFunction nodeHash;
21     HashKeyFunction keyHash;
22     HashNodeOnFree nodeFree;
23     int maxBucket;
24     uint32_t tableId;
25     HashNode *buckets[0];
26 } HashTab;
27 
28 static uint32_t g_tableId = 0;
HashMapCreate(HashMapHandle * handle,const HashInfo * info)29 int32_t HashMapCreate(HashMapHandle *handle, const HashInfo *info)
30 {
31     INIT_ERROR_CHECK(handle != NULL && info != NULL, return -1, "Invalid param");
32     INIT_ERROR_CHECK(info->keyHash != NULL && info->nodeHash != NULL, return -1, "Invalid param");
33     INIT_ERROR_CHECK(info->nodeCompare != NULL && info->keyCompare != NULL, return -1, "Invalid param");
34     uint32_t maxBucket = info->maxBucket;
35     if (info->maxBucket > HASH_TAB_BUCKET_MAX) {
36         maxBucket = HASH_TAB_BUCKET_MAX;
37     } else if (info->maxBucket < HASH_TAB_BUCKET_MIN) {
38         maxBucket = HASH_TAB_BUCKET_MIN;
39     }
40     HashTab *tab = (HashTab *)calloc(1, sizeof(HashTab) + sizeof(HashNode*) * maxBucket);
41     INIT_ERROR_CHECK(tab != NULL, return -1, "Failed to create hash tab");
42     tab->maxBucket = maxBucket;
43     tab->keyHash = info->keyHash;
44     tab->nodeCompare = info->nodeCompare;
45     tab->keyCompare = info->keyCompare;
46     tab->nodeHash = info->nodeHash;
47     tab->nodeFree = info->nodeFree;
48     tab->tableId = g_tableId;
49     INIT_LOGI("Create hash map success %d", g_tableId);
50     *handle = (HashMapHandle)tab;
51     return 0;
52 }
53 
GetHashNodeByNode(const HashTab * tab,const HashNode * root,const HashNode * new)54 static HashNode *GetHashNodeByNode(const HashTab *tab, const HashNode *root, const HashNode *new)
55 {
56     HashNode *node = (HashNode *)root;
57     while (node != NULL) {
58         int ret = tab->nodeCompare(node, new);
59         if (ret == 0) {
60             return node;
61         }
62         node = node->next;
63     }
64     return NULL;
65 }
66 
GetHashNodeByKey(const HashTab * tab,const HashNode * root,const void * key,HashKeyCompare keyCompare)67 static HashNode *GetHashNodeByKey(const HashTab *tab, const HashNode *root, const void *key, HashKeyCompare keyCompare)
68 {
69     HashNode *node = (HashNode *)root;
70     while (node != NULL) {
71         int ret = keyCompare(node, key);
72         if (ret == 0) {
73             return node;
74         }
75         node = node->next;
76     }
77     return NULL;
78 }
79 
HashMapAdd(HashMapHandle handle,HashNode * node)80 int32_t HashMapAdd(HashMapHandle handle, HashNode *node)
81 {
82     INIT_ERROR_CHECK(handle != NULL, return -1, "Invalid param");
83     INIT_ERROR_CHECK(node != NULL && node->next == NULL, return -1, "Invalid param");
84     HashTab *tab = (HashTab *)handle;
85     int hashCode = tab->nodeHash(node);
86     hashCode = (hashCode < 0) ? -hashCode : hashCode;
87     hashCode = hashCode % tab->maxBucket;
88     INIT_ERROR_CHECK(hashCode < tab->maxBucket, return -1, "Invalid hashcode %d %d", tab->maxBucket, hashCode);
89 
90     // check key exist
91     HashNode *tmp = GetHashNodeByNode(tab, tab->buckets[hashCode], node);
92     if (tmp != NULL) {
93         INIT_LOGE("node hash been exist");
94         return -1;
95     }
96     node->next = tab->buckets[hashCode];
97     tab->buckets[hashCode] = node;
98     INIT_LOGV("HashMapAdd tableId %d hashCode %d node %p", tab->tableId, hashCode, node);
99     return 0;
100 }
101 
HashMapRemove(HashMapHandle handle,const void * key)102 void HashMapRemove(HashMapHandle handle, const void *key)
103 {
104     INIT_ERROR_CHECK(handle != NULL && key != NULL, return, "Invalid param");
105     HashTab *tab = (HashTab *)handle;
106     int hashCode = tab->keyHash(key);
107     hashCode = (hashCode < 0) ? -hashCode : hashCode;
108     hashCode = hashCode % tab->maxBucket;
109     INIT_ERROR_CHECK(hashCode < tab->maxBucket, return, "Invalid hashcode %d %d", tab->maxBucket, hashCode);
110 
111     HashNode *node = tab->buckets[hashCode];
112     HashNode *preNode = node;
113     while (node != NULL) {
114         int ret = tab->keyCompare(node, key);
115         if (ret == 0) {
116             INIT_LOGV("HashMapRemove tableId %d hashCode %d node %p", tab->tableId, hashCode, node);
117             if (node == tab->buckets[hashCode]) {
118                 tab->buckets[hashCode] = node->next;
119             } else {
120                 preNode->next = node->next;
121             }
122             return;
123         }
124         preNode = node;
125         node = node->next;
126     }
127 }
128 
HashMapGet(HashMapHandle handle,const void * key)129 HashNode *HashMapGet(HashMapHandle handle, const void *key)
130 {
131     INIT_ERROR_CHECK(handle != NULL && key != NULL, return NULL, "Invalid param");
132     HashTab *tab = (HashTab *)handle;
133     int hashCode = tab->keyHash(key);
134     hashCode = (hashCode < 0) ? -hashCode : hashCode;
135     hashCode = hashCode % tab->maxBucket;
136     INIT_ERROR_CHECK(hashCode < tab->maxBucket, return NULL,
137         "Invalid hashcode %d %d", tab->maxBucket, hashCode);
138     return GetHashNodeByKey(tab, tab->buckets[hashCode], key, tab->keyCompare);
139 }
140 
HashListFree(HashTab * tab,HashNode * root)141 static void HashListFree(HashTab *tab, HashNode *root)
142 {
143     if (root == NULL) {
144         return;
145     }
146     HashNode *node = root;
147     while (node != NULL) {
148         HashNode *next = node->next;
149         if (tab->nodeFree != NULL) {
150             tab->nodeFree(node);
151         }
152         node = next;
153     }
154 }
155 
HashMapDestory(HashMapHandle handle)156 void HashMapDestory(HashMapHandle handle)
157 {
158     INIT_ERROR_CHECK(handle != NULL, return, "Invalid param");
159     HashTab *tab = (HashTab *)handle;
160     for (int i = 0; i < tab->maxBucket; i++) {
161         HashListFree(tab, tab->buckets[i]);
162     }
163     free(tab);
164 }
165 
HashMapFind(HashMapHandle handle,int hashCode,const void * key,HashKeyCompare keyCompare)166 HashNode *HashMapFind(HashMapHandle handle,
167     int hashCode, const void *key, HashKeyCompare keyCompare)
168 {
169     INIT_ERROR_CHECK(handle != NULL && key != NULL, return NULL, "Invalid param");
170     INIT_ERROR_CHECK(handle != NULL && keyCompare != NULL, return NULL, "Invalid param");
171     HashTab *tab = (HashTab *)handle;
172     INIT_ERROR_CHECK(hashCode < tab->maxBucket, return NULL,
173         "Invalid hashcode %d %d", tab->maxBucket, hashCode);
174     INIT_LOGV("HashMapGet tableId %d hashCode %d", tab->tableId, hashCode);
175     return GetHashNodeByKey(tab, tab->buckets[hashCode], key, keyCompare);
176 }