Coverage Report

Created: 2025-09-04 07:51

/src/fluent-bit/lib/librdkafka-2.10.1/src/rdmap.h
Line
Count
Source (jump to first uncovered line)
1
/*
2
 * librdkafka - The Apache Kafka C/C++ library
3
 *
4
 * Copyright (c) 2020-2022, Magnus Edenhill
5
 *               2023, Confluent Inc.
6
 * All rights reserved.
7
 *
8
 * Redistribution and use in source and binary forms, with or without
9
 * modification, are permitted provided that the following conditions are met:
10
 *
11
 * 1. Redistributions of source code must retain the above copyright notice,
12
 *    this list of conditions and the following disclaimer.
13
 * 2. Redistributions in binary form must reproduce the above copyright notice,
14
 *    this list of conditions and the following disclaimer in the documentation
15
 *    and/or other materials provided with the distribution.
16
 *
17
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
18
 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
19
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
20
 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
21
 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
22
 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
23
 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
24
 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
25
 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
26
 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
27
 * POSSIBILITY OF SUCH DAMAGE.
28
 */
29
30
#ifndef _RDMAP_H_
31
#define _RDMAP_H_
32
33
/**
34
 * @name Hash maps.
35
 *
36
 * Memory of key and value are allocated by the user but owned by the hash map
37
 * until elements are deleted or overwritten.
38
 *
39
 * The lower-case API provides a generic typeless (void *) hash map while
40
 * the upper-case API provides a strictly typed hash map implemented as macros
41
 * on top of the generic API.
42
 *
43
 * See rd_map_init(), et.al, for the generic API and RD_MAP_INITIALIZER()
44
 * for the typed API.
45
 *
46
 * @remark Not thread safe.
47
 */
48
49
50
/**
51
 * @struct Map element. This is the internal representation
52
 *         of the element and exposed to the user for iterating over the hash.
53
 */
54
typedef struct rd_map_elem_s {
55
        LIST_ENTRY(rd_map_elem_s) hlink; /**< Hash bucket link */
56
        LIST_ENTRY(rd_map_elem_s) link;  /**< Iterator link */
57
        unsigned int hash;               /**< Key hash value */
58
        const void *key;                 /**< Key (memory owned by map) */
59
        const void *value;               /**< Value (memory owned by map) */
60
} rd_map_elem_t;
61
62
63
/**
64
 * @struct Hash buckets (internal use).
65
 */
66
struct rd_map_buckets {
67
        LIST_HEAD(, rd_map_elem_s) * p; /**< Hash buckets array */
68
        int cnt;                        /**< Bucket count */
69
};
70
71
72
/**
73
 * @struct Hash map.
74
 */
75
typedef struct rd_map_s {
76
        struct rd_map_buckets rmap_buckets; /**< Hash buckets */
77
        int rmap_cnt;                       /**< Element count */
78
79
        LIST_HEAD(, rd_map_elem_s)
80
        rmap_iter; /**< Element list for iterating
81
                    *   over all elements. */
82
83
        int (*rmap_cmp)(const void *a, const void *b); /**< Key comparator */
84
        unsigned int (*rmap_hash)(const void *key);    /**< Key hash function */
85
        void (*rmap_destroy_key)(void *key);           /**< Optional key free */
86
        void (*rmap_destroy_value)(void *value); /**< Optional value free */
87
88
        void *rmap_opaque;
89
} rd_map_t;
90
91
92
93
/**
94
 * @brief Set/overwrite value in map.
95
 *
96
 * If an existing entry with the same key already exists its key and value
97
 * will be freed with the destroy_key and destroy_value functions
98
 * passed to rd_map_init().
99
 *
100
 * The map assumes memory ownership of both the \p key and \p value and will
101
 * use the destroy_key and destroy_value functions (if set) to free
102
 * the key and value memory when the map is destroyed or element removed.
103
 *
104
 * @returns the map element.
105
 */
106
rd_map_elem_t *rd_map_set(rd_map_t *rmap, void *key, void *value);
107
108
109
/**
110
 * @brief Look up \p key in the map and return its value, or NULL
111
 *        if \p key was not found.
112
 *
113
 * The returned memory is still owned by the map.
114
 */
