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 "selinux_map.h"
16 #include <stdlib.h>
17 #include <string.h>
18
19 static const int32_t MAX_BUCKET = 32;
20
GenerateHashCode(const char * key,uint32_t len)21 static int GenerateHashCode(const char *key, uint32_t len)
22 {
23 int code = 0;
24 for (size_t i = 0; i < len; i++) {
25 code += key[i] - 'A';
26 }
27 return code;
28 }
29
GroupNodeNodeCompare(const HashNode * node1,const HashNode * node2)30 static int GroupNodeNodeCompare(const HashNode *node1, const HashNode *node2)
31 {
32 ParamHashNode *groupNode1 = HASHMAP_ENTRY(node1, ParamHashNode, hashNode);
33 ParamHashNode *groupNode2 = HASHMAP_ENTRY(node2, ParamHashNode, hashNode);
34 return strcmp(groupNode1->name, groupNode2->name);
35 }
36
GroupNodeKeyCompare(const HashNode * node1,const char * key)37 static int GroupNodeKeyCompare(const HashNode *node1, const char *key)
38 {
39 ParamHashNode *groupNode1 = HASHMAP_ENTRY(node1, ParamHashNode, hashNode);
40 return strncmp(groupNode1->name, key, groupNode1->nameLen);
41 }
42
GroupNodeGetNodeHashCode(const HashNode * node)43 static int GroupNodeGetNodeHashCode(const HashNode *node)
44 {
45 ParamHashNode *groupNode = HASHMAP_ENTRY(node, ParamHashNode, hashNode);
46 return GenerateHashCode(groupNode->name, groupNode->nameLen);
47 }
48
GroupNodeFree(const HashNode * node)49 static void GroupNodeFree(const HashNode *node)
50 {
51 ParamHashNode *groupNode = HASHMAP_ENTRY(node, ParamHashNode, hashNode);
52 free(groupNode);
53 }
54
HashMapCreate(HashTab ** handle)55 int32_t HashMapCreate(HashTab **handle)
56 {
57 if (handle == NULL) {
58 return -1;
59 }
60
61 HashTab *tab = (HashTab *)calloc(1, sizeof(HashTab) + sizeof(HashNode *) * MAX_BUCKET);
62 if (tab == NULL) {
63 return -1;
64 }
65 *handle = tab;
66 return 0;
67 }
68
GetHashNodeByNode(HashNode * root,const HashNode * nodeKey)69 static HashNode *GetHashNodeByNode(HashNode *root, const HashNode *nodeKey)
70 {
71 while (root != NULL) {
72 int ret = GroupNodeNodeCompare(root, nodeKey);
73 if (ret == 0) {
74 return root;
75 }
76 root = root->next;
77 }
78 return NULL;
79 }
80
GetHashNodeByKey(HashNode * root,const char * key)81 static HashNode *GetHashNodeByKey(HashNode *root, const char *key)
82 {
83 while (root != NULL) {
84 int ret = GroupNodeKeyCompare(root, key);
85 if (ret == 0) {
86 return root;
87 }
88 root = root->next;
89 }
90 return NULL;
91 }
92
HashMapAdd(HashTab * handle,HashNode * node)93 int32_t HashMapAdd(HashTab *handle, HashNode *node)
94 {
95 if (handle == NULL || !(node != NULL && node->next == NULL)) {
96 return -1;
97 }
98 int hashCode = GroupNodeGetNodeHashCode(node);
99 hashCode = (hashCode < 0) ? -hashCode : hashCode;
100 hashCode = hashCode % MAX_BUCKET;
101
102 // check key exist
103 HashNode *tmp = GetHashNodeByNode(handle->buckets[hashCode], node);
104 if (tmp != NULL) {
105 return -1;
106 }
107 node->next = handle->buckets[hashCode];
108 handle->buckets[hashCode] = node;
109 return 0;
110 }
111
HashMapGet(HashTab * handle,const char * key,uint32_t len)112 HashNode *HashMapGet(HashTab *handle, const char *key, uint32_t len)
113 {
114 int hashCode = GenerateHashCode(key, len);
115 hashCode = (hashCode < 0) ? -hashCode : hashCode;
116 hashCode = hashCode % MAX_BUCKET;
117
118 return GetHashNodeByKey(handle->buckets[hashCode], key);
119 }
120
HashListFree(HashNode * root)121 static void HashListFree(HashNode *root)
122 {
123 if (root == NULL) {
124 return;
125 }
126 HashNode *node = root;
127 while (node != NULL) {
128 HashNode *next = node->next;
129 GroupNodeFree(node);
130 node = next;
131 }
132 }
133
HashMapDestroy(HashTab * handle)134 void HashMapDestroy(HashTab *handle)
135 {
136 if (handle == NULL) {
137 return;
138 }
139 for (int i = 0; i < MAX_BUCKET; i++) {
140 HashListFree(handle->buckets[i]);
141 }
142 free(handle);
143 }
144