2016-05-03 16:15:08 +00:00
|
|
|
/*
|
2017-01-23 06:19:43 +00:00
|
|
|
4coder_table.h - Preversioning
|
|
|
|
no warranty implied; use at your own risk
|
|
|
|
|
|
|
|
This software is in the public domain. Where that dedication is not
|
|
|
|
recognized, you are granted a perpetual, irrevocable license to copy,
|
|
|
|
distribute, and modify this file as you see fit.
|
|
|
|
*/
|
2016-05-03 16:15:08 +00:00
|
|
|
|
|
|
|
// TOP
|
|
|
|
|
2017-01-23 06:19:43 +00:00
|
|
|
#if !defined(FCODER_TABLE_H)
|
|
|
|
#define FCODER_TABLE_H
|
|
|
|
|
|
|
|
// 4tech_standard_preamble.h
|
|
|
|
#if !defined(FTECH_INTEGERS)
|
|
|
|
#define FTECH_INTEGERS
|
|
|
|
#include <stdint.h>
|
|
|
|
typedef int8_t i8_4tech;
|
|
|
|
typedef int16_t i16_4tech;
|
|
|
|
typedef int32_t i32_4tech;
|
|
|
|
typedef int64_t i64_4tech;
|
|
|
|
|
|
|
|
typedef uint8_t u8_4tech;
|
|
|
|
typedef uint16_t u16_4tech;
|
|
|
|
typedef uint32_t u32_4tech;
|
|
|
|
typedef uint64_t u64_4tech;
|
|
|
|
|
2017-02-18 01:04:41 +00:00
|
|
|
typedef u64_4tech umem_4tech;
|
|
|
|
|
2017-01-23 06:19:43 +00:00
|
|
|
typedef float f32_4tech;
|
|
|
|
typedef double f64_4tech;
|
|
|
|
|
|
|
|
typedef int8_t b8_4tech;
|
|
|
|
typedef int32_t b32_4tech;
|
|
|
|
#endif
|
|
|
|
|
|
|
|
#if !defined(Assert)
|
|
|
|
# define Assert(n) do{ if (!(n)) *(int*)0 = 0xA11E; }while(0)
|
|
|
|
#endif
|
|
|
|
// standard preamble end
|
|
|
|
|
2016-05-03 16:15:08 +00:00
|
|
|
#define TableHashEmpty 0
|
|
|
|
#define TableHashDeleted 1
|
|
|
|
#define TableHashMin 0x10000000
|
|
|
|
|
2016-07-10 05:49:11 +00:00
|
|
|
#include <string.h>
|
|
|
|
|
2017-01-23 06:19:43 +00:00
|
|
|
typedef u32_4tech Hash_Function(void *item, void *arg);
|
|
|
|
typedef i32_4tech Compare_Function(void *key, void *item, void *arg);
|
2016-05-03 16:15:08 +00:00
|
|
|
|
|
|
|
struct Table{
|
2017-01-23 06:19:43 +00:00
|
|
|
u32_4tech *hash_array;
|
2016-07-10 05:49:11 +00:00
|
|
|
char *data_array;
|
2017-03-20 06:35:39 +00:00
|
|
|
u32_4tech count, max;
|
|
|
|
u32_4tech item_size;
|
2016-05-03 16:15:08 +00:00
|
|
|
};
|
|
|
|
|
2017-03-20 06:35:39 +00:00
|
|
|
static umem_4tech
|
|
|
|
table_required_mem_size(u32_4tech table_size, u32_4tech item_size){
|
|
|
|
u32_4tech hash_size = ((table_size * sizeof(u32_4tech)) + 7) & ~7;
|
|
|
|
umem_4tech mem_size = hash_size + table_size * item_size;
|
2016-05-03 16:15:08 +00:00
|
|
|
return(mem_size);
|
|
|
|
}
|
|
|
|
|
2016-07-10 05:49:11 +00:00
|
|
|
static void
|
2017-03-20 06:35:39 +00:00
|
|
|
table_init_memory(Table *table, void *memory, u32_4tech table_size, u32_4tech item_size){
|
|
|
|
umem_4tech hash_size = table_size * sizeof(u32_4tech);
|
2016-05-03 16:15:08 +00:00
|
|
|
hash_size = (hash_size + 7) & ~7;
|
|
|
|
|
2017-01-23 06:19:43 +00:00
|
|
|
table->hash_array = (u32_4tech*)memory;
|
2016-07-10 05:49:11 +00:00
|
|
|
table->data_array = (char*)(table->hash_array) + hash_size;
|
2016-05-03 16:15:08 +00:00
|
|
|
|
|
|
|
table->count = 0;
|
|
|
|
table->max = table_size;
|
|
|
|
table->item_size = item_size;
|
|
|
|
}
|
|
|
|
|
2017-01-23 06:19:43 +00:00
|
|
|
static i32_4tech
|
2016-05-03 16:15:08 +00:00
|
|
|
table_at_capacity(Table *table){
|
2017-01-23 06:19:43 +00:00
|
|
|
i32_4tech result = true;
|
2016-05-03 16:15:08 +00:00
|
|
|
if (table->count * 8 < table->max * 7){
|
2016-07-10 05:49:11 +00:00
|
|
|
result = false;
|
2016-05-03 16:15:08 +00:00
|
|
|
}
|
|
|
|
return(result);
|
|
|
|
}
|
|
|
|
|
2017-01-23 06:19:43 +00:00
|
|
|
static i32_4tech
|
2016-05-03 16:15:08 +00:00
|
|
|
table_add(Table *table, void *item, void *arg, Hash_Function *hash_func, Compare_Function *comp_func){
|
2017-01-23 06:19:43 +00:00
|
|
|
Assert(table->count * 8 < table->max * 7);
|
2016-06-01 16:03:45 +00:00
|
|
|
|
2017-01-23 06:19:43 +00:00
|
|
|
u32_4tech hash = (hash_func(item, arg) | TableHashMin);
|
2017-03-20 06:35:39 +00:00
|
|
|
u32_4tech i = hash % table->max;
|
|
|
|
u32_4tech start = i;
|
2017-01-23 06:19:43 +00:00
|
|
|
u32_4tech *inspect = table->hash_array + i;
|
2016-05-03 16:15:08 +00:00
|
|
|
|
|
|
|
while (*inspect >= TableHashMin){
|
|
|
|
if (*inspect == hash){
|
|
|
|
if (comp_func(item, table->data_array + i*table->item_size, arg) == 0){
|
|
|
|
return(1);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
++i;
|
|
|
|
++inspect;
|
|
|
|
if (i == table->max){
|
|
|
|
i = 0;
|
|
|
|
inspect = table->hash_array;
|
|
|
|
}
|
2017-01-23 06:19:43 +00:00
|
|
|
Assert(i != start);
|
2016-05-03 16:15:08 +00:00
|
|
|
}
|
|
|
|
*inspect = hash;
|
|
|
|
memcpy(table->data_array + i*table->item_size, item, table->item_size);
|
|
|
|
++table->count;
|
|
|
|
|
|
|
|
return(0);
|
|
|
|
}
|
|
|
|
|
2017-01-23 06:19:43 +00:00
|
|
|
static i32_4tech
|
|
|
|
table_find_pos(Table *table, void *search_key, void *arg, i32_4tech *pos, i32_4tech *index, Hash_Function *hash_func, Compare_Function *comp_func){
|
2017-03-23 19:14:39 +00:00
|
|
|
Assert((table->count - 1) * 8 < table->max * 7);
|
2016-05-03 16:15:08 +00:00
|
|
|
|
2017-01-23 06:19:43 +00:00
|
|
|
u32_4tech hash = (hash_func(search_key, arg) | TableHashMin);
|
2017-03-20 06:35:39 +00:00
|
|
|
u32_4tech i = hash % table->max;
|
|
|
|
u32_4tech start = i;
|
2017-01-23 06:19:43 +00:00
|
|
|
u32_4tech *inspect = table->hash_array + i;
|
2016-05-03 16:15:08 +00:00
|
|
|
|
|
|
|
while (*inspect != TableHashEmpty){
|
|
|
|
if (*inspect == hash){
|
|
|
|
if (comp_func(search_key, table->data_array + i*table->item_size, arg) == 0){
|
|
|
|
if (pos) *pos = i*table->item_size;
|
|
|
|
if (index) *index = i;
|
|
|
|
return(1);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
++i;
|
|
|
|
++inspect;
|
|
|
|
if (i == table->max){
|
|
|
|
i = 0;
|
|
|
|
inspect = table->hash_array;
|
|
|
|
}
|
2016-06-01 16:03:45 +00:00
|
|
|
if (i == start) break;
|
2016-05-03 16:15:08 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
return(0);
|
|
|
|
}
|
|
|
|
|
|
|
|
inline void*
|
|
|
|
table_find_item(Table *table, void *search_key, void *arg, Hash_Function *hash_func, Compare_Function *comp_func){
|
|
|
|
void *result = 0;
|
2017-01-23 06:19:43 +00:00
|
|
|
i32_4tech pos;
|
2016-05-03 16:15:08 +00:00
|
|
|
if (table_find_pos(table, search_key, arg, &pos, 0, hash_func, comp_func)){
|
|
|
|
result = table->data_array + pos;
|
|
|
|
}
|
|
|
|
return(result);
|
|
|
|
}
|
|
|
|
|
|
|
|
inline void
|
2017-01-23 06:19:43 +00:00
|
|
|
table_remove_index(Table *table, i32_4tech index){
|
2016-05-03 16:15:08 +00:00
|
|
|
table->hash_array[index] = TableHashDeleted;
|
|
|
|
--table->count;
|
|
|
|
}
|
|
|
|
|
2017-01-23 06:19:43 +00:00
|
|
|
inline i32_4tech
|
2016-05-03 16:15:08 +00:00
|
|
|
table_remove_match(Table *table, void *search_key, void *arg, Hash_Function *hash_func, Compare_Function *comp_func){
|
2017-01-23 06:19:43 +00:00
|
|
|
i32_4tech result = false;
|
|
|
|
i32_4tech index;
|
2016-05-03 16:15:08 +00:00
|
|
|
if (table_find_pos(table, search_key, arg, 0, &index, hash_func, comp_func)){
|
|
|
|
table_remove_index(table, index);
|
2016-07-10 05:49:11 +00:00
|
|
|
result = true;
|
2016-05-03 16:15:08 +00:00
|
|
|
}
|
|
|
|
return(result);
|
|
|
|
}
|
|
|
|
|
|
|
|
inline void
|
|
|
|
table_clear(Table *table){
|
|
|
|
table->count = 0;
|
|
|
|
memset(table->hash_array, 0, table->max*sizeof(*table->hash_array));
|
|
|
|
}
|
|
|
|
|
2016-07-10 05:49:11 +00:00
|
|
|
static void
|
2016-05-03 16:15:08 +00:00
|
|
|
table_rehash(Table *src, Table *dst, void *arg, Hash_Function *hash_func, Compare_Function *comp_func){
|
2017-01-23 06:19:43 +00:00
|
|
|
Assert((dst->count + src->count - 1) * 7 < dst->max * 8);
|
|
|
|
Assert(dst->item_size == src->item_size);
|
2016-05-03 16:15:08 +00:00
|
|
|
|
2017-01-23 06:19:43 +00:00
|
|
|
i32_4tech count = src->count;
|
|
|
|
i32_4tech item_size = src->item_size;
|
|
|
|
u32_4tech *hash_item = src->hash_array;
|
2016-07-10 05:49:11 +00:00
|
|
|
char *data_item = src->data_array;
|
2017-01-23 06:19:43 +00:00
|
|
|
for (i32_4tech i = 0, c = 0;
|
2016-07-10 05:49:11 +00:00
|
|
|
c < count;
|
|
|
|
++i, ++hash_item, data_item += item_size){
|
2016-05-03 16:15:08 +00:00
|
|
|
if (*hash_item >= TableHashMin){
|
|
|
|
++c;
|
|
|
|
table_add(dst, data_item, arg, hash_func, comp_func);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2017-01-23 06:19:43 +00:00
|
|
|
static u32_4tech
|
2016-05-03 16:15:08 +00:00
|
|
|
tbl_string_hash(void *item, void *arg){
|
|
|
|
String *string = (String*)item;
|
2017-01-23 06:19:43 +00:00
|
|
|
u32_4tech x = 5381;
|
2016-05-03 16:15:08 +00:00
|
|
|
(void)arg;
|
|
|
|
|
2017-01-23 06:19:43 +00:00
|
|
|
char *str = string->str;
|
|
|
|
i32_4tech len = string->size;
|
|
|
|
i32_4tech i = 0;
|
2016-05-03 16:15:08 +00:00
|
|
|
while (i < len){
|
2017-01-23 06:19:43 +00:00
|
|
|
char c = str[i++];
|
2016-05-03 16:15:08 +00:00
|
|
|
x = ((x << 5) + x) + c;
|
|
|
|
}
|
|
|
|
|
|
|
|
return(x);
|
|
|
|
}
|
|
|
|
|
2017-01-23 06:19:43 +00:00
|
|
|
static i32_4tech
|
2016-05-03 16:15:08 +00:00
|
|
|
tbl_string_compare(void *a, void *b, void *arg){
|
|
|
|
String *stra = (String*)a;
|
|
|
|
String *strb = (String*)b;
|
2017-01-23 06:19:43 +00:00
|
|
|
i32_4tech result = !match_ss(*stra, *strb);
|
2016-05-03 16:15:08 +00:00
|
|
|
return(result);
|
|
|
|
}
|
|
|
|
|
2017-01-23 06:19:43 +00:00
|
|
|
struct Offset_String{
|
|
|
|
i32_4tech offset;
|
|
|
|
i32_4tech size;
|
|
|
|
};
|
|
|
|
|
|
|
|
static u32_4tech
|
2016-05-03 16:15:08 +00:00
|
|
|
tbl_offset_string_hash(void *item, void *arg){
|
|
|
|
Offset_String *string = (Offset_String*)item;
|
2017-01-23 06:19:43 +00:00
|
|
|
u32_4tech x = 5381;
|
2016-05-03 16:15:08 +00:00
|
|
|
|
2017-01-23 06:19:43 +00:00
|
|
|
char *str = ((char*)arg) + string->offset;
|
|
|
|
i32_4tech len = string->size;
|
|
|
|
i32_4tech i = 0;
|
2016-05-03 16:15:08 +00:00
|
|
|
while (i < len){
|
2017-01-23 06:19:43 +00:00
|
|
|
char c = str[i++];
|
2016-05-03 16:15:08 +00:00
|
|
|
x = ((x << 5) + x) + c;
|
|
|
|
}
|
|
|
|
|
|
|
|
return(x);
|
|
|
|
}
|
|
|
|
|
2017-01-23 06:19:43 +00:00
|
|
|
static i32_4tech
|
2016-05-03 16:15:08 +00:00
|
|
|
tbl_offset_string_compare(void *a, void *b, void *arg){
|
|
|
|
Offset_String *ostra = (Offset_String*)a;
|
|
|
|
Offset_String *ostrb = (Offset_String*)b;
|
|
|
|
String stra = make_string((char*)arg + ostra->offset, ostra->size);
|
|
|
|
String strb = make_string((char*)arg + ostrb->offset, ostrb->size);
|
2017-01-23 06:19:43 +00:00
|
|
|
i32_4tech result = !match_ss(stra, strb);
|
2016-05-03 16:15:08 +00:00
|
|
|
return(result);
|
|
|
|
}
|
|
|
|
|
|
|
|
struct String_Space{
|
|
|
|
char *space;
|
2017-03-20 06:35:39 +00:00
|
|
|
u32_4tech pos;
|
|
|
|
u32_4tech new_pos;
|
|
|
|
u32_4tech max;
|
2016-05-03 16:15:08 +00:00
|
|
|
};
|
|
|
|
|
2016-07-10 05:49:11 +00:00
|
|
|
static Offset_String
|
2017-03-20 06:35:39 +00:00
|
|
|
strspace_append(String_Space *space, char *str, u32_4tech len){
|
2016-05-03 16:15:08 +00:00
|
|
|
Offset_String result = {};
|
|
|
|
if (space->new_pos + len <= space->max){
|
|
|
|
result.offset = space->new_pos;
|
|
|
|
result.size = len;
|
|
|
|
memcpy(space->space + space->new_pos, str, len);
|
|
|
|
space->new_pos = space->pos + len;
|
|
|
|
}
|
|
|
|
return(result);
|
|
|
|
}
|
|
|
|
|
2016-07-10 05:49:11 +00:00
|
|
|
static void
|
2016-05-03 16:15:08 +00:00
|
|
|
strspace_keep_prev(String_Space *space){
|
|
|
|
space->pos = space->new_pos;
|
|
|
|
}
|
|
|
|
|
2016-07-10 05:49:11 +00:00
|
|
|
static void
|
2016-05-03 16:15:08 +00:00
|
|
|
strspace_discard_prev(String_Space *space){
|
|
|
|
space->new_pos = space->pos;
|
|
|
|
}
|
|
|
|
|
2017-01-23 06:19:43 +00:00
|
|
|
#endif
|
|
|
|
|
2016-05-03 16:15:08 +00:00
|
|
|
// BOTTOM
|
|
|
|
|