115
void *rd_map_get(const rd_map_t *rmap, const void *key);
116
117
118
/**
119
 * @brief Delete \p key from the map, if it exists.
120
 *
121
 * The destroy_key and destroy_value functions (if set) will be used
122
 * to free the key and value memory.
123
 */
124
void rd_map_delete(rd_map_t *rmap, const void *key);
125
126
127
/** Key or Value Copy function signature. */
128
typedef void *(rd_map_copy_t)(const void *key_or_value);
129
130
131
/**
132
 * @brief Copy all elements from \p src to \p dst.
133
 *        \p dst must be initialized and compatible with \p src.
134
 *
135
 * @param dst Destination map to copy to.
136
 * @param src Source map to copy from.
137
 * @param key_copy Key copy callback. If NULL the \p dst key will just
138
 *                 reference the \p src key.
139
 * @param value_copy Value copy callback. If NULL the \p dst value will just
140
 *                   reference the \p src value.
141
 */
142
void rd_map_copy(rd_map_t *dst,
143
                 const rd_map_t *src,
144
                 rd_map_copy_t *key_copy,
145
                 rd_map_copy_t *value_copy);
146
147
148
/**
149
 * @returns the current number of elements in the map.
150
 */
151
size_t rd_map_cnt(const rd_map_t *rmap);
152
153
/**
154
 * @returns true if map is empty, else false.
155
 */
156
rd_bool_t rd_map_is_empty(const rd_map_t *rmap);
157
158
159
/**
160
 * @brief Iterate over all elements in the map.
161
 *
162
 * @warning The map MUST NOT be modified during the loop.
163
 *
164
 * @remark This is part of the untyped generic API.
165
 */
166
#define RD_MAP_FOREACH_ELEM(ELEM, RMAP)                                        \
167
0
        for (rd_map_iter_begin((RMAP), &(ELEM)); rd_map_iter(&(ELEM));         \
168
0
             rd_map_iter_next(&(ELEM)))
169
170
171
/**
172
 * @brief Begin iterating \p rmap, first element is set in \p *elem.
173
 */
174
void rd_map_iter_begin(const rd_map_t *rmap, const rd_map_elem_t **elem);
175
176
/**
177
 * @returns 1 if \p *elem is a valid iteration element, else 0.
178
 */
