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 bool (*key_equals_func_t)(const void *key1, const void *key2);
|
||||||
|
|
||||||
typedef struct map_header {
|
typedef struct map_header {
|
||||||
unsigned int capacity;
|
uint32_t capacity;
|
||||||
unsigned int item_size;
|
uint32_t item_size;
|
||||||
unsigned int key_size;
|
uint32_t key_size;
|
||||||
unsigned int mapping_capacity;
|
uint32_t mapping_capacity;
|
||||||
unsigned int n_items;
|
uint32_t n_items;
|
||||||
unsigned int key_offset;
|
uint32_t key_offset;
|
||||||
allocator_t allocator;
|
allocator_t allocator;
|
||||||
key_hash_func_t hash;
|
key_hash_func_t hash;
|
||||||
key_equals_func_t equals;
|
key_equals_func_t equals;
|
||||||
int *mapping_arr;
|
int32_t *mapping_arr;
|
||||||
union {
|
union {
|
||||||
uint8_t bytes[1];
|
uint8_t bytes[1];
|
||||||
any_align_t _[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 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);
|
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);
|
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
|
// TODO: NOT DONE!!! FIRST try to get the existing in
|
||||||
#define set_add(THIS, VALUE) do { \
|
#define set_add(THIS, VALUE) do { \
|
||||||
map_assure_growable_by_1((void**)THIS, __FILE__, __LINE__); \
|
map_assure_growable_by_1((void**)THIS, __FILE__, __LINE__); \
|
||||||
unsigned int len = map_len(*(THIS)); \
|
unsigned int len = map_len(*(THIS)); \
|
||||||
(*(THIS))[len] = VALUE; \
|
(*(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; \
|
(*(THIS))[map_place((*(THIS)), idx_pair)] = VALUE; \
|
||||||
} while (0)
|
} while (0)
|
||||||
|
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
CC := "zig cc"
|
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" {
|
LDFLAGS := if os() == "macos" {
|
||||||
"$(pkg-config --libs --cflags criterion)"
|
"$(pkg-config --libs --cflags criterion)"
|
||||||
} else {
|
} else {
|
||||||
@@ -12,9 +12,11 @@ TESTBIN := TMP/"all_tests"
|
|||||||
|
|
||||||
set shell := ["bash", "-cu"]
|
set shell := ["bash", "-cu"]
|
||||||
|
|
||||||
|
RUNNER := if os() == "linux" { "valgrind" } else { "" }
|
||||||
|
|
||||||
[default]
|
[default]
|
||||||
test: build
|
test: build
|
||||||
{{TESTBIN}}
|
{{RUNNER}} {{TESTBIN}}
|
||||||
|
|
||||||
test_memcheck: build
|
test_memcheck: build
|
||||||
valgrind --leak-check=full \
|
valgrind --leak-check=full \
|
||||||
@@ -28,6 +30,8 @@ build:
|
|||||||
|
|
||||||
DEPENDENCY_HEADERS := if os() == "macos" {
|
DEPENDENCY_HEADERS := if os() == "macos" {
|
||||||
"$(pkg-config --cflags-only-I criterion | sed 's/-I//g')"
|
"$(pkg-config --cflags-only-I criterion | sed 's/-I//g')"
|
||||||
|
} else if os() == "linux" {
|
||||||
|
"/usr/include/"
|
||||||
} else {
|
} else {
|
||||||
"TODO"
|
"TODO"
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -17,12 +17,9 @@
|
|||||||
#define DEFAULT ESC "0m"
|
#define DEFAULT ESC "0m"
|
||||||
#define COLORED(COLOR, TEXT) COLOR TEXT DEFAULT
|
#define COLORED(COLOR, TEXT) COLOR TEXT DEFAULT
|
||||||
|
|
||||||
static int __map_mod(int a, int b) {
|
uint32_t map_mod_index(const map_header_t *header, uint32_t i) {
|
||||||
int r = a % b;
|
return i % header->mapping_capacity;
|
||||||
if (r < 0) r += (b > 0 ? b : -b);
|
|
||||||
return r;
|
|
||||||
}
|
}
|
||||||
#define mod(a, b) __map_mod(a, b)
|
|
||||||
|
|
||||||
void map_print_mapping_state(void *this, FILE *file) {
|
void map_print_mapping_state(void *this, FILE *file) {
|
||||||
map_header_t *header = PTR_FROM_FIELD_PTR(map_header_t, bytes, this);
|
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]);
|
return (const uint8_t *) (&pair[this->key_offset]);
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO: just make these internal probably
|
bool map_key_equals(map_header_t *header, const uint8_t *key1_bytes, const uint8_t *key2_bytes) {
|
||||||
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);
|
|
||||||
if (header->equals != NULL) {
|
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++ ) {
|
for ( unsigned int i = 0; i < header->key_size; i++ ) {
|
||||||
if (key1_bytes[i] != key2_bytes[i]) {
|
if (key1_bytes[i] != key2_bytes[i]) {
|
||||||
return false;
|
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) {
|
unsigned int map_place(void *this, index_pair_t idx) {
|
||||||
map_header_t *header = PTR_FROM_FIELD_PTR(map_header_t, bytes, this);
|
map_header_t *header = PTR_FROM_FIELD_PTR(map_header_t, bytes, this);
|
||||||
if (idx.has_old) {
|
if (idx.has_old) {
|
||||||
header->mapping_arr[idx.new_i_into_mapping] = header->mapping_arr[idx.old_index];
|
header->mapping_arr[idx.new_i_into_mapping] = header->mapping_arr[idx.old_i_into_mapping];
|
||||||
header->mapping_arr[idx.old_index] = FLAG_TOMBSTONE;
|
header->mapping_arr[idx.old_i_into_mapping] = FLAG_TOMBSTONE;
|
||||||
for ( long i = idx.old_index; i != idx.new_i_into_mapping; mod(i-1, header->mapping_capacity) ) {
|
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) {
|
if (header->mapping_arr[i] == FLAG_TOMBSTONE) {
|
||||||
header->mapping_arr[i] = FLAG_FREE;
|
header->mapping_arr[i] = FLAG_FREE;
|
||||||
} else {
|
} else {
|
||||||
@@ -182,8 +175,7 @@ index_pair_t map_pair_hash(void *this, const uint8_t *pair) {
|
|||||||
.new_i_into_mapping=i_into_mapping,
|
.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
|
// 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