Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
Roblox
GitHub Repository: Roblox/luau
Path: blob/master/extern/isocline/src/common.c
2727 views
1
/* ----------------------------------------------------------------------------
2
Copyright (c) 2021, Daan Leijen
3
This is free software; you can redistribute it and/or modify it
4
under the terms of the MIT License. A copy of the license can be
5
found in the "LICENSE" file at the root of this distribution.
6
-----------------------------------------------------------------------------*/
7
8
#include <string.h>
9
#include <stdio.h>
10
#include <stdarg.h>
11
#include <stdlib.h>
12
#include "common.h"
13
14
15
//-------------------------------------------------------------
16
// String wrappers for ssize_t
17
//-------------------------------------------------------------
18
19
ic_private ssize_t ic_strlen( const char* s ) {
20
if (s==NULL) return 0;
21
return to_ssize_t(strlen(s));
22
}
23
24
ic_private void ic_memmove( void* dest, const void* src, ssize_t n ) {
25
assert(dest!=NULL && src != NULL);
26
if (n <= 0) return;
27
memmove(dest,src,to_size_t(n));
28
}
29
30
31
ic_private void ic_memcpy( void* dest, const void* src, ssize_t n ) {
32
assert(dest!=NULL && src != NULL);
33
if (dest == NULL || src == NULL || n <= 0) return;
34
memcpy(dest,src,to_size_t(n));
35
}
36
37
ic_private void ic_memset(void* dest, uint8_t value, ssize_t n) {
38
assert(dest!=NULL);
39
if (dest == NULL || n <= 0) return;
40
memset(dest,(int8_t)value,to_size_t(n));
41
}
42
43
ic_private bool ic_memnmove( void* dest, ssize_t dest_size, const void* src, ssize_t n ) {
44
assert(dest!=NULL && src != NULL);
45
if (n <= 0) return true;
46
if (dest_size < n) { assert(false); return false; }
47
memmove(dest,src,to_size_t(n));
48
return true;
49
}
50
51
ic_private bool ic_strcpy( char* dest, ssize_t dest_size /* including 0 */, const char* src) {
52
assert(dest!=NULL && src != NULL);
53
if (dest == NULL || dest_size <= 0) return false;
54
ssize_t slen = ic_strlen(src);
55
if (slen >= dest_size) return false;
56
strcpy(dest,src);
57
assert(dest[slen] == 0);
58
return true;
59
}
60
61
62
ic_private bool ic_strncpy( char* dest, ssize_t dest_size /* including 0 */, const char* src, ssize_t n) {
63
assert(dest!=NULL && n < dest_size);
64
if (dest == NULL || dest_size <= 0) return false;
65
if (n >= dest_size) return false;
66
if (src==NULL || n <= 0) {
67
dest[0] = 0;
68
}
69
else {
70
strncpy(dest,src,to_size_t(n));
71
dest[n] = 0;
72
}
73
return true;
74
}
75
76
//-------------------------------------------------------------
77
// String matching
78
//-------------------------------------------------------------
79
80
ic_public bool ic_starts_with( const char* s, const char* prefix ) {
81
if (s==prefix) return true;
82
if (prefix==NULL) return true;
83
if (s==NULL) return false;
84
85
ssize_t i;
86
for( i = 0; s[i] != 0 && prefix[i] != 0; i++) {
87
if (s[i] != prefix[i]) return false;
88
}
89
return (prefix[i] == 0);
90
}
91
92
ic_private char ic_tolower( char c ) {
93
return (c >= 'A' && c <= 'Z' ? c - 'A' + 'a' : c);
94
}
95
96
ic_private void ic_str_tolower(char* s) {
97
while(*s != 0) {
98
*s = ic_tolower(*s);
99
s++;
100
}
101
}
102
103
ic_public bool ic_istarts_with( const char* s, const char* prefix ) {
104
if (s==prefix) return true;
105
if (prefix==NULL) return true;
106
if (s==NULL) return false;
107
108
ssize_t i;
109
for( i = 0; s[i] != 0 && prefix[i] != 0; i++) {
110
if (ic_tolower(s[i]) != ic_tolower(prefix[i])) return false;
111
}
112
return (prefix[i] == 0);
113
}
114
115
116
ic_private int ic_strnicmp(const char* s1, const char* s2, ssize_t n) {
117
if (s1 == NULL && s2 == NULL) return 0;
118
if (s1 == NULL) return -1;
119
if (s2 == NULL) return 1;
120
ssize_t i;
121
for (i = 0; s1[i] != 0 && i < n; i++) { // note: if s2[i] == 0 the loop will stop as c1 != c2
122
char c1 = ic_tolower(s1[i]);
123
char c2 = ic_tolower(s2[i]);
124
if (c1 < c2) return -1;
125
if (c1 > c2) return 1;
126
}
127
return ((i >= n || s2[i] == 0) ? 0 : -1);
128
}
129
130
ic_private int ic_stricmp(const char* s1, const char* s2) {
131
ssize_t len1 = ic_strlen(s1);
132
ssize_t len2 = ic_strlen(s2);
133
if (len1 < len2) return -1;
134
if (len1 > len2) return 1;
135
return (ic_strnicmp(s1, s2, (len1 >= len2 ? len1 : len2)));
136
}
137
138
139
static const char* ic_stristr(const char* s, const char* pat) {
140
if (s==NULL) return NULL;
141
if (pat==NULL || pat[0] == 0) return s;
142
ssize_t patlen = ic_strlen(pat);
143
for (ssize_t i = 0; s[i] != 0; i++) {
144
if (ic_strnicmp(s + i, pat, patlen) == 0) return (s+i);
145
}
146
return NULL;
147
}
148
149
ic_private bool ic_contains(const char* big, const char* s) {
150
if (big == NULL) return false;
151
if (s == NULL) return true;
152
return (strstr(big,s) != NULL);
153
}
154
155
ic_private bool ic_icontains(const char* big, const char* s) {
156
if (big == NULL) return false;
157
if (s == NULL) return true;
158
return (ic_stristr(big,s) != NULL);
159
}
160
161
162
//-------------------------------------------------------------
163
// Unicode
164
// QUTF-8: See <https://github.com/koka-lang/koka/blob/master/kklib/include/kklib/string.h>
165
// Raw bytes are code points 0xEE000 - 0xEE0FF
166
//-------------------------------------------------------------
167
#define IC_UNICODE_RAW ((unicode_t)(0xEE000U))
168
169
ic_private unicode_t unicode_from_raw(uint8_t c) {
170
return (IC_UNICODE_RAW + c);
171
}
172
173
ic_private bool unicode_is_raw(unicode_t u, uint8_t* c) {
174
if (u >= IC_UNICODE_RAW && u <= IC_UNICODE_RAW + 0xFF) {
175
*c = (uint8_t)(u - IC_UNICODE_RAW);
176
return true;
177
}
178
else {
179
return false;
180
}
181
}
182
183
ic_private void unicode_to_qutf8(unicode_t u, uint8_t buf[5]) {
184
memset(buf, 0, 5);
185
if (u <= 0x7F) {
186
buf[0] = (uint8_t)u;
187
}
188
else if (u <= 0x07FF) {
189
buf[0] = (0xC0 | ((uint8_t)(u >> 6)));
190
buf[1] = (0x80 | (((uint8_t)u) & 0x3F));
191
}
192
else if (u <= 0xFFFF) {
193
buf[0] = (0xE0 | ((uint8_t)(u >> 12)));
194
buf[1] = (0x80 | (((uint8_t)(u >> 6)) & 0x3F));
195
buf[2] = (0x80 | (((uint8_t)u) & 0x3F));
196
}
197
else if (u <= 0x10FFFF) {
198
if (unicode_is_raw(u, &buf[0])) {
199
buf[1] = 0;
200
}
201
else {
202
buf[0] = (0xF0 | ((uint8_t)(u >> 18)));
203
buf[1] = (0x80 | (((uint8_t)(u >> 12)) & 0x3F));
204
buf[2] = (0x80 | (((uint8_t)(u >> 6)) & 0x3F));
205
buf[3] = (0x80 | (((uint8_t)u) & 0x3F));
206
}
207
}
208
}
209
210
// is this a utf8 continuation byte?
211
ic_private bool utf8_is_cont(uint8_t c) {
212
return ((c & 0xC0) == 0x80);
213
}
214
215
ic_private unicode_t unicode_from_qutf8(const uint8_t* s, ssize_t len, ssize_t* count) {
216
unicode_t c0 = 0;
217
if (len <= 0 || s == NULL) {
218
goto fail;
219
}
220
// 1 byte
221
c0 = s[0];
222
if (c0 <= 0x7F && len >= 1) {
223
if (count != NULL) *count = 1;
224
return c0;
225
}
226
else if (c0 <= 0xC1) { // invalid continuation byte or invalid 0xC0, 0xC1
227
goto fail;
228
}
229
// 2 bytes
230
else if (c0 <= 0xDF && len >= 2 && utf8_is_cont(s[1])) {
231
if (count != NULL) *count = 2;
232
return (((c0 & 0x1F) << 6) | (s[1] & 0x3F));
233
}
234
// 3 bytes: reject overlong and surrogate halves
235
else if (len >= 3 &&
236
((c0 == 0xE0 && s[1] >= 0xA0 && s[1] <= 0xBF && utf8_is_cont(s[2])) ||
237
(c0 >= 0xE1 && c0 <= 0xEC && utf8_is_cont(s[1]) && utf8_is_cont(s[2]))
238
))
239
{
240
if (count != NULL) *count = 3;
241
return (((c0 & 0x0F) << 12) | ((unicode_t)(s[1] & 0x3F) << 6) | (s[2] & 0x3F));
242
}
243
// 4 bytes: reject overlong
244
else if (len >= 4 &&
245
(((c0 == 0xF0 && s[1] >= 0x90 && s[1] <= 0xBF && utf8_is_cont(s[2]) && utf8_is_cont(s[3])) ||
246
(c0 >= 0xF1 && c0 <= 0xF3 && utf8_is_cont(s[1]) && utf8_is_cont(s[2]) && utf8_is_cont(s[3])) ||
247
(c0 == 0xF4 && s[1] >= 0x80 && s[1] <= 0x8F && utf8_is_cont(s[2]) && utf8_is_cont(s[3])))
248
))
249
{
250
if (count != NULL) *count = 4;
251
return (((c0 & 0x07) << 18) | ((unicode_t)(s[1] & 0x3F) << 12) | ((unicode_t)(s[2] & 0x3F) << 6) | (s[3] & 0x3F));
252
}
253
fail:
254
if (count != NULL) *count = 1;
255
return unicode_from_raw(s[0]);
256
}
257
258
259
//-------------------------------------------------------------
260
// Debug
261
//-------------------------------------------------------------
262
263
#if defined(IC_NO_DEBUG_MSG)
264
// nothing
265
#elif !defined(IC_DEBUG_TO_FILE)
266
ic_private void debug_msg(const char* fmt, ...) {
267
if (getenv("ISOCLINE_DEBUG")) {
268
va_list args;
269
va_start(args, fmt);
270
vfprintf(stderr, fmt, args);
271
va_end(args);
272
}
273
}
274
#else
275
ic_private void debug_msg(const char* fmt, ...) {
276
static int debug_init;
277
static const char* debug_fname = "isocline.debug.txt";
278
// initialize?
279
if (debug_init==0) {
280
debug_init = -1;
281
const char* rdebug = getenv("ISOCLINE_DEBUG");
282
if (rdebug!=NULL && strcmp(rdebug,"1") == 0) {
283
FILE* fdbg = fopen(debug_fname, "w");
284
if (fdbg!=NULL) {
285
debug_init = 1;
286
fclose(fdbg);
287
}
288
}
289
}
290
if (debug_init <= 0) return;
291
292
// write debug messages
293
FILE* fdbg = fopen(debug_fname, "a");
294
if (fdbg==NULL) return;
295
va_list args;
296
va_start(args, fmt);
297
vfprintf(fdbg, fmt, args);
298
fclose(fdbg);
299
va_end(args);
300
}
301
#endif
302
303
304
//-------------------------------------------------------------
305
// Allocation
306
//-------------------------------------------------------------
307
308
ic_private void* mem_malloc(alloc_t* mem, ssize_t sz) {
309
return mem->malloc(to_size_t(sz));
310
}
311
312
ic_private void* mem_zalloc(alloc_t* mem, ssize_t sz) {
313
void* p = mem_malloc(mem, sz);
314
if (p != NULL) memset(p, 0, to_size_t(sz));
315
return p;
316
}
317
318
ic_private void* mem_realloc(alloc_t* mem, void* p, ssize_t newsz) {
319
return mem->realloc(p, to_size_t(newsz));
320
}
321
322
ic_private void mem_free(alloc_t* mem, const void* p) {
323
mem->free((void*)p);
324
}
325
326
ic_private char* mem_strdup(alloc_t* mem, const char* s) {
327
if (s==NULL) return NULL;
328
ssize_t n = ic_strlen(s);
329
char* p = mem_malloc_tp_n(mem, char, n+1);
330
if (p == NULL) return NULL;
331
ic_memcpy(p, s, n+1);
332
return p;
333
}
334
335
ic_private char* mem_strndup(alloc_t* mem, const char* s, ssize_t n) {
336
if (s==NULL || n < 0) return NULL;
337
char* p = mem_malloc_tp_n(mem, char, n+1);
338
if (p == NULL) return NULL;
339
ssize_t i;
340
for (i = 0; i < n && s[i] != 0; i++) {
341
p[i] = s[i];
342
}
343
assert(i <= n);
344
p[i] = 0;
345
return p;
346
}
347
348
349