179
0
static RD_INLINE RD_UNUSED int rd_map_iter(const rd_map_elem_t **elem) {
180
0
        return *elem != NULL;
181
0
}
Unexecuted instantiation: rdkafka.c:rd_map_iter
Unexecuted instantiation: rdkafka_assignor.c:rd_map_iter
Unexecuted instantiation: rdkafka_broker.c:rd_map_iter
Unexecuted instantiation: rdkafka_buf.c:rd_map_iter
Unexecuted instantiation: rdkafka_cgrp.c:rd_map_iter
Unexecuted instantiation: rdkafka_conf.c:rd_map_iter
Unexecuted instantiation: rdkafka_feature.c:rd_map_iter
Unexecuted instantiation: rdkafka_metadata.c:rd_map_iter
Unexecuted instantiation: rdkafka_metadata_cache.c:rd_map_iter
Unexecuted instantiation: rdkafka_msg.c:rd_map_iter
Unexecuted instantiation: rdkafka_offset.c:rd_map_iter
Unexecuted instantiation: rdkafka_op.c:rd_map_iter
Unexecuted instantiation: rdkafka_partition.c:rd_map_iter
Unexecuted instantiation: rdkafka_pattern.c:rd_map_iter
Unexecuted instantiation: rdkafka_queue.c:rd_map_iter
Unexecuted instantiation: rdkafka_range_assignor.c:rd_map_iter
Unexecuted instantiation: rdkafka_request.c:rd_map_iter
Unexecuted instantiation: rdkafka_roundrobin_assignor.c:rd_map_iter
Unexecuted instantiation: rdkafka_sasl.c:rd_map_iter
Unexecuted instantiation: rdkafka_sasl_plain.c:rd_map_iter
Unexecuted instantiation: rdkafka_sticky_assignor.c:rd_map_iter
Unexecuted instantiation: rdkafka_subscription.c:rd_map_iter
Unexecuted instantiation: rdkafka_assignment.c:rd_map_iter
Unexecuted instantiation: rdkafka_timer.c:rd_map_iter
Unexecuted instantiation: rdkafka_topic.c:rd_map_iter
Unexecuted instantiation: rdkafka_transport.c:rd_map_iter
Unexecuted instantiation: rdkafka_interceptor.c:rd_map_iter
Unexecuted instantiation: rdkafka_header.c:rd_map_iter
Unexecuted instantiation: rdkafka_admin.c:rd_map_iter
Unexecuted instantiation: rdkafka_aux.c:rd_map_iter
Unexecuted instantiation: rdkafka_background.c:rd_map_iter
Unexecuted instantiation: rdkafka_idempotence.c:rd_map_iter
Unexecuted instantiation: rdkafka_txnmgr.c:rd_map_iter
Unexecuted instantiation: rdkafka_cert.c:rd_map_iter
Unexecuted instantiation: rdkafka_coord.c:rd_map_iter
Unexecuted instantiation: rdkafka_mock.c:rd_map_iter
Unexecuted instantiation: rdkafka_mock_handlers.c:rd_map_iter
Unexecuted instantiation: rdkafka_mock_cgrp.c:rd_map_iter
Unexecuted instantiation: rdkafka_error.c:rd_map_iter
Unexecuted instantiation: rdkafka_fetcher.c:rd_map_iter
Unexecuted instantiation: rdkafka_telemetry.c:rd_map_iter
Unexecuted instantiation: rdkafka_telemetry_decode.c:rd_map_iter
Unexecuted instantiation: rdkafka_telemetry_encode.c:rd_map_iter
Unexecuted instantiation: rdunittest.c:rd_map_iter
Unexecuted instantiation: rdmap.c:rd_map_iter
Unexecuted instantiation: snappy.c:rd_map_iter
Unexecuted instantiation: rdkafka_ssl.c:rd_map_iter
Unexecuted instantiation: rdkafka_plugin.c:rd_map_iter
Unexecuted instantiation: rdavl.c:rd_map_iter
Unexecuted instantiation: rdkafka_event.c:rd_map_iter
Unexecuted instantiation: rdkafka_lz4.c:rd_map_iter
Unexecuted instantiation: rdkafka_msgset_reader.c:rd_map_iter
Unexecuted instantiation: rdkafka_msgset_writer.c:rd_map_iter
Unexecuted instantiation: rdlog.c:rd_map_iter
182
183
/**
184
 * @brief Advances the iteration to the next element.
185
 */
