ref: 7636f011e455a9d8a7e3ef6a0222801443886b45
parent: 1d16496ba7c15cc5dd9c34e8a6f2f94385be0612
author: cancel <cancel@cancel.fm>
date: Wed Nov 28 05:30:24 EST 2018
Add more bank procedures
--- a/bank.c
+++ b/bank.c
@@ -5,6 +5,19 @@
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);
+ }
}
--- a/bank.h
+++ b/bank.h
@@ -10,7 +10,51 @@
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;
+}
--- a/base.h
+++ b/base.h
@@ -10,12 +10,30 @@
#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
#define ORCA_X_MAX UINT16_MAX
@@ -39,3 +57,17 @@
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;
+}