source: mainline/uspace/lib/nic/src/nic_addr_db.c@ 84239b1

lfn serial ticket/834-toolchain-update topic/msim-upgrade topic/simplify-dev-export
Last change on this file since 84239b1 was a35b458, checked in by Jiří Zárevúcky <zarevucky.jiri@…>, 8 years ago

style: Remove trailing whitespace on _all_ lines, including empty ones, for particular file types.

Command used: tools/srepl '\s\+$' '' -- *.c *.h *.py *.sh *.s *.S *.ag

Currently, whitespace on empty lines is very inconsistent.
There are two basic choices: Either remove the whitespace, or keep empty lines
indented to the level of surrounding code. The former is AFAICT more common,
and also much easier to do automatically.

Alternatively, we could write script for automatic indentation, and use that
instead. However, if such a script exists, it's possible to use the indented
style locally, by having the editor apply relevant conversions on load/save,
without affecting remote repository. IMO, it makes more sense to adopt
the simpler rule.

  • Property mode set to 100644
File size: 6.3 KB
Line 
1/*
2 * Copyright (c) 2011 Radim Vansa
3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 *
9 * - Redistributions of source code must retain the above copyright
10 * notice, this list of conditions and the following disclaimer.
11 * - Redistributions in binary form must reproduce the above copyright
12 * notice, this list of conditions and the following disclaimer in the
13 * documentation and/or other materials provided with the distribution.
14 * - The name of the author may not be used to endorse or promote products
15 * derived from this software without specific prior written permission.
16 *
17 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
18 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
19 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
20 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
21 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
22 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
23 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
24 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
26 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27 */
28
29/**
30 * @addtogroup libnic
31 * @{
32 */
33/**
34 * @file
35 * @brief Generic hash-set based database of addresses
36 */
37#include "nic_addr_db.h"
38#include <assert.h>
39#include <stdlib.h>
40#include <stdbool.h>
41#include <errno.h>
42#include <mem.h>
43#include <adt/hash_table.h>
44#include <macros.h>
45#include <stdint.h>
46
47
48/**
49 * Helper structure for keeping the address in the hash set.
50 */
51typedef struct nic_addr_entry {
52 ht_link_t link;
53 uint8_t len;
54 uint8_t addr[1];
55} nic_addr_entry_t;
56
57
58/*
59 * Hash table helper functions
60 */
61typedef struct {
62 size_t len;
63 const uint8_t *addr;
64} addr_key_t;
65
66static bool nic_addr_key_equal(void *key_arg, const ht_link_t *item)
67{
68 addr_key_t *key = (addr_key_t*)key_arg;
69 nic_addr_entry_t *entry = member_to_inst(item, nic_addr_entry_t, link);
70
71 return memcmp(entry->addr, key->addr, entry->len) == 0;
72}
73
74static size_t addr_hash(size_t len, const uint8_t *addr)
75{
76 size_t hash = 0;
77
78 for (size_t i = 0; i < len; ++i) {
79 hash = (hash << 5) ^ addr[i];
80 }
81
82 return hash;
83}
84
85static size_t nic_addr_key_hash(void *k)
86{
87 addr_key_t *key = (addr_key_t*)k;
88 return addr_hash(key->len, key->addr);
89}
90
91static size_t nic_addr_hash(const ht_link_t *item)
92{
93 nic_addr_entry_t *entry = member_to_inst(item, nic_addr_entry_t, link);
94 return addr_hash(entry->len, entry->addr);
95}
96
97static void nic_addr_removed(ht_link_t *item)
98{
99 nic_addr_entry_t *entry = member_to_inst(item, nic_addr_entry_t, link);
100
101 free(entry);
102}
103
104static hash_table_ops_t set_ops = {
105 .hash = nic_addr_hash,
106 .key_hash = nic_addr_key_hash,
107 .key_equal = nic_addr_key_equal,
108 .equal = NULL,
109 .remove_callback = nic_addr_removed
110};
111
112/**
113 * Initialize the database
114 *
115 * @param[in,out] db Uninitialized storage
116 * @param[in] addr_len Size of addresses in the db
117 *
118 * @return EOK If successfully initialized
119 * @return EINVAL If the address length is too big
120 * @return ENOMEM If there was not enough memory to initialize the storage
121 */
122errno_t nic_addr_db_init(nic_addr_db_t *db, size_t addr_len)
123{
124 assert(db);
125
126 if (addr_len > UCHAR_MAX)
127 return EINVAL;
128
129 if (!hash_table_create(&db->set, 0, 0, &set_ops))
130 return ENOMEM;
131
132 db->addr_len = addr_len;
133 return EOK;
134}
135
136/**
137 * Remove all records from the DB
138 *
139 * @param db
140 */
141void nic_addr_db_clear(nic_addr_db_t *db)
142{
143 assert(db);
144 hash_table_clear(&db->set);
145}
146
147/**
148 * Free the memory used by db, including all records...
149 *
150 * @param db
151 */
152void nic_addr_db_destroy(nic_addr_db_t *db)
153{
154 assert(db);
155 hash_table_destroy(&db->set);
156}
157
158
159/**
160 * Insert an address to the db
161 *
162 * @param db
163 * @param addr Inserted address. Length is implicitly concluded from the
164 * db's address length.
165 *
166 * @return EOK If the address was inserted
167 * @return ENOMEM If there was not enough memory
168 * @return EEXIST If this adress already is in the db
169 */
170errno_t nic_addr_db_insert(nic_addr_db_t *db, const uint8_t *addr)
171{
172 assert(db && addr);
173
174 addr_key_t key = {
175 .len = db->addr_len,
176 .addr = addr
177 };
178
179 if (hash_table_find(&db->set, &key))
180 return EEXIST;
181
182 nic_addr_entry_t *entry = malloc(sizeof(nic_addr_entry_t) + db->addr_len - 1);
183 if (entry == NULL)
184 return ENOMEM;
185
186 entry->len = (uint8_t) db->addr_len;
187 memcpy(entry->addr, addr, db->addr_len);
188
189 hash_table_insert(&db->set, &entry->link);
190 return EOK;
191}
192
193/**
194 * Remove the address from the db
195 *
196 * @param db
197 * @param addr Removed address.
198 *
199 * @return EOK If the address was removed
200 * @return ENOENT If there is no address
201 */
202errno_t nic_addr_db_remove(nic_addr_db_t *db, const uint8_t *addr)
203{
204 assert(db && addr);
205
206 addr_key_t key = {
207 .len = db->addr_len,
208 .addr = addr
209 };
210
211 if (hash_table_remove(&db->set, &key))
212 return EOK;
213 else
214 return ENOENT;
215}
216
217/**
218 * Test if the address is contained in the db
219 *
220 * @param db
221 * @param addr Tested addresss
222 *
223 * @return true if the address is in the db, false otherwise
224 */
225bool nic_addr_db_contains(const nic_addr_db_t *db, const uint8_t *addr)
226{
227 assert(db && addr);
228
229 addr_key_t key = {
230 .len = db->addr_len,
231 .addr = addr
232 };
233
234 return 0 != hash_table_find(&db->set, &key);
235}
236
237/**
238 * Helper structure for nic_addr_db_foreach
239 */
240typedef struct {
241 void (*func)(const uint8_t *, void *);
242 void *arg;
243} nic_addr_db_fe_arg_t;
244
245/**
246 * Helper function for nic_addr_db_foreach
247 */
248static bool nic_addr_db_fe_helper(ht_link_t *item, void *arg)
249{
250 nic_addr_db_fe_arg_t *hs = (nic_addr_db_fe_arg_t *) arg;
251 nic_addr_entry_t *entry = member_to_inst(item, nic_addr_entry_t, link);
252 hs->func(entry->addr, hs->arg);
253 return true;
254}
255
256/**
257 * Executes a user-defined function on all addresses in the DB. The function
258 * must not change the addresses.
259 *
260 * @param db
261 * @param func User-defined function
262 * @param arg Custom argument passed to the function
263 */
264void nic_addr_db_foreach(const nic_addr_db_t *db,
265 void (*func)(const uint8_t *, void *), void *arg)
266{
267 nic_addr_db_fe_arg_t hs = { .func = func, .arg = arg };
268 hash_table_apply((hash_table_t*)&db->set, nic_addr_db_fe_helper, &hs);
269}
270
271/** @}
272 */
Note: See TracBrowser for help on using the repository browser.