186
0
static RD_INLINE RD_UNUSED void rd_map_iter_next(const rd_map_elem_t **elem) {
187
0
        *elem = LIST_NEXT(*elem, link);
188
0
}
Unexecuted instantiation: rdkafka.c:rd_map_iter_next
Unexecuted instantiation: rdkafka_assignor.c:rd_map_iter_next
Unexecuted instantiation: rdkafka_broker.c:rd_map_iter_next
Unexecuted instantiation: rdkafka_buf.c:rd_map_iter_next
Unexecuted instantiation: rdkafka_cgrp.c:rd_map_iter_next
Unexecuted instantiation: rdkafka_conf.c:rd_map_iter_next
Unexecuted instantiation: rdkafka_feature.c:rd_map_iter_next
Unexecuted instantiation: rdkafka_metadata.c:rd_map_iter_next
Unexecuted instantiation: rdkafka_metadata_cache.c:rd_map_iter_next
Unexecuted instantiation: rdkafka_msg.c:rd_map_iter_next
Unexecuted instantiation: rdkafka_offset.c:rd_map_iter_next
Unexecuted instantiation: rdkafka_op.c:rd_map_iter_next
Unexecuted instantiation: rdkafka_partition.c:rd_map_iter_next
Unexecuted instantiation: rdkafka_pattern.c:rd_map_iter_next
Unexecuted instantiation: rdkafka_queue.c:rd_map_iter_next
Unexecuted instantiation: rdkafka_range_assignor.c:rd_map_iter_next
Unexecuted instantiation: rdkafka_request.c:rd_map_iter_next
Unexecuted instantiation: rdkafka_roundrobin_assignor.c:rd_map_iter_next
Unexecuted instantiation: rdkafka_sasl.c:rd_map_iter_next
Unexecuted instantiation: rdkafka_sasl_plain.c:rd_map_iter_next
Unexecuted instantiation: rdkafka_sticky_assignor.c:rd_map_iter_next
Unexecuted instantiation: rdkafka_subscription.c:rd_map_iter_next
Unexecuted instantiation: rdkafka_assignment.c:rd_map_iter_next
Unexecuted instantiation: rdkafka_timer.c:rd_map_iter_next
Unexecuted instantiation: rdkafka_topic.c:rd_map_iter_next
Unexecuted instantiation: rdkafka_transport.c:rd_map_iter_next
Unexecuted instantiation: rdkafka_interceptor.c:rd_map_iter_next
Unexecuted instantiation: rdkafka_header.c:rd_map_iter_next
Unexecuted instantiation: rdkafka_admin.c:rd_map_iter_next
Unexecuted instantiation: rdkafka_aux.c:rd_map_iter_next
Unexecuted instantiation: rdkafka_background.c:rd_map_iter_next
Unexecuted instantiation: rdkafka_idempotence.c:rd_map_iter_next
Unexecuted instantiation: rdkafka_txnmgr.c:rd_map_iter_next
Unexecuted instantiation: rdkafka_cert.c:rd_map_iter_next
Unexecuted instantiation: rdkafka_coord.c:rd_map_iter_next
Unexecuted instantiation: rdkafka_mock.c:rd_map_iter_next
Unexecuted instantiation: rdkafka_mock_handlers.c:rd_map_iter_next
Unexecuted instantiation: rdkafka_mock_cgrp.c:rd_map_iter_next
Unexecuted instantiation: rdkafka_error.c:rd_map_iter_next
Unexecuted instantiation: rdkafka_fetcher.c:rd_map_iter_next
Unexecuted instantiation: rdkafka_telemetry.c:rd_map_iter_next
Unexecuted instantiation: rdkafka_telemetry_decode.c:rd_map_iter_next
Unexecuted instantiation: rdkafka_telemetry_encode.c:rd_map_iter_next
Unexecuted instantiation: rdunittest.c:rd_map_iter_next
Unexecuted instantiation: rdmap.c:rd_map_iter_next
Unexecuted instantiation: snappy.c:rd_map_iter_next
Unexecuted instantiation: rdkafka_ssl.c:rd_map_iter_next
Unexecuted instantiation: rdkafka_plugin.c:rd_map_iter_next
Unexecuted instantiation: rdavl.c:rd_map_iter_next
Unexecuted instantiation: rdkafka_event.c:rd_map_iter_next
Unexecuted instantiation: rdkafka_lz4.c:rd_map_iter_next
Unexecuted instantiation: rdkafka_msgset_reader.c:rd_map_iter_next
Unexecuted instantiation: rdkafka_msgset_writer.c:rd_map_iter_next
Unexecuted instantiation: rdlog.c:rd_map_iter_next
189
190
191
/**
192
 * @brief Initialize a map that is expected to hold \p expected_cnt elements.
193
 *
194
 * @param expected_cnt Expected number of elements in the map,
195
 *                     this is used to select a suitable bucket count.
196
 *                     Passing a value of 0 will set the bucket count
197
 *                     to a reasonable default.
198
 * @param cmp Key comparator that must return 0 if the two keys match.
199
 * @param hash Key hashing function that is used to map a key to a bucket.
200
 *             It must return an integer hash >= 0 of the key.
201
 * @param destroy_key (Optional) When an element is deleted or overwritten
202
 *                    this function will be used to free the key memory.
203
 * @param destroy_value (Optional) When an element is deleted or overwritten
204
 *                      this function will be used to free the value memory.
205
 *
206
 * Destroy the map with rd_map_destroy()
207
 *
208
 * @remarks The map is not thread-safe.
209
 */
