| 1 | #ifndef wren_utils_h |
| 2 | #define wren_utils_h |
| 3 | |
| 4 | #include "wren.h" |
| 5 | #include "wren_common.h" |
| 6 | |
| 7 | // Reusable data structures and other utility functions. |
| 8 | |
| 9 | // Forward declare this here to break a cycle between wren_utils.h and |
| 10 | // wren_value.h. |
| 11 | typedef struct sObjString ObjString; |
| 12 | |
| 13 | // We need buffers of a few different types. To avoid lots of casting between |
| 14 | // void* and back, we'll use the preprocessor as a poor man's generics and let |
| 15 | // it generate a few type-specific ones. |
| 16 | #define DECLARE_BUFFER(name, type) \ |
| 17 | typedef struct \ |
| 18 | { \ |
| 19 | type* data; \ |
| 20 | int count; \ |
| 21 | int capacity; \ |
| 22 | } name##Buffer; \ |
| 23 | void wren##name##BufferInit(name##Buffer* buffer); \ |
| 24 | void wren##name##BufferClear(WrenVM* vm, name##Buffer* buffer); \ |
| 25 | void wren##name##BufferFill(WrenVM* vm, name##Buffer* buffer, type data, \ |
| 26 | int count); \ |
| 27 | void wren##name##BufferWrite(WrenVM* vm, name##Buffer* buffer, type data) |
| 28 | |
| 29 | // This should be used once for each type instantiation, somewhere in a .c file. |
| 30 | #define DEFINE_BUFFER(name, type) \ |
| 31 | void wren##name##BufferInit(name##Buffer* buffer) \ |
| 32 | { \ |
| 33 | buffer->data = NULL; \ |
| 34 | buffer->capacity = 0; \ |
| 35 | buffer->count = 0; \ |
| 36 | } \ |
| 37 | \ |
| 38 | void wren##name##BufferClear(WrenVM* vm, name##Buffer* buffer) \ |
| 39 | { \ |
| 40 | wrenReallocate(vm, buffer->data, 0, 0); \ |
| 41 | wren##name##BufferInit(buffer); \ |
| 42 | } \ |
| 43 | \ |
| 44 | void wren##name##BufferFill(WrenVM* vm, name##Buffer* buffer, type data, \ |
| 45 | int count) \ |
| 46 | { \ |
| 47 | if (buffer->capacity < buffer->count + count) \ |
| 48 | { \ |
| 49 | int capacity = wrenPowerOf2Ceil(buffer->count + count); \ |
| 50 | buffer->data = (type*)wrenReallocate(vm, buffer->data, \ |
| 51 | buffer->capacity * sizeof(type), capacity * sizeof(type)); \ |
| 52 | buffer->capacity = capacity; \ |
| 53 | } \ |
| 54 | \ |
| 55 | for (int i = 0; i < count; i++) \ |
| 56 | { \ |
| 57 | buffer->data[buffer->count++] = data; \ |
| 58 | } \ |
| 59 | } \ |
| 60 | \ |
| 61 | void wren##name##BufferWrite(WrenVM* vm, name##Buffer* buffer, type data) \ |
| 62 | { \ |
| 63 | wren##name##BufferFill(vm, buffer, data, 1); \ |
| 64 | } |
| 65 | |
| 66 | DECLARE_BUFFER(Byte, uint8_t); |
| 67 | DECLARE_BUFFER(Int, int); |
| 68 | DECLARE_BUFFER(String, ObjString*); |
| 69 | |
| 70 | // TODO: Change this to use a map. |
| 71 | typedef StringBuffer SymbolTable; |
| 72 | |
| 73 | // Initializes the symbol table. |
| 74 | void wrenSymbolTableInit(SymbolTable* symbols); |
| 75 | |
| 76 | // Frees all dynamically allocated memory used by the symbol table, but not the |
| 77 | // SymbolTable itself. |
| 78 | void wrenSymbolTableClear(WrenVM* vm, SymbolTable* symbols); |
| 79 | |
| 80 | // Adds name to the symbol table. Returns the index of it in the table. |
| 81 | int wrenSymbolTableAdd(WrenVM* vm, SymbolTable* symbols, |
| 82 | const char* name, size_t length); |
| 83 | |
| 84 | // Adds name to the symbol table. Returns the index of it in the table. Will |
| 85 | // use an existing symbol if already present. |
| 86 | int wrenSymbolTableEnsure(WrenVM* vm, SymbolTable* symbols, |
| 87 | const char* name, size_t length); |
| 88 | |
| 89 | // Looks up name in the symbol table. Returns its index if found or -1 if not. |
| 90 | int wrenSymbolTableFind(const SymbolTable* symbols, |
| 91 | const char* name, size_t length); |
| 92 | |
| 93 | void wrenBlackenSymbolTable(WrenVM* vm, SymbolTable* symbolTable); |
| 94 | |
| 95 | // Returns the number of bytes needed to encode [value] in UTF-8. |
| 96 | // |
| 97 | // Returns 0 if [value] is too large to encode. |
| 98 | int wrenUtf8EncodeNumBytes(int value); |
| 99 | |
| 100 | // Encodes value as a series of bytes in [bytes], which is assumed to be large |
| 101 | // enough to hold the encoded result. |
| 102 | // |
| 103 | // Returns the number of written bytes. |
| 104 | int wrenUtf8Encode(int value, uint8_t* bytes); |
| 105 | |
| 106 | // Decodes the UTF-8 sequence starting at [bytes] (which has max [length]), |
| 107 | // returning the code point. |
| 108 | // |
| 109 | // Returns -1 if the bytes are not a valid UTF-8 sequence. |
| 110 | int wrenUtf8Decode(const uint8_t* bytes, uint32_t length); |
| 111 | |
| 112 | // Returns the number of bytes in the UTF-8 sequence starting with [byte]. |
| 113 | // |
| 114 | // If the character at that index is not the beginning of a UTF-8 sequence, |
| 115 | // returns 0. |
| 116 | int wrenUtf8DecodeNumBytes(uint8_t byte); |
| 117 | |
| 118 | // Returns the smallest power of two that is equal to or greater than [n]. |
| 119 | int wrenPowerOf2Ceil(int n); |
| 120 | |
| 121 | // Validates that [value] is within `[0, count)`. Also allows |
| 122 | // negative indices which map backwards from the end. Returns the valid positive |
| 123 | // index value. If invalid, returns `UINT32_MAX`. |
| 124 | uint32_t wrenValidateIndex(uint32_t count, int64_t value); |
| 125 | |
| 126 | #endif |
| 127 | |