aboutsummaryrefslogtreecommitdiffstats
path: root/lib/includes/hicn/util/map.h
blob: 1ac5812ef81d586492d16b451a0fa8d9587cf5c9 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
/*
 * Copyright (c) 2017-2019 Cisco and/or its affiliates.
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at:
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

#ifndef UTIL_MAP_H
#define UTIL_MAP_H

#include <stdlib.h>

#include "set.h"

#define ERR_MAP_EXISTS -2
#define ERR_MAP_NOT_FOUND -3

#define TYPEDEF_MAP_H(NAME, KEY_T, VAL_T)                                       \
                                                                                \
typedef struct {                                                                \
    KEY_T key;                                                                  \
    VAL_T value;                                                                \
} NAME ## _pair_t;                                                              \
                                                                                \
NAME ## _pair_t * NAME ## _pair_create(KEY_T key, VAL_T value);                 \
                                                                                \
void NAME ## _pair_free(NAME ## _pair_t * pair);                                \
                                                                                \
int NAME ## _pair_cmp(const NAME ## _pair_t * p1, const NAME ## _pair_t * p2);  \
                                                                                \
TYPEDEF_SET_H(NAME ## _pair_set, NAME ## _pair_t *)                             \
                                                                                \
typedef struct NAME ## _s {                                                     \
    NAME ## _pair_set_t pair_set;                                               \
} NAME ## _t;                                                                   \
                                                                                \
int NAME ## _initialize(NAME ## _t * map);                                      \
                                                                                \
int NAME ## _finalize(NAME ## _t * map);                                        \
                                                                                \
NAME ## _t * NAME ## _create();                                                 \
                                                                                \
void NAME ## _free(NAME ## _t * map);                                           \
                                                                                \
int NAME ## _add(NAME ## _t * map, KEY_T key, VAL_T value);                     \
                                                                                \
int NAME ## _remove(NAME ## _t * map, KEY_T key, VAL_T * value);                \
                                                                                \
int NAME ## _get(NAME ## _t * map, KEY_T key, VAL_T * value);                   \
                                                                                \
void NAME ## _dump(NAME ## _t * map);




#define TYPEDEF_MAP(NAME, KEY_T, VAL_T, CMP, KEY_SNPRINTF, VALUE_SNPRINTF)      \
                                                                                \
NAME ## _pair_t * NAME ## _pair_create(KEY_T key, VAL_T value)                  \
{                                                                               \
    /* Create pair */                                                           \
    NAME ## _pair_t * pair = malloc(sizeof(NAME ## _pair_t));                   \
    if (!pair)                                                                  \
        return NULL;                                                            \
                                                                                \
    pair->key = key;                                                            \
    pair->value = value;                                                        \
                                                                                \
    return pair;                                                                \
}                                                                               \
                                                                                \
void NAME ## _pair_free(NAME ## _pair_t * pair)                                 \
{                                                                               \
    free(pair);                                                                 \
}                                                                               \
                                                                                \
int                                                                             \
NAME ## _pair_cmp(const NAME ## _pair_t * p1, const NAME ## _pair_t * p2)       \
{                                                                               \
    return (CMP(p1->key, p2->key));                                             \
}                                                                               \
                                                                                \
int                                                                             \
NAME ## _pair_snprintf(char * buf, size_t size, const NAME ## _pair_t * pair) { \
    int rc;                                                                     \
    rc = KEY_SNPRINTF(buf, BUFSIZE/2, (KEY_T)pair->key);                        \
    if (rc < 0)                                                                 \
        return rc;                                                              \
    rc = VALUE_SNPRINTF(buf+rc, BUFSIZE/2, (VAL_T)pair->value);                 \
    return rc;                                                                  \
}                                                                               \
                                                                                \
