shithub: orca

Download patch

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;
+}