some updates and tests for the equals function
This commit is contained in:
@@ -239,16 +239,16 @@ typedef unsigned int (*key_hash_func_t)(const void *key);
|
||||
typedef bool (*key_equals_func_t)(const void *key1, const void *key2);
|
||||
|
||||
typedef struct map_header {
|
||||
unsigned int capacity;
|
||||
unsigned int item_size;
|
||||
unsigned int key_size;
|
||||
unsigned int mapping_capacity;
|
||||
unsigned int n_items;
|
||||
unsigned int key_offset;
|
||||
uint32_t capacity;
|
||||
uint32_t item_size;
|
||||
uint32_t key_size;
|
||||
uint32_t mapping_capacity;
|
||||
uint32_t n_items;
|
||||
uint32_t key_offset;
|
||||
allocator_t allocator;
|
||||
key_hash_func_t hash;
|
||||
key_equals_func_t equals;
|
||||
int *mapping_arr;
|
||||
int32_t *mapping_arr;
|
||||
union {
|
||||
uint8_t bytes[1];
|
||||
any_align_t _[1];
|
||||
@@ -317,14 +317,19 @@ typedef struct index_pair {
|
||||
* index with a tombstone if they are going to write a new value for that key.
|
||||
*/
|
||||
index_pair_t map_pair_hash(void *this, const uint8_t *pair);
|
||||
bool map_key_equals(map_header_t *header, const uint8_t *key1_bytes, const uint8_t *key2_bytes);
|
||||
unsigned int map_place(void *this, index_pair_t idx_pair);
|
||||
|
||||
// Exists to take a hash of a key and modulo it so it fits within the maps
|
||||
// capacity.
|
||||
uint32_t map_mod_index(const map_header_t *header, uint32_t i);
|
||||
|
||||
// TODO: NOT DONE!!! FIRST try to get the existing in
|
||||
#define set_add(THIS, VALUE) do { \
|
||||
map_assure_growable_by_1((void**)THIS, __FILE__, __LINE__); \
|
||||
unsigned int len = map_len(*(THIS)); \
|
||||
(*(THIS))[len] = VALUE; \
|
||||
index_pair_t idx_pair = map_pair_hash((*(THIS)), &(*(THIS))[len]); \
|
||||
index_pair_t idx_pair = map_pair_hash((*(THIS)), (const uint8_t*) (&(*(THIS))[len])); \
|
||||
(*(THIS))[map_place((*(THIS)), idx_pair)] = VALUE; \
|
||||
} while (0)
|
||||
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
CC := "zig cc"
|
||||
CFLAGS := "-pedantic -Wall -Wextra -Wno-override-init -O0 -g -fno-omit-frame-pointer -fno-inline"
|
||||
CFLAGS := "-pedantic -Wall -Wextra -Wno-override-init -O0 -g3 -fno-omit-frame-pointer -fno-inline -fsanitize=address,undefined -fno-sanitize-recover=all"
|
||||
LDFLAGS := if os() == "macos" {
|
||||
"$(pkg-config --libs --cflags criterion)"
|
||||
} else {
|
||||
@@ -12,9 +12,11 @@ TESTBIN := TMP/"all_tests"
|
||||
|
||||
set shell := ["bash", "-cu"]
|
||||
|
||||
RUNNER := if os() == "linux" { "valgrind" } else { "" }
|
||||
|
||||
[default]
|
||||
test: build
|
||||
{{TESTBIN}}
|
||||
{{RUNNER}} {{TESTBIN}}
|
||||
|
||||
test_memcheck: build
|
||||
valgrind --leak-check=full \
|
||||
@@ -28,6 +30,8 @@ build:
|
||||
|
||||
DEPENDENCY_HEADERS := if os() == "macos" {
|
||||
"$(pkg-config --cflags-only-I criterion | sed 's/-I//g')"
|
||||
} else if os() == "linux" {
|
||||
"/usr/include/"
|
||||
} else {
|
||||
"TODO"
|
||||
}
|
||||
|
||||
@@ -17,12 +17,9 @@
|
||||
#define DEFAULT ESC "0m"
|
||||
#define COLORED(COLOR, TEXT) COLOR TEXT DEFAULT
|
||||
|
||||
static int __map_mod(int a, int b) {
|
||||
int r = a % b;
|
||||
if (r < 0) r += (b > 0 ? b : -b);
|
||||
return r;
|
||||
uint32_t map_mod_index(const map_header_t *header, uint32_t i) {
|
||||
return i % header->mapping_capacity;
|
||||
}
|
||||
#define mod(a, b) __map_mod(a, b)
|
||||
|
||||
void map_print_mapping_state(void *this, FILE *file) {
|
||||
map_header_t *header = PTR_FROM_FIELD_PTR(map_header_t, bytes, this);
|
||||
@@ -104,14 +101,10 @@ static const uint8_t *__cig_key_ptr_from_pair_ptr(const map_header_t *this, cons
|
||||
return (const uint8_t *) (&pair[this->key_offset]);
|
||||
}
|
||||
|
||||
// TODO: just make these internal probably
|
||||
bool map_key_equals(void *this, const void *key1, const void *key2) {
|
||||
map_header_t *header = PTR_FROM_FIELD_PTR(map_header_t, bytes, this);
|
||||
bool map_key_equals(map_header_t *header, const uint8_t *key1_bytes, const uint8_t *key2_bytes) {
|
||||
if (header->equals != NULL) {
|
||||
return header->equals(key1, key2);
|
||||
return header->equals(key1_bytes, key2_bytes);
|
||||
}
|
||||
const char *key1_bytes = key1;
|
||||
const char *key2_bytes = key2;
|
||||
for ( unsigned int i = 0; i < header->key_size; i++ ) {
|
||||
if (key1_bytes[i] != key2_bytes[i]) {
|
||||
return false;
|
||||
@@ -123,9 +116,9 @@ bool map_key_equals(void *this, const void *key1, const void *key2) {
|
||||
unsigned int map_place(void *this, index_pair_t idx) {
|
||||
map_header_t *header = PTR_FROM_FIELD_PTR(map_header_t, bytes, this);
|
||||
if (idx.has_old) {
|
||||
header->mapping_arr[idx.new_i_into_mapping] = header->mapping_arr[idx.old_index];
|
||||
header->mapping_arr[idx.old_index] = FLAG_TOMBSTONE;
|
||||
for ( long i = idx.old_index; i != idx.new_i_into_mapping; mod(i-1, header->mapping_capacity) ) {
|
||||
header->mapping_arr[idx.new_i_into_mapping] = header->mapping_arr[idx.old_i_into_mapping];
|
||||
header->mapping_arr[idx.old_i_into_mapping] = FLAG_TOMBSTONE;
|
||||
for ( long i = idx.old_i_into_mapping; i != idx.new_i_into_mapping; map_mod_index(header, i-1) ) {
|
||||
if (header->mapping_arr[i] == FLAG_TOMBSTONE) {
|
||||
header->mapping_arr[i] = FLAG_FREE;
|
||||
} else {
|
||||
@@ -182,8 +175,7 @@ index_pair_t map_pair_hash(void *this, const uint8_t *pair) {
|
||||
.new_i_into_mapping=i_into_mapping,
|
||||
};
|
||||
}
|
||||
map_key_equals(this, const void *key1, const void *key2);
|
||||
TODO this
|
||||
// TODO THIS!!
|
||||
}
|
||||
|
||||
// TODO: search all occurances of **this. The whole point is to reassign to the
|
||||
|
||||
@@ -0,0 +1,80 @@
|
||||
#include <criterion/criterion.h>
|
||||
#include "cig.h"
|
||||
|
||||
Test(map_key_equals, ints) {
|
||||
{ // should be equal
|
||||
int key1 = 20;
|
||||
int key2 = 20;
|
||||
map_header_t header = (map_header_t) { 0 };
|
||||
header.key_size = sizeof(key1);
|
||||
cr_assert(
|
||||
map_key_equals(
|
||||
&header,
|
||||
(const uint8_t*)&key1,
|
||||
(const uint8_t*)&key2
|
||||
),
|
||||
"key %d is not equal to key %d",
|
||||
key1,
|
||||
key2
|
||||
);
|
||||
}
|
||||
{ // should not be equal
|
||||
int key1 = 20;
|
||||
int key2 = 21;
|
||||
map_header_t header = (map_header_t) { 0 };
|
||||
header.key_size = sizeof(key1);
|
||||
cr_assert(
|
||||
!map_key_equals(
|
||||
&header,
|
||||
(const uint8_t*)&key1,
|
||||
(const uint8_t*)&key2
|
||||
),
|
||||
"key %d is equal to key %d",
|
||||
key1,
|
||||
key2
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
static bool inverse_int_equals(const void *key1, const void *key2) {
|
||||
int key1_i = *((int*)key1);
|
||||
int key2_i = *((int*)key2);
|
||||
return key1_i != key2_i;
|
||||
}
|
||||
|
||||
Test(map_key_equals, custom) {
|
||||
{ // should be equal
|
||||
int key1 = 20;
|
||||
int key2 = 21;
|
||||
map_header_t header = (map_header_t) { 0 };
|
||||
header.key_size = sizeof(key1);
|
||||
header.equals = inverse_int_equals;
|
||||
cr_assert(
|
||||
map_key_equals(
|
||||
&header,
|
||||
(const uint8_t*)&key1,
|
||||
(const uint8_t*)&key2
|
||||
),
|
||||
"key %d is equal to key %d",
|
||||
key1,
|
||||
key2
|
||||
);
|
||||
}
|
||||
{ // should not be equal
|
||||
int key1 = 20;
|
||||
int key2 = 20;
|
||||
map_header_t header = (map_header_t) { 0 };
|
||||
header.key_size = sizeof(key1);
|
||||
header.equals = inverse_int_equals;
|
||||
cr_assert(
|
||||
!map_key_equals(
|
||||
&header,
|
||||
(const uint8_t*)&key1,
|
||||
(const uint8_t*)&key2
|
||||
),
|
||||
"key %d is not equal to key %d",
|
||||
key1,
|
||||
key2
|
||||
);
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user