1#include <string.h>
2
3#include "wren_utils.h"
4#include "wren_vm.h"
5
6DEFINE_BUFFER(Byte, uint8_t);
7DEFINE_BUFFER(Int, int);
8DEFINE_BUFFER(String, ObjString*);
9
10void wrenSymbolTableInit(SymbolTable* symbols)
11{
12 wrenStringBufferInit(symbols);
13}
14
15void wrenSymbolTableClear(WrenVM* vm, SymbolTable* symbols)
16{
17 wrenStringBufferClear(vm, symbols);
18}
19
20int wrenSymbolTableAdd(WrenVM* vm, SymbolTable* symbols,
21 const char* name, size_t length)
22{
23 ObjString* symbol = AS_STRING(wrenNewStringLength(vm, name, length));
24
25 wrenPushRoot(vm, &symbol->obj);
26 wrenStringBufferWrite(vm, symbols, symbol);
27 wrenPopRoot(vm);
28
29 return symbols->count - 1;
30}
31
32int wrenSymbolTableEnsure(WrenVM* vm, SymbolTable* symbols,
33 const char* name, size_t length)
34{
35 // See if the symbol is already defined.
36 int existing = wrenSymbolTableFind(symbols, name, length);
37 if (existing != -1) return existing;
38
39 // New symbol, so add it.
40 return wrenSymbolTableAdd(vm, symbols, name, length);
41}
42
43int wrenSymbolTableFind(const SymbolTable* symbols,
44 const char* name, size_t length)
45{
46 // See if the symbol is already defined.
47 // TODO: O(n). Do something better.
48 for (int i = 0; i < symbols->count; i++)
49 {
50 if (wrenStringEqualsCString(symbols->data[i], name, length)) return i;
51 }
52
53 return -1;
54}
55
56void wrenBlackenSymbolTable(WrenVM* vm, SymbolTable* symbolTable)
57{
58 for (int i = 0; i < symbolTable->count; i++)
59 {
60 wrenGrayObj(vm, &symbolTable->data[i]->obj);
61 }
62
63 // Keep track of how much memory is still in use.
64 vm->bytesAllocated += symbolTable->capacity * sizeof(*symbolTable->data);
65}
66
67int wrenUtf8EncodeNumBytes(int value)
68{
69 ASSERT(value >= 0, "Cannot encode a negative value.");
70
71 if (value <= 0x7f) return 1;
72 if (value <= 0x7ff) return 2;
73 if (value <= 0xffff) return 3;
74 if (value <= 0x10ffff) return 4;
75 return 0;
76}
77
78int wrenUtf8Encode(int value, uint8_t* bytes)
79{
80 if (value <= 0x7f)
81 {
82 // Single byte (i.e. fits in ASCII).
83 *bytes = value & 0x7f;
84 return 1;
85 }
86 else if (value <= 0x7ff)
87 {
88 // Two byte sequence: 110xxxxx 10xxxxxx.
89 *bytes = 0xc0 | ((value & 0x7c0) >> 6);
90 bytes++;
91 *bytes = 0x80 | (value & 0x3f);
92 return 2;
93 }
94 else if (value <= 0xffff)
95 {
96 // Three byte sequence: 1110xxxx 10xxxxxx 10xxxxxx.
97 *bytes = 0xe0 | ((value & 0xf000) >> 12);
98 bytes++;
99 *bytes = 0x80 | ((value & 0xfc0) >> 6);
100 bytes++;
101 *bytes = 0x80 | (value & 0x3f);
102 return 3;
103 }
104 else if (value <= 0x10ffff)
105 {
106 // Four byte sequence: 11110xxx 10xxxxxx 10xxxxxx 10xxxxxx.
107 *bytes = 0xf0 | ((value & 0x1c0000) >> 18);
108 bytes++;
109 *bytes = 0x80 | ((value & 0x3f000) >> 12);
110 bytes++;
111 *bytes = 0x80 | ((value & 0xfc0) >> 6);
112 bytes++;
113 *bytes = 0x80 | (value & 0x3f);
114 return 4;
115 }
116
117 // Invalid Unicode value. See: http://tools.ietf.org/html/rfc3629
118 UNREACHABLE();
119 return 0;
120}
121
122int wrenUtf8Decode(const uint8_t* bytes, uint32_t length)
123{
124 // Single byte (i.e. fits in ASCII).
125 if (*bytes <= 0x7f) return *bytes;
126
127 int value;
128 uint32_t remainingBytes;
129 if ((*bytes & 0xe0) == 0xc0)
130 {
131 // Two byte sequence: 110xxxxx 10xxxxxx.
132 value = *bytes & 0x1f;
133 remainingBytes = 1;
134 }
135 else if ((*bytes & 0xf0) == 0xe0)
136 {
137 // Three byte sequence: 1110xxxx 10xxxxxx 10xxxxxx.
138 value = *bytes & 0x0f;
139 remainingBytes = 2;
140 }
141 else if ((*bytes & 0xf8) == 0xf0)
142 {
143 // Four byte sequence: 11110xxx 10xxxxxx 10xxxxxx 10xxxxxx.
144 value = *bytes & 0x07;
145 remainingBytes = 3;
146 }
147 else
148 {
149 // Invalid UTF-8 sequence.
150 return -1;
151 }
152
153 // Don't read past the end of the buffer on truncated UTF-8.
154 if (remainingBytes > length - 1) return -1;
155
156 while (remainingBytes > 0)
157 {
158 bytes++;
159 remainingBytes--;
160
161 // Remaining bytes must be of form 10xxxxxx.
162 if ((*bytes & 0xc0) != 0x80) return -1;
163
164 value = value << 6 | (*bytes & 0x3f);
165 }
166
167 return value;
168}
169
170int wrenUtf8DecodeNumBytes(uint8_t byte)
171{
172 // If the byte starts with 10xxxxx, it's the middle of a UTF-8 sequence, so
173 // don't count it at all.
174 if ((byte & 0xc0) == 0x80) return 0;
175
176 // The first byte's high bits tell us how many bytes are in the UTF-8
177 // sequence.
178 if ((byte & 0xf8) == 0xf0) return 4;
179 if ((byte & 0xf0) == 0xe0) return 3;
180 if ((byte & 0xe0) == 0xc0) return 2;
181 return 1;
182}
183
184// From: http://graphics.stanford.edu/~seander/bithacks.html#RoundUpPowerOf2Float
185int wrenPowerOf2Ceil(int n)
186{
187 n--;
188 n |= n >> 1;
189 n |= n >> 2;
190 n |= n >> 4;
191 n |= n >> 8;
192 n |= n >> 16;
193 n++;
194
195 return n;
196}
197
198uint32_t wrenValidateIndex(uint32_t count, int64_t value)
199{
200 // Negative indices count from the end.
201 if (value < 0) value = count + value;
202
203 // Check bounds.
204 if (value >= 0 && value < count) return (uint32_t)value;
205
206 return UINT32_MAX;
207}
208