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