From 7636f011e455a9d8a7e3ef6a0222801443886b45 Mon Sep 17 00:00:00 2001 From: cancel Date: Wed, 28 Nov 2018 10:30:24 +0900 Subject: [PATCH] Add more bank procedures --- bank.c | 17 +++++++++++++++-- bank.h | 46 +++++++++++++++++++++++++++++++++++++++++++++- base.h | 32 ++++++++++++++++++++++++++++++++ 3 files changed, 92 insertions(+), 3 deletions(-) diff --git a/bank.c b/bank.c index e701de2..4de573b 100644 --- a/bank.c +++ b/bank.c @@ -5,6 +5,19 @@ void bank_init(Bank* bank) { bank->capacity = 0; } -void bank_deinit(Bank* bank) { - free(bank->data); +void bank_deinit(Bank* bank) { free(bank->data); } + +void bank_enlarge_to(Bank* bank, Usz bytes) { + Usz new_cap = orca_round_up_power2(bytes); + bank->data = realloc(bank->data, new_cap); + bank->capacity = new_cap; +} + +void bank_reserve(Bank* bank, Usz entries, Usz avg_count) { + Usz avg_size = bank_entry_size(avg_count); + Usz total_bytes = entries * avg_size; + if (bank->capacity < total_bytes) { + Usz new_cap = orca_round_up_power2(total_bytes); + bank->data = realloc(bank->data, new_cap); + } } diff --git a/bank.h b/bank.h index 3294f69..753ba39 100644 --- a/bank.h +++ b/bank.h @@ -10,7 +10,51 @@ typedef struct { Usz capacity; } Bank; -typedef char* Bank_cursor; +typedef size_t Bank_cursor; + +#define ORCA_BANK_GRID_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 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; +} diff --git a/base.h b/base.h index 2e1198e..ecaabca 100644 --- a/base.h +++ b/base.h @@ -10,10 +10,28 @@ #if defined(__GNUC__) || defined(__clang__) #define ORCA_FORCE_INLINE __attribute__((always_inline)) inline +#define ORCA_FORCE_STATIC_INLINE __attribute__((always_inline)) static inline #elif defined(_MSC_VER) #define ORCA_FORCE_INLINE __forceinline +#define ORCA_FORCE_STATIC_INLINE __forceinline static #else #define ORCA_FORCE_INLINE inline +#define ORCA_FORCE_STATIC_INLINE inline static +#endif + +#if defined(__GNUC__) || defined(__clang__) +#define ORCA_FORCE_NO_INLINE __attribute__((noinline)) +#elif defined(_MSC_VER) +#define ORCA_FORCE_NO_INLINE __declspec(noinline) +#else +#define ORCA_FORCE_NO_INLINE +#endif + +#if defined(__GNUC__) || defined(__clang__) +#define ORCA_ASSUME_ALIGNED(_ptr, _alignment) \ + __builtin_assume_aligned(_ptr, _alignment) +#else +#define ORCA_ASSUME_ALIGNED(_ptr, _alignment) (_ptr) #endif #define ORCA_Y_MAX UINT16_MAX @@ -39,3 +57,17 @@ typedef struct { U16 height; U16 width; } Field; + +ORCA_FORCE_STATIC_INLINE Usz orca_round_up_power2(Usz x) { + assert(x <= SIZE_MAX / 2 + 1); + x -= 1; + x |= (x >> 1); + x |= (x >> 2); + x |= (x >> 4); + x |= (x >> 8); + x |= (x >> 16); +#if SIZE_MAX > UINT32_MAX + x |= (x >> 32); +#endif + return x + 1; +}