diff --git a/Makefile b/Makefile index fc0a083..5c643e2 100644 --- a/Makefile +++ b/Makefile @@ -1,4 +1,4 @@ -basic_flags := -std=c99 -pipe -Wall -Wpedantic -Wextra -Wconversion -Werror=implicit-function-declaration -Werror=incompatible-pointer-types -Werror=int-conversion -D_XOPEN_SOURCE_EXTENDED=1 +basic_flags := -std=c99 -pipe -Wall -Wpedantic -Wextra -Wconversion -Werror=implicit-function-declaration -Werror=implicit-int -Werror=incompatible-pointer-types -Werror=int-conversion -D_XOPEN_SOURCE_EXTENDED=1 debug_flags := -DDEBUG -ggdb sanitize_flags := -fsanitize=address -fsanitize=undefined # note: -fsanitize=leak not available on at least Mac 10.12 diff --git a/bank.c b/bank.c index 4de573b..77cf240 100644 --- a/bank.c +++ b/bank.c @@ -1,5 +1,18 @@ #include "bank.h" +#define ORCA_BANK_ENTRY_HEADER (sizeof(U32) + sizeof(U8)) +#define ORCA_BANK_ENTRY_ALIGN sizeof(Bank_entry) + +ORCA_FORCE_STATIC_INLINE +Usz bank_entry_padding(Usz glyph_count) { + return ORCA_BANK_ENTRY_ALIGN - + (ORCA_BANK_ENTRY_HEADER + glyph_count) % ORCA_BANK_ENTRY_ALIGN; +} +ORCA_FORCE_STATIC_INLINE +Usz bank_entry_size(Usz glyph_count) { + return ORCA_BANK_ENTRY_HEADER + bank_entry_padding(glyph_count); +} + void bank_init(Bank* bank) { bank->data = NULL; bank->capacity = 0; @@ -21,3 +34,62 @@ void bank_reserve(Bank* bank, Usz entries, Usz avg_count) { bank->data = realloc(bank->data, new_cap); } } + +Usz bank_append(Bank* restrict bank, Usz cur_size, Usz index, + Glyph* restrict glyphs, Usz glyph_count) { + assert(index <= ORCA_BANK_INDEX_MAX); + assert(glyph_count <= ORCA_BANK_ENTRY_GLYPHS_MAX); + // no overflow check + Usz new_size = cur_size + bank_entry_size(glyph_count); + if (new_size > bank->capacity) + bank_enlarge_to(bank, new_size); + char* data = bank->data; + Bank_entry* entry = + (Bank_entry*)ORCA_ASSUME_ALIGNED(data, ORCA_BANK_ENTRY_ALIGN); + entry->index = (U32)index; + entry->size = (U8)glyph_count; + data += ORCA_BANK_ENTRY_HEADER; + memcpy(data, glyphs, glyph_count); +#ifndef NDEBUG + Usz padding = bank_entry_padding(glyph_count); + memset(data + glyph_count, 0x1c, padding); +#endif + return new_size; +} + +Usz bank_read(char const* bank_data, Usz bank_size, + Bank_cursor* restrict cursor, Usz index, Usz num_to_read, + Glyph* restrict dest, Usz dest_count) { + assert(index <= ORCA_BANK_INDEX_MAX); + assert(num_to_read <= ORCA_BANK_ENTRY_GLYPHS_MAX); + Usz offset = *cursor; + Bank_entry* entry; + Usz entry_index; + Usz entry_size; + Usz num_to_copy; + +next: + if (offset == bank_size) + goto fail; + entry = (Bank_entry*)ORCA_ASSUME_ALIGNED(bank_data + offset, + ORCA_BANK_ENTRY_ALIGN); + entry_index = entry->index; + if (entry_index > index) + goto fail; + entry_size = entry->size; + if (entry_index < index) { + offset += ORCA_BANK_ENTRY_HEADER + entry_size; + goto next; + } + num_to_copy = dest_count < entry_size ? dest_count : entry_size; + memcpy(dest, bank_data + offset + ORCA_BANK_ENTRY_HEADER, num_to_copy); + if (num_to_copy < dest_count) + memset(dest, '.', dest_count - num_to_copy); + *cursor = ORCA_BANK_ENTRY_HEADER + entry_size; + return num_to_copy; + +fail: + memset(dest, '.', dest_count); + *cursor = offset; + return 0; +} diff --git a/bank.h b/bank.h index 753ba39..f3e8b12 100644 --- a/bank.h +++ b/bank.h @@ -1,7 +1,7 @@ #include "base.h" typedef struct { - U32 grid_index; + U32 index; U8 size; } Bank_entry; @@ -12,49 +12,17 @@ typedef struct { typedef size_t Bank_cursor; -#define ORCA_BANK_GRID_INDEX_MAX UINT32_MAX +#define ORCA_BANK_INDEX_MAX UINT32_MAX #define ORCA_BANK_ENTRY_GLYPHS_MAX UINT8_MAX -#define ORCA_BANK_ENTRY_HEADER (sizeof(U32) + sizeof(U8)) -#define ORCA_BANK_ENTRY_ALIGN sizeof(Bank_entry) void bank_init(Bank* bank); void bank_deinit(Bank* bank); void bank_enlarge_to(Bank* bank, Usz bytes); void bank_reserve_average(Bank* bank, Usz num_entries, Usz avg_glyph_count); +static inline void bank_cursor_reset(Bank_cursor* cursor) { *cursor = 0; } -static inline Usz bank_append(Bank* restrict bank, Usz cur_size, Usz grid_index, - Glyph* restrict glyphs, Usz glyph_count); - -ORCA_FORCE_STATIC_INLINE -Usz bank_entry_padding(Usz glyph_count) { - return ORCA_BANK_ENTRY_ALIGN - - (ORCA_BANK_ENTRY_HEADER + glyph_count) % ORCA_BANK_ENTRY_ALIGN; -} -ORCA_FORCE_STATIC_INLINE -Usz bank_entry_size(Usz glyph_count) { - return ORCA_BANK_ENTRY_HEADER + bank_entry_padding(glyph_count); -} - -static inline Usz bank_append(Bank* restrict bank, Usz cur_size, Usz grid_index, - Glyph* restrict glyphs, Usz glyph_count) { - assert(grid_index <= ORCA_BANK_GRID_INDEX_MAX); - assert(glyph_count <= ORCA_BANK_ENTRY_GLYPHS_MAX); - // no overflow check - Usz new_size = cur_size + bank_entry_size(glyph_count); - if (new_size > bank->capacity) - bank_enlarge_to(bank, new_size); - char* data = bank->data; - { - Bank_entry* entry = - (Bank_entry*)ORCA_ASSUME_ALIGNED(data, ORCA_BANK_ENTRY_ALIGN); - entry->grid_index = (U32)grid_index; - entry->size = (U8)glyph_count; - } - data += ORCA_BANK_ENTRY_HEADER; - memcpy(data, glyphs, glyph_count); -#ifndef NDEBUG - Usz padding = bank_entry_padding(glyph_count); - memset(data + glyph_count, 0x1c, padding); -#endif - return new_size; -} +Usz bank_append(Bank* restrict bank, Usz cur_size, Usz index, + Glyph* restrict glyphs, Usz glyph_count); +Usz bank_read(char const* bank_data, Usz bank_size, + Bank_cursor* restrict cursor, Usz index, Usz num_to_read, + Glyph* restrict dest, Usz dest_count);