210
void rd_map_init(rd_map_t *rmap,
211
                 size_t expected_cnt,
212
                 int (*cmp)(const void *a, const void *b),
213
                 unsigned int (*hash)(const void *key),
214
                 void (*destroy_key)(void *key),
215
                 void (*destroy_value)(void *value));
216
217
218
/**
219
 * @brief Internal use
220
 */
221
struct rd_map_buckets rd_map_alloc_buckets(size_t expected_cnt);
222
223
224
/**
225
 * @brief Empty the map and free all elements.
226
 */
227
void rd_map_clear(rd_map_t *rmap);
228
229
230
/**
231
 * @brief Free all elements in the map and free all memory associated
232
 *        with the map, but not the rd_map_t itself.
233
 *
234
 * The map is unusable after this call but can be re-initialized using
235
 * rd_map_init().
236
 *
237
 * @sa rd_map_clear()
238
 */
239
void rd_map_destroy(rd_map_t *rmap);
240
241
242
/**
243
 * @brief String comparator for (const char *) keys.
244
 */
245
int rd_map_str_cmp(const void *a, const void *b);
246
247
248
/**
249
 * @brief String hash function (djb2) for (const char *) keys.
250
 */
251
unsigned int rd_map_str_hash(const void *a);
252
253
/**
254
 * @brief Bytes hash function (djb2).
255
 */
256
unsigned int rd_bytes_hash(unsigned char *bytes, size_t len);
257
258
259
/**
260
 * @name Typed hash maps.
261
 *
262
 * Typed hash maps provides a type-safe layer on top of the standard hash maps.
263
 */
264
265
/**
266
 * @brief Define a typed map type which can later be used with
267
 *        RD_MAP_INITIALIZER() and typed RD_MAP_*() API.
268
 */
269
#define RD_MAP_TYPE(KEY_TYPE, VALUE_TYPE)                                      \
270
        struct {                                                               \
271
                rd_map_t rmap;                                                 \
272
                KEY_TYPE key;                                                  \
273
                VALUE_TYPE value;                                              \
274
                const rd_map_elem_t *elem;                                     \
275
        }
276
277
/**
278
 * @brief Initialize a typed hash map. The left hand side variable must be
279
 *        a typed hash map defined by RD_MAP_TYPE().
280
 *
281
 * The typed hash map is a macro layer on top of the rd_map_t implementation
282
 * that provides type safety.
283
 * The methods are the same as the underlying implementation but in all caps
284
 * (to indicate their macro use), e.g., RD_MAP_SET() is the typed version
285
 * of rd_map_set().
286
 *
287
 * @param EXPECTED_CNT Expected number of elements in hash.
288
 * @param KEY_TYPE The type of the hash key.
289
 * @param VALUE_TYPE The type of the hash value.
290
 * @param CMP Comparator function for the key.
291
 * @param HASH Hash function for the key.
292
 * @param DESTROY_KEY Destructor for the key type.
293
 * @param DESTROY_VALUE Destructor for the value type.
294
 *
295
 * @sa rd_map_init()
296
 */
297
#define RD_MAP_INITIALIZER(EXPECTED_CNT, CMP, HASH, DESTROY_KEY,                \
298
                           DESTROY_VALUE)                                       \
299
0
        {                                                                       \
300
0
                .rmap = {                                                       \
301
0
                        .rmap_buckets     = rd_map_alloc_buckets(EXPECTED_CNT), \
302
0
                        .rmap_cmp         = CMP,                                \
303
0
                        .rmap_hash        = HASH,                               \
304
0
                        .rmap_destroy_key = DESTROY_KEY,                        \
305
0
                        .rmap_destroy_value = DESTROY_VALUE                     \
306
0
                }                                                               \
307
0
        }
308
309
310
/**
311
 * @brief Initialize a locally-defined typed hash map.
312
 *        This hash map can only be used in the current scope/function
313
 *        as its type is private to this initializement.
314
 *
315
 * @param RMAP Hash map variable name.
316
 *
317
 * For the other parameters, see RD_MAP_INITIALIZER().
318
 *
319
 * @sa RD_MAP_INITIALIZER()
320
 */
