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 | |