sc/map/sc_map.h

226 lines
11 KiB
C
Raw Normal View History

2020-11-11 01:19:49 +03:00
/*
* BSD-3-Clause
2020-11-11 01:19:49 +03:00
*
* Copyright 2021 Ozan Tezcan
* All rights reserved.
2020-11-11 01:19:49 +03:00
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
2020-11-11 01:19:49 +03:00
*
* 1. Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
* 3. Neither the name of the copyright holder nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
2020-11-11 01:19:49 +03:00
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY,
* OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT
* OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
2020-11-11 01:19:49 +03:00
*/
#ifndef SC_MAP_H
#define SC_MAP_H
#include <memory.h>
#include <stdbool.h>
#include <stddef.h>
#include <stdint.h>
#include <stdlib.h>
2021-04-13 22:36:50 +03:00
#define SC_MAP_VERSION "2.0.0"
2021-02-14 16:19:26 +03:00
#ifdef SC_HAVE_CONFIG_H
#include "config.h"
#else
#define sc_map_calloc calloc
#define sc_map_free free
#endif
#define sc_map_dec_strkey(name, K, V) \
struct sc_map_item_##name { \
K key; \
V value; \
uint32_t hash; \
}; \
2020-11-11 01:19:49 +03:00
\
sc_map_of(name, K, V)
2020-11-11 01:19:49 +03:00
#define sc_map_dec_scalar(name, K, V) \
struct sc_map_item_##name { \
K key; \
V value; \
}; \
2020-11-11 01:19:49 +03:00
\
sc_map_of(name, K, V)
2020-11-11 01:19:49 +03:00
#define sc_map_of(name, K, V) \
struct sc_map_##name { \
struct sc_map_item_##name *mem; \
uint32_t cap; \
uint32_t size; \
uint32_t load_fac; \
uint32_t remap; \
bool used; \
2021-05-01 02:19:39 +03:00
bool oom; \
bool found; \
}; \
2020-11-11 01:19:49 +03:00
\
/** \
* Create map \
* \
* @param map map \
* @param cap initial capacity, zero is accepted \
* @param load_factor must be >25 and <95. Pass 0 for default value. \
* @return 'true' on success, \
* 'false' on out of memory or if 'load_factor' value is \
2022-02-04 22:43:15 +03:00
* invalid. \
*/ \
bool sc_map_init_##name(struct sc_map_##name *map, uint32_t cap, \
uint32_t load_factor); \
2021-02-03 08:09:50 +03:00
\
/** \
* Destroy map. \
* \
* @param map map \
*/ \
void sc_map_term_##name(struct sc_map_##name *map); \
2021-02-03 08:09:50 +03:00
\
/** \
* Get map element count \
* \
* @param map map \
* @return element count \
*/ \
uint32_t sc_map_size_##name(struct sc_map_##name *map); \
2021-02-03 08:09:50 +03:00
\
/** \
* Clear map \
* \
* @param map map \
*/ \
void sc_map_clear_##name(struct sc_map_##name *map); \
2021-02-03 08:09:50 +03:00
\
/** \
* Put element to the map \
* \
2021-05-01 02:19:39 +03:00
* struct sc_map_str map; \
* sc_map_put_str(&map, "key", "value"); \
* \
* @param map map \
* @param K key \
* @param V value \
2021-05-01 02:19:39 +03:00
* @return previous value if exists \
2022-02-04 22:43:15 +03:00
* call sc_map_found() to see if returned value if valid. \
*/ \
2021-05-01 02:19:39 +03:00
V sc_map_put_##name(struct sc_map_##name *map, K key, V val); \
2021-02-03 08:09:50 +03:00
\
/** \
* Get element \
* \
* @param map map \
2021-05-01 02:19:39 +03:00
* @param K key \ \
* @return current value if exists. \
* call sc_map_found() to see if returned value if valid. \
*/ \
/** NOLINTNEXTLINE */ \
2021-05-01 02:19:39 +03:00
V sc_map_get_##name(struct sc_map_##name *map, K key); \
2021-02-03 08:09:50 +03:00
\
/** \
* Delete element \
* \
* @param map map \
2021-05-01 02:19:39 +03:00
* @param K key \
* @return current value if exists. \
* call sc_map_found() to see if returned value if valid. \
*/ \
/** NOLINTNEXTLINE */ \
2021-05-01 02:19:39 +03:00
V sc_map_del_##name(struct sc_map_##name *map, K key);
/**
* @param map map
* @return - if put operation overrides a value, returns true
2022-02-04 22:43:15 +03:00
* - if get operation finds the key, returns true
2021-05-01 02:19:39 +03:00
* - if del operation deletes a key, returns true
*/
#define sc_map_found(map) ((map)->found)
/**
* @param map map
* @return true if put operation failed with out of memory
*/
#define sc_map_oom(map) ((map)->oom)
2020-11-11 01:19:49 +03:00
2021-02-03 08:09:50 +03:00
/**
* Foreach loop
*
2021-05-01 02:19:39 +03:00
* char *key, *value;
2021-02-03 08:09:50 +03:00
* struct sc_map_str map;
*
* sc_map_foreach(&map, key, value) {
* printf("key = %s, value = %s \n");
* }
*/
2020-11-11 01:19:49 +03:00
#define sc_map_foreach(map, K, V) \
for (int64_t __i = -1, __b = 0; __i < (map)->cap; __i++) \
for ((V) = (map)->mem[__i].value, (K) = (map)->mem[__i].key, \
__b = 1; \
__b && ((__i == -1 && (map)->used) || (K) != 0); __b = 0)
2020-11-11 01:19:49 +03:00
2021-02-03 08:09:50 +03:00
/**
* Foreach loop for keys
*
2021-05-01 02:19:39 +03:00
* char *key;
2021-02-03 08:09:50 +03:00
* struct sc_map_str map;
*
* sc_map_foreach_key(&map, key) {
* printf("key = %s \n");
* }
*/
2020-11-11 01:19:49 +03:00
#define sc_map_foreach_key(map, K) \
for (int64_t __i = -1, __b = 0; __i < (map)->cap; __i++) \
for ((K) = (map)->mem[__i].key, __b = 1; \
__b && ((__i == -1 && (map)->used) || (K) != 0); __b = 0)
2020-11-11 01:19:49 +03:00
2021-02-03 08:09:50 +03:00
/**
* Foreach loop for values
*
2021-05-01 02:19:39 +03:00
* char *value;
2021-02-03 08:09:50 +03:00
* struct sc_map_str map;
*
* sc_map_foreach_value(&map, value) {
* printf("value = %s \n");
* }
*/
2020-11-11 01:19:49 +03:00
#define sc_map_foreach_value(map, V) \
for (int64_t __i = -1, __b = 0; __i < (map)->cap; __i++) \
for ((V) = (map)->mem[__i].value, __b = 1; \
__b && \
((__i == -1 && (map)->used) || (map)->mem[__i].key != 0); \
__b = 0)
2020-11-11 01:19:49 +03:00
// clang-format off
2020-12-27 17:41:44 +03:00
// name key type value type
sc_map_dec_scalar(32, uint32_t, uint32_t)
sc_map_dec_scalar(64, uint64_t, uint64_t)
sc_map_dec_scalar(64v, uint64_t, void *)
sc_map_dec_scalar(64s, uint64_t, const char *)
sc_map_dec_strkey(str, const char *, const char *)
sc_map_dec_strkey(sv, const char *, void*)
sc_map_dec_strkey(s64, const char *, uint64_t)
2020-11-11 01:19:49 +03:00
// clang-format on
2020-11-11 01:19:49 +03:00
#endif