321
#define RD_MAP_LOCAL_INITIALIZER(RMAP, EXPECTED_CNT, KEY_TYPE, VALUE_TYPE,     \
322
                                 CMP, HASH, DESTROY_KEY, DESTROY_VALUE)        \
323
0
        struct {                                                               \
324
0
                rd_map_t rmap;                                                 \
325
0
                KEY_TYPE key;                                                  \
326
0
                VALUE_TYPE value;                                              \
327
0
                const rd_map_elem_t *elem;                                     \
328
0
        } RMAP = RD_MAP_INITIALIZER(EXPECTED_CNT, CMP, HASH, DESTROY_KEY,      \
329
0
                                    DESTROY_VALUE)
330
331
332
/**
333
 * @brief Initialize typed map \p RMAP.
334
 *
335
 * @sa rd_map_init()
336
 */
337
#define RD_MAP_INIT(RMAP, EXPECTED_CNT, CMP, HASH, DESTROY_KEY, DESTROY_VALUE) \
338
0
        rd_map_init(&(RMAP)->rmap, EXPECTED_CNT, CMP, HASH, DESTROY_KEY,       \
339
0
                    DESTROY_VALUE)
340
341
342
/**
343
 * @brief Allocate and initialize a typed map.
344
 */
345
346
347
/**
348
 * @brief Typed hash map: Set key/value in map.
349
 *
350
 * @sa rd_map_set()
351
 */
352
#define RD_MAP_SET(RMAP, KEY, VALUE)                                           \
353
0
        ((RMAP)->key = KEY, (RMAP)->value = VALUE,                             \
354
0
         rd_map_set(&(RMAP)->rmap, (void *)(RMAP)->key,                        \
355
0
                    (void *)(RMAP)->value))
356
357
/**
358
 * @brief Typed hash map: Get value for key.
359
 *
360
 * @sa rd_map_get()
361
 */
362
#define RD_MAP_GET(RMAP, KEY)                                                  \
363
0
        ((RMAP)->key   = (KEY),                                                \
364
0
         (RMAP)->value = rd_map_get(&(RMAP)->rmap, (RMAP)->key),               \
365
0
         (RMAP)->value)
366
367
368
369
/**
370
 * @brief Get value for key. If key does not exist in map a new
371
 *        entry is added using the DEFAULT_CODE.
372
 */
373
#define RD_MAP_GET_OR_SET(RMAP, KEY, DEFAULT_CODE)                             \
374
0
        (RD_MAP_GET(RMAP, KEY)                                                 \
375
0
             ? (RMAP)->value                                                   \
376
0
             : (RD_MAP_SET(RMAP, (RMAP)->key, DEFAULT_CODE), (RMAP)->value))
377
378
379
/**
380
 * @brief Typed hash map: Delete element by key.
381
 *
382
 * The destroy_key and destroy_value functions (if set) will be used
383
 * to free the key and value memory.
384
 *
385
 * @sa rd_map_delete()
386
 */
387
#define RD_MAP_DELETE(RMAP, KEY)                                               \
388
0
        ((RMAP)->key = (KEY), rd_map_delete(&(RMAP)->rmap, (RMAP)->key))
389
390
391
/**
392
 * @brief Copy all elements from \p SRC to \p DST.
393
 *        \p DST must be initialized and compatible with \p SRC.
394
 *
395
 * @param DST Destination map to copy to.
396
 * @param SRC Source map to copy from.
397
 * @param KEY_COPY Key copy callback. If NULL the \p DST key will just
398
 *                 reference the \p SRC key.
399
 * @param VALUE_COPY Value copy callback. If NULL the \p DST value will just
400
 *                   reference the \p SRC value.
401
 */
402
#define RD_MAP_COPY(DST, SRC, KEY_COPY, VALUE_COPY)                            \
403
0
        do {                                                                   \
404
0
                if ((DST) != (SRC)) /*implicit type-check*/                    \
405
0
                        rd_map_copy(&(DST)->rmap, &(SRC)->rmap, KEY_COPY,      \
406
0
                                    VALUE_COPY);                               \
407
0
        } while (0)
