2024-06-16 00:50:00 +08:00

122 lines
2.9 KiB
C

#if !defined(SMALLMAP_T__HEADER) && !defined(SMALLMAP_T__SOURCE)
#include "pocketpy/common/vector.h"
/* Input */
#define K int
#define V float
#define TAG int_float
#endif
/* Optional Input */
#ifndef less
#define less(a, b) ((a.key) < (b))
#endif
#ifndef equal
#define equal(a, b) ((a) == (b))
#endif
/* Temprary macros */
#define CONCAT(A, B) CONCAT_(A, B)
#define CONCAT_(A, B) A##B
#define KV CONCAT(c11_smallmap_entry_, TAG)
#define SMALLMAP CONCAT(c11_smallmap_, TAG)
#define SMALLMAP_METHOD(name) CONCAT(SMALLMAP, CONCAT(__, name))
typedef struct {
K key;
V value;
} KV;
typedef c11_vector SMALLMAP;
void SMALLMAP_METHOD(ctor)(SMALLMAP* self);
void SMALLMAP_METHOD(dtor)(SMALLMAP* self);
void SMALLMAP_METHOD(set)(SMALLMAP* self, K key, V value);
V* SMALLMAP_METHOD(try_get)(const SMALLMAP* self, K key);
V SMALLMAP_METHOD(get)(const SMALLMAP* self, K key, V default_value);
bool SMALLMAP_METHOD(contains)(const SMALLMAP* self, K key);
bool SMALLMAP_METHOD(del)(SMALLMAP* self, K key);
void SMALLMAP_METHOD(clear)(SMALLMAP* self);
#ifdef SMALLMAP_T__SOURCE
/* Implementation */
void SMALLMAP_METHOD(ctor)(SMALLMAP* self) {
c11_vector__ctor(self, sizeof(KV));
c11_vector__reserve(self, 4);
}
void SMALLMAP_METHOD(dtor)(SMALLMAP* self) {
c11_vector__dtor(self);
}
void SMALLMAP_METHOD(set)(SMALLMAP* self, K key, V value) {
int index;
c11__lower_bound(KV, self->data, self->count, key, less, &index);
KV* it = c11__at(KV, self, index);
if(index != self->count && equal(it->key, key)) {
it->value = value;
} else {
KV kv = {key, value};
c11_vector__insert(KV, self, index, kv);
}
}
V* SMALLMAP_METHOD(try_get)(const SMALLMAP* self, K key) {
// use `bsearch` which is faster than `lower_bound`
int low = 0;
int high = self->count - 1;
KV* a = self->data;
while(low <= high){
int mid = (low + high) / 2;
if(equal(a[mid].key, key)){
return &a[mid].value;
} else if(less(a[mid], key)){
low = mid + 1;
} else {
high = mid - 1;
}
}
return NULL;
}
V SMALLMAP_METHOD(get)(const SMALLMAP* self, K key, V default_value) {
V* p = SMALLMAP_METHOD(try_get)(self, key);
return p ? *p : default_value;
}
bool SMALLMAP_METHOD(contains)(const SMALLMAP* self, K key) {
return SMALLMAP_METHOD(try_get)(self, key) != NULL;
}
bool SMALLMAP_METHOD(del)(SMALLMAP* self, K key) {
int index;
c11__lower_bound(KV, self->data, self->count, key, less, &index);
KV* it = c11__at(KV, self, index);
if(index != self->count && equal(it->key, key)) {
c11_vector__erase(KV, self, index);
return true;
}
return false;
}
void SMALLMAP_METHOD(clear)(SMALLMAP* self) {
c11_vector__clear(self);
}
#endif
#undef KV
#undef SMALLMAP
#undef SMALLMAP_METHOD
#undef CONCAT
#undef CONCAT_
#undef K
#undef V
#undef TAG
#undef less
#undef equal