Compare commits
1 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| b1b99cb224 |
248
ev_map.h
Normal file
248
ev_map.h
Normal file
@@ -0,0 +1,248 @@
|
||||
/*!
|
||||
* \file ev_map.h
|
||||
*/
|
||||
#ifndef EV_MAP_HEADER
|
||||
#define EV_MAP_HEADER
|
||||
#include "ev_internal.h"
|
||||
#include "ev_types.h"
|
||||
#include "ev_numeric.h"
|
||||
#include "ev_vec.h"
|
||||
|
||||
#define EV_MAP_MAGIC (0x65765F6D61705F74)
|
||||
|
||||
#if defined(EV_MAP_SHARED)
|
||||
# if defined (EV_MAP_IMPL)
|
||||
# define EV_MAP_API EV_EXPORT
|
||||
# else
|
||||
# define EV_MAP_API EV_IMPORT
|
||||
# endif
|
||||
#else
|
||||
# define EV_MAP_API
|
||||
#endif
|
||||
|
||||
#ifndef EV_MAP_INIT_CAP
|
||||
/*!
|
||||
* \brief Initial capacity that is first reserved when a map is initialized
|
||||
*/
|
||||
#define EV_MAP_INIT_CAP 32
|
||||
#endif
|
||||
|
||||
#ifndef EV_MAP_GROWTH_RATE
|
||||
/*!
|
||||
* \brief Rate at which a map grows whenever a resize is needed
|
||||
*/
|
||||
#define EV_MAP_GROWTH_RATE 3 / 2
|
||||
#endif
|
||||
|
||||
typedef struct {
|
||||
u64 _magic;
|
||||
u64 length;
|
||||
u64 capacity;
|
||||
u64 seed;
|
||||
EvTypeData keyTypeData;
|
||||
EvTypeData valTypeData;
|
||||
ev_vec_t keys;
|
||||
ev_vec_t vals;
|
||||
} ev_map_t;
|
||||
|
||||
typedef enum {
|
||||
EV_MAP_ERR_NONE = 0,
|
||||
EV_MAP_ERR_OOM = 1
|
||||
} ev_map_error_t;
|
||||
TYPEDATA_GEN(ev_map_error_t, DEFAULT(EV_MAP_ERR_NONE));
|
||||
|
||||
#if defined(EV_MAP_SHORTNAMES)
|
||||
# define map_t ev_map_t
|
||||
|
||||
# define map_error_t ev_map_error_t
|
||||
|
||||
# define map(K,V) ev_map(K,V)
|
||||
|
||||
# define map_init ev_map_init
|
||||
/* # define vec_iter_begin ev_vec_iter_begin */
|
||||
/* # define vec_iter_end ev_vec_iter_end */
|
||||
/* # define vec_iter_next ev_vec_iter_next */
|
||||
/* # define vec_fini ev_vec_fini */
|
||||
/* # define vec_push ev_vec_push */
|
||||
/* # define vec_append ev_vec_append */
|
||||
/* # define vec_last ev_vec_last */
|
||||
/* # define vec_len ev_vec_len */
|
||||
/* # define vec_capacity ev_vec_capacity */
|
||||
/* # define vec_clear ev_vec_clear */
|
||||
/* # define vec_setlen ev_vec_setlen */
|
||||
/* # define vec_setcapacity ev_vec_setcapacity */
|
||||
/* # define vec_grow ev_vec_grow */
|
||||
#endif
|
||||
|
||||
/*!
|
||||
* \brief For the sake of readability
|
||||
* \details Sample usage:
|
||||
* ```
|
||||
* ev_map(int,int) v = ev_map_init(int,int);
|
||||
* ```
|
||||
*/
|
||||
#define ev_map(K,V) struct { \
|
||||
u64 _magic; \
|
||||
u64 length; \
|
||||
u64 capacity; \
|
||||
u64 seed; \
|
||||
EvTypeData keyTypeData; \
|
||||
EvTypeData valTypeData; \
|
||||
ev_vec(K) keys; \
|
||||
ev_vec(V) vals; \
|
||||
}
|
||||
|
||||
/*!
|
||||
* \param typeData The EvTypeData for the element that the vector will contain
|
||||
*
|
||||
* \returns A vector object
|
||||
*/
|
||||
EV_MAP_API ev_map_t*
|
||||
ev_map_init_impl(
|
||||
EvTypeData keyTypeData,
|
||||
EvTypeData valTypeData);
|
||||
|
||||
/*!
|
||||
* \brief Syntactic sugar for `ev_map_init_impl()`
|
||||
* \details Sample usage:
|
||||
* ```
|
||||
* ev_map_init(i32,i64); // ev_map_init_impl(TypeData(i32),TypeData(i64));
|
||||
* ```
|
||||
*/
|
||||
#define ev_map_init(K,V) (void*)ev_map_init_impl(TypeData(K), TypeData(V))
|
||||
|
||||
/*!
|
||||
* \brief Syntactic sugar for `ev_vec_push_impl()` that allows multiple pushed in the same statement.
|
||||
* \details Sample usage:
|
||||
* ```
|
||||
* ev_vec_t v;
|
||||
* i32 x = 1;
|
||||
* i32 y = 2;
|
||||
* ev_vec_push(&v, &x); // ev_vec_push_impl(&v, &x);
|
||||
* ev_vec_push(&v, &x, &y); // ev_vec_push_impl(&v, &x); ev_vec_push_impl(&v, &y);
|
||||
* ```
|
||||
*
|
||||
* *Note* This is possibly replaceable with a variadic function.
|
||||
*/
|
||||
#define ev_map_add(m, ...) \
|
||||
EV_FOREACH_UDATA(__ev_map_internal_add, m, __VA_ARGS__);
|
||||
#define __ev_map_internal_add(m, entry) ev_map_add_impl((ev_map_t*)m, EV_HEAD entry, EV_TAIL entry);
|
||||
|
||||
|
||||
/*!
|
||||
* \brief A function that destroys a vector object. If the element type has a
|
||||
* destructor function, then this function is called on every element before
|
||||
* all reserved memory is freed.
|
||||
*
|
||||
* *Note*: For stack-allocated vectors (`svec`), destructors are called for
|
||||
* elements but no memory is freed.
|
||||
*
|
||||
* \param v A pointer to the vector that is being destroyed
|
||||
*/
|
||||
EV_MAP_API void
|
||||
ev_map_fini(
|
||||
ev_map_t* m);
|
||||
|
||||
EV_MAP_API void
|
||||
ev_map_add_impl(
|
||||
ev_map_t* m,
|
||||
void* key,
|
||||
void* val
|
||||
);
|
||||
|
||||
/*!
|
||||
* \brief Calls the free operation (if exists) on every entry, then sets
|
||||
* the length to 0.
|
||||
*
|
||||
* \param v A pointer to the map object
|
||||
*
|
||||
* \returns 0 on success
|
||||
*/
|
||||
EV_MAP_API u32
|
||||
ev_map_clear(
|
||||
ev_map_t* m);
|
||||
|
||||
TYPEDATA_GEN(
|
||||
ev_map_t,
|
||||
INVALID(
|
||||
._magic = ~0ULL
|
||||
),
|
||||
);
|
||||
|
||||
#define EV_MAP_IMPLEMENTATION
|
||||
|
||||
#ifdef EV_MAP_IMPLEMENTATION
|
||||
#undef EV_MAP_IMPLEMENTATION
|
||||
|
||||
#ifdef EV_MAP_API_CHECK
|
||||
#define EV_VEC_CHECK(x) do { x; } while (0)
|
||||
#else
|
||||
#define EV_MAP_CHECK(x)
|
||||
#endif
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
ev_map_t*
|
||||
ev_map_init_impl(
|
||||
EvTypeData keyTypeData,
|
||||
EvTypeData valTypeData)
|
||||
{
|
||||
ev_map_t* m = malloc(sizeof(ev_map_t));
|
||||
if(!m) return &EV_INVALID(ev_map_t);
|
||||
|
||||
m->_magic = EV_MAP_MAGIC;
|
||||
m->keyTypeData = keyTypeData;
|
||||
m->valTypeData = valTypeData;
|
||||
m->keys = ev_vec_init_impl(keyTypeData, EV_DEFAULT(ev_vec_overrides_t));
|
||||
m->vals = ev_vec_init_impl(valTypeData, EV_DEFAULT(ev_vec_overrides_t));
|
||||
|
||||
m->length = 0;
|
||||
|
||||
assert(ev_vec_capacity(&m->keys) == ev_vec_capacity(&m->vals));
|
||||
|
||||
m->capacity = ev_vec_capacity(&m->keys);
|
||||
|
||||
return m;
|
||||
}
|
||||
|
||||
void
|
||||
ev_map_fini(
|
||||
ev_map_t* m)
|
||||
{
|
||||
ev_vec_fini(&m->keys);
|
||||
ev_vec_fini(&m->vals);
|
||||
free(m);
|
||||
}
|
||||
|
||||
u64
|
||||
_ev_map_hash(
|
||||
ev_map_t* m,
|
||||
void* key)
|
||||
{
|
||||
u64 clipMask = 0xFFFFFFFFFFFF;
|
||||
if(m->keyTypeData.hash_fn != NULL)
|
||||
return m->keyTypeData.hash_fn(key, m->seed) & clipMask;
|
||||
return ev_hash_murmur3(key, m->keyTypeData.size, m->seed) & clipMask;
|
||||
}
|
||||
|
||||
void
|
||||
ev_map_add_impl(
|
||||
ev_map_t* m,
|
||||
void* key,
|
||||
void* val)
|
||||
{
|
||||
u64 hash = _ev_map_hash(m, key);
|
||||
}
|
||||
|
||||
u32
|
||||
ev_map_clear(
|
||||
ev_map_t* m)
|
||||
{
|
||||
m->length = 0;
|
||||
return ev_vec_clear(m->keys) | ev_vec_clear(m->vals);
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
#endif
|
||||
22
map_test.c
Normal file
22
map_test.c
Normal file
@@ -0,0 +1,22 @@
|
||||
#include <stdio.h>
|
||||
|
||||
#define EV_MAP_IMPLEMENTATION
|
||||
#include "ev_map.h"
|
||||
|
||||
int main()
|
||||
{
|
||||
int x = 10;
|
||||
int y = 100;
|
||||
int x2 = 300;
|
||||
int y2 = 123;
|
||||
|
||||
ev_map(i32, i32)* m = ev_map_init(i32, i32);
|
||||
ev_map_add(m, (&x, &y), (&x2, &y2));
|
||||
|
||||
i32 out;
|
||||
ev_map_get(m, &x, &out);
|
||||
|
||||
ev_map_fini(m);
|
||||
|
||||
return 0;
|
||||
}
|
||||
Reference in New Issue
Block a user