408
409
410
/**
411
 * @brief Empty the map and free all elements.
412
 *
413
 * @sa rd_map_clear()
414
 */
415
0
#define RD_MAP_CLEAR(RMAP) rd_map_clear(&(RMAP)->rmap)
416
417
418
/**
419
 * @brief Typed hash map: Destroy hash map.
420
 *
421
 * @sa rd_map_destroy()
422
 */
423
0
#define RD_MAP_DESTROY(RMAP) rd_map_destroy(&(RMAP)->rmap)
424
425
426
/**
427
 * @brief Typed hash map: Destroy and free the hash map.
428
 *
429
 * @sa rd_map_destroy()
430
 */
431
#define RD_MAP_DESTROY_AND_FREE(RMAP)                                          \
432
0
        do {                                                                   \
433
0
                rd_map_destroy(&(RMAP)->rmap);                                 \
434
0
                rd_free(RMAP);                                                 \
435
0
        } while (0)
436
437
438
/**
439
 * @brief Typed hash map: Iterate over all elements in the map.
440
 *
441
 * @warning The current or previous elements may be removed, but the next
442
 *          element after the current one MUST NOT be modified during the loop.
443
 *
444
 * @warning RD_MAP_FOREACH() only supports one simultaneous invocation,
445
 *          that is, special care must be taken not to call FOREACH() from
446
 *          within a FOREACH() or FOREACH_KEY() loop on the same map.
447
 *          This is due to how RMAP->elem is used as the iterator.
448
 *          This restriction is unfortunately not enforced at build or run time.
449
 *
450
 * @remark The \p RMAP may not be const.
451
 */
452
#define RD_MAP_FOREACH(K, V, RMAP)                                             \
453
0
        for (rd_map_iter_begin(&(RMAP)->rmap, &(RMAP)->elem), (K) = NULL,      \
454
0
                                                              (V) = NULL;      \
455
0
             rd_map_iter(&(RMAP)->elem) &&                                     \
456
0
             ((RMAP)->key = (void *)(RMAP)->elem->key, (K) = (RMAP)->key,      \
457
0
             (RMAP)->value = (void *)(RMAP)->elem->value, (V) = (RMAP)->value, \
458
0
             rd_map_iter_next(&(RMAP)->elem), rd_true);)
459
460
461
/**
462
 * @brief Typed hash map: Iterate over all keys in the map.
463
 *
464
 * @warning The current or previous elements may be removed, but the next
465
 *          element after the current one MUST NOT be modified during the loop.
466
 *
467
 * @warning RD_MAP_FOREACH_KEY() only supports one simultaneous invocation,
468
 *          that is, special care must be taken not to call FOREACH_KEY() from
469
 *          within a FOREACH() or FOREACH_KEY() loop on the same map.
470
 *          This is due to how RMAP->elem is used as the iterator.
471
 *          This restriction is unfortunately not enforced at build or run time.
472
 *
473
 * @remark The \p RMAP may not be const.
474
 */
475
#define RD_MAP_FOREACH_KEY(K, RMAP)                                            \
476
0
        for (rd_map_iter_begin(&(RMAP)->rmap, &(RMAP)->elem), (K) = NULL;      \
477
0
             rd_map_iter(&(RMAP)->elem) &&                                     \
478
0
             ((RMAP)->key = (void *)(RMAP)->elem->key, (K) = (RMAP)->key,      \
479
0
             rd_map_iter_next(&(RMAP)->elem), rd_true);)
480
481
482
/**
483
 * @returns the number of elements in the map.
484
 */
485
0
#define RD_MAP_CNT(RMAP) rd_map_cnt(&(RMAP)->rmap)
486
487
/**
488
 * @returns true if map is empty, else false.
489
 */
490
0
#define RD_MAP_IS_EMPTY(RMAP) rd_map_is_empty(&(RMAP)->rmap)
491
492
#endif /* _RDMAP_H_ */