TYPEDEF_SET(NAME ## _pair_set, NAME ## _pair_t *, NAME ## _pair_cmp, NAME ## _pair_snprintf); \
                                                                                \
int                                                                             \
NAME ## _initialize(NAME ## _t * map)                                           \
{                                                                               \
    return NAME ## _pair_set_initialize(&map->pair_set);                        \
}                                                                               \
                                                                                \
int                                                                             \
NAME ## _finalize(NAME ## _t * map)                                             \
{                                                                               \
    NAME ## _pair_t ** array;                                                   \
    int n = NAME ## _pair_set_get_array(&map->pair_set, &array);                \
    if (n < 0)                                                                  \
        return -1;                                                              \
    for (unsigned i = 0; i < n; i++) {                                          \
        NAME ## _pair_t * pair = array[i];                                      \
        NAME ## _pair_set_remove(&map->pair_set, pair, NULL);                   \
        NAME ## _pair_free(pair);                                               \
    }                                                                           \
    free(array);                                                                \
    return NAME ## _pair_set_finalize(&map->pair_set);                          \
}                                                                               \
                                                                                \
NAME ## _t *                                                                    \
NAME ## _create()                                                               \
{                                                                               \
    NAME ## _t * map = malloc(sizeof(NAME ## _t));                              \
    if (!map)                                                                   \
        goto ERR_MALLOC;                                                        \
                                                                                \
    if (NAME ## _initialize(map) < 0)                                           \
        goto ERR_INITIALIZE;                                                    \
                                                                                \
    return map;                                                                 \
                                                                                \
ERR_INITIALIZE:                                                                 \
    free(map);                                                                  \
ERR_MALLOC:                                                                     \
    return NULL;                                                                \
}                                                                               \
                                                                                \
void                                                                            \
NAME ## _free(NAME ## _t * map)                                                 \
{                                                                               \
    NAME ## _finalize(map);                                                     \
    free(map);                                                                  \
}                                                                               \
                                                                                \
int                                                                             \
NAME ## _add(NAME ## _t * map, KEY_T key, VAL_T value)                          \
{                                                                               \
    int rc;                                                                     \
    NAME ## _pair_t * found = NULL;                                             \
                                                                                \
    NAME ## _pair_t * pair = NAME ## _pair_create(key, value);                  \
    if (!pair)                                                                  \
        return -1;                                                              \
                                                                                \
    rc = NAME ## _pair_set_get(&map->pair_set, pair, &found);                   \
    if (rc < 0)                                                                 \
        return -1;                                                              \
    if (found) {                                                                \
        NAME ## _pair_free(pair);                                               \
        return ERR_MAP_EXISTS;                                                  \
    }                                                                           \
                                                                                \
    rc = NAME ## _pair_set_add(&map->pair_set, pair);                           \
    if (rc < 0) {                                                               \
        NAME ## _pair_free(pair);                                               \
        return -1;                                                              \
    }                                                                           \
    return 0;                                                                   \
}                                                                               \
                                                                                \
int                                                                             \
NAME ## _remove(NAME ## _t * map, KEY_T key, VAL_T * value)                     \
{                                                                               \
    NAME ## _pair_t * found = NULL;                                             \
    NAME ## _pair_t search = { .key = key };                                    \
    int rc = NAME ## _pair_set_remove(&map->pair_set, &search, &found);         \
    if (rc < 0)                                                                 \
        return ERR_MAP_NOT_FOUND;                                               \
    if (value)                                                                  \
        *value = found->value;                                                  \
    NAME ## _pair_free(found);                                                  \
    return 0;                                                                   \
}                                                                               \
                                                                                \
int                                                                             \
NAME ## _get(NAME ## _t * map, KEY_T key, VAL_T * value)                        \
{                                                                               \
    NAME ## _pair_t * found = NULL, search = { .key = key };                    \
    int rc = NAME ## _pair_set_get(&map->pair_set, &search, &found);            \
    if (rc < 0)                                                                 \
        return -1;                                                              \
    if (found)                                                                  \
        *value = found->value;                                                  \
    return 0;                                                                   \
}                                                                               \
                                                                                \
void                                                                            \
NAME ## _dump(NAME ## _t * map) {                                               \
    NAME ## _pair_set_dump(&map->pair_set);                                     \
}                                                                               \
                                                                                \
int                                                                             \
NAME ## _get_key_array(NAME ## _t * map, KEY_T **array) {                       \
    NAME ## _pair_t ** pair_array;                                              \
    int n = NAME ## _pair_set_get_array(&map->pair_set, &pair_array);           \
    if (n < 0)                                                                  \
        return -1;                                                              \
    if (!array)                                                                 \
        goto END;                                                               \
    /* Allocate result array */                                                 \
    *array = malloc(n * sizeof(KEY_T));                                         \
    if (!array) {                                                               \
        free(pair_array);                                                       \
        return -1;                                                              \
    }                                                                           \
    /* Copy keys */                                                             \
    for (int i = 0; i < n; i++)                                                 \
        (*array)[i] = pair_array[i]->key;                                       \
    free(pair_array);                                                           \
END:                                                                            \
    return n;                                                                   \
}                                                                               \
                                                                                \
int                                                                             \
NAME ## _get_value_array(NAME ## _t * map, VAL_T **array) {                     \
    NAME ## _pair_t ** pair_array;                                              \
    int n = NAME ## _pair_set_get_array(&map->pair_set, &pair_array);           \
    if (n < 0)                                                                  \
        return -1;                                                              \
    if (!array)                                                                 \
        goto END;                                                               \
    /* Allocate result array */                                                 \
    *array = malloc(n * sizeof(VAL_T));                                         \
    if (!array) {                                                               \
        free(pair_array);                                                       \
        return -1;                                                              \
    }                                                                           \
    /* Copy values */                                                           \
    for (int i = 0; i < n; i++)                                                 \
        (*array)[i] = pair_array[i]->value;                                     \
    free(pair_array);                                                           \
END:                                                                            \
    return n;                                                                   \
}

#endif /* UTIL_MAP_H */