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.
11typedef 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
66DECLARE_BUFFER(Byte, uint8_t);
67DECLARE_BUFFER(Int, int);
68DECLARE_BUFFER(String, ObjString*);
69
70// TODO: Change this to use a map.
71typedef StringBuffer SymbolTable;
72
73// Initializes the symbol table.
74void wrenSymbolTableInit(SymbolTable* symbols);
75
76// Frees all dynamically allocated memory used by the symbol table, but not the
77// SymbolTable itself.
78void wrenSymbolTableClear(WrenVM* vm, SymbolTable* symbols);
79
80// Adds name to the symbol table. Returns the index of it in the table.
81int 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.
86int 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.
90int wrenSymbolTableFind(const SymbolTable* symbols,
91 const char* name, size_t length);
92
93void 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.
98int 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.
104int 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.
110int 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.
116int wrenUtf8DecodeNumBytes(uint8_t byte);
117
118// Returns the smallest power of two that is equal to or greater than [n].
119int 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`.
124uint32_t wrenValidateIndex(uint32_t count, int64_t value);
125
126#endif
127