@ohos-ports/bare-buffer 3.7.1-beta.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (155) hide show
  1. package/LICENSE +201 -0
  2. package/README.md +26 -0
  3. package/binding.c +1077 -0
  4. package/binding.gyp +32 -0
  5. package/binding.js +1 -0
  6. package/build/Release/bare_buffer.node +0 -0
  7. package/deps/libbase64/.clang-format +10 -0
  8. package/deps/libbase64/.gitattributes +1 -0
  9. package/deps/libbase64/.github/workflows/integrate.yml +45 -0
  10. package/deps/libbase64/.github/workflows/nightly.yml +28 -0
  11. package/deps/libbase64/.prettierrc +1 -0
  12. package/deps/libbase64/CMakeLists.txt +71 -0
  13. package/deps/libbase64/LICENSE +201 -0
  14. package/deps/libbase64/NOTICE +13 -0
  15. package/deps/libbase64/README.md +11 -0
  16. package/deps/libbase64/include/base64.h +323 -0
  17. package/deps/libbase64/package.json +25 -0
  18. package/deps/libbase64/src/base64.c +22 -0
  19. package/deps/libbase64/test/CMakeLists.txt +31 -0
  20. package/deps/libbase64/test/decode-invalid.c +35 -0
  21. package/deps/libbase64/test/decode-length.c +23 -0
  22. package/deps/libbase64/test/decode.c +36 -0
  23. package/deps/libbase64/test/encode-length.c +22 -0
  24. package/deps/libbase64/test/encode.c +42 -0
  25. package/deps/libbase64/test/fuzz/CMakeLists.txt +18 -0
  26. package/deps/libbase64/test/fuzz/decode/utf16le.c +53 -0
  27. package/deps/libbase64/test/fuzz/decode/utf8.c +47 -0
  28. package/deps/libbase64/test/fuzz/encode/utf16le.c +56 -0
  29. package/deps/libbase64/test/fuzz/encode/utf8.c +56 -0
  30. package/deps/libhex/.clang-format +10 -0
  31. package/deps/libhex/.gitattributes +1 -0
  32. package/deps/libhex/.github/workflows/integrate.yml +45 -0
  33. package/deps/libhex/.github/workflows/nightly.yml +28 -0
  34. package/deps/libhex/.prettierrc +1 -0
  35. package/deps/libhex/CMakeLists.txt +72 -0
  36. package/deps/libhex/LICENSE +201 -0
  37. package/deps/libhex/NOTICE +13 -0
  38. package/deps/libhex/README.md +11 -0
  39. package/deps/libhex/include/hex.h +163 -0
  40. package/deps/libhex/package.json +25 -0
  41. package/deps/libhex/src/hex.c +16 -0
  42. package/deps/libhex/test/CMakeLists.txt +31 -0
  43. package/deps/libhex/test/decode-invalid.c +37 -0
  44. package/deps/libhex/test/decode-length.c +23 -0
  45. package/deps/libhex/test/decode.c +25 -0
  46. package/deps/libhex/test/encode-length.c +22 -0
  47. package/deps/libhex/test/encode.c +25 -0
  48. package/deps/libhex/test/fuzz/CMakeLists.txt +18 -0
  49. package/deps/libhex/test/fuzz/decode/utf16le.c +53 -0
  50. package/deps/libhex/test/fuzz/decode/utf8.c +47 -0
  51. package/deps/libhex/test/fuzz/encode/utf16le.c +36 -0
  52. package/deps/libhex/test/fuzz/encode/utf8.c +36 -0
  53. package/deps/libutf/.clang-format +10 -0
  54. package/deps/libutf/.gitattributes +1 -0
  55. package/deps/libutf/.github/workflows/integrate.yml +45 -0
  56. package/deps/libutf/.github/workflows/nightly.yml +28 -0
  57. package/deps/libutf/.prettierrc +1 -0
  58. package/deps/libutf/CMakeLists.txt +105 -0
  59. package/deps/libutf/LICENSE +201 -0
  60. package/deps/libutf/NOTICE +13 -0
  61. package/deps/libutf/README.md +11 -0
  62. package/deps/libutf/include/utf/string.h +1655 -0
  63. package/deps/libutf/include/utf.h +132 -0
  64. package/deps/libutf/package.json +24 -0
  65. package/deps/libutf/src/ascii/validate.c +47 -0
  66. package/deps/libutf/src/endianness.c +19 -0
  67. package/deps/libutf/src/endianness.h +54 -0
  68. package/deps/libutf/src/latin1/convert-to-utf16.c +37 -0
  69. package/deps/libutf/src/latin1/convert-to-utf32.c +34 -0
  70. package/deps/libutf/src/latin1/convert-to-utf8.c +58 -0
  71. package/deps/libutf/src/latin1/length-from-utf16.c +26 -0
  72. package/deps/libutf/src/latin1/length-from-utf32.c +26 -0
  73. package/deps/libutf/src/latin1/length-from-utf8.c +34 -0
  74. package/deps/libutf/src/utf16/convert-to-latin1.c +41 -0
  75. package/deps/libutf/src/utf16/convert-to-utf32.c +56 -0
  76. package/deps/libutf/src/utf16/convert-to-utf8.c +80 -0
  77. package/deps/libutf/src/utf16/length-from-latin1.c +26 -0
  78. package/deps/libutf/src/utf16/length-from-utf32.c +33 -0
  79. package/deps/libutf/src/utf16/length-from-utf8.c +38 -0
  80. package/deps/libutf/src/utf16/validate.c +53 -0
  81. package/deps/libutf/src/utf32/convert-to-latin1.c +40 -0
  82. package/deps/libutf/src/utf32/convert-to-utf16.c +56 -0
  83. package/deps/libutf/src/utf32/convert-to-utf8.c +71 -0
  84. package/deps/libutf/src/utf32/length-from-latin1.c +26 -0
  85. package/deps/libutf/src/utf32/length-from-utf16.c +35 -0
  86. package/deps/libutf/src/utf32/length-from-utf8.c +35 -0
  87. package/deps/libutf/src/utf32/string.c +149 -0
  88. package/deps/libutf/src/utf32/validate.c +39 -0
  89. package/deps/libutf/src/utf8/convert-to-latin1.c +70 -0
  90. package/deps/libutf/src/utf8/convert-to-utf16.c +95 -0
  91. package/deps/libutf/src/utf8/convert-to-utf32.c +110 -0
  92. package/deps/libutf/src/utf8/length-from-latin1.c +32 -0
  93. package/deps/libutf/src/utf8/length-from-utf16.c +48 -0
  94. package/deps/libutf/src/utf8/length-from-utf32.c +35 -0
  95. package/deps/libutf/src/utf8/string.c +149 -0
  96. package/deps/libutf/src/utf8/validate.c +107 -0
  97. package/deps/libutf/test/CMakeLists.txt +56 -0
  98. package/deps/libutf/test/fuzz/CMakeLists.txt +26 -0
  99. package/deps/libutf/test/fuzz/corpus/.gitignore +2 -0
  100. package/deps/libutf/test/fuzz/crashes/.gitignore +2 -0
  101. package/deps/libutf/test/fuzz/latin1/convert-to-utf16.c +32 -0
  102. package/deps/libutf/test/fuzz/latin1/convert-to-utf32.c +32 -0
  103. package/deps/libutf/test/fuzz/latin1/convert-to-utf8.c +33 -0
  104. package/deps/libutf/test/fuzz/utf16/convert-to-latin1.c +36 -0
  105. package/deps/libutf/test/fuzz/utf16/convert-to-utf32.c +38 -0
  106. package/deps/libutf/test/fuzz/utf16/convert-to-utf8.c +38 -0
  107. package/deps/libutf/test/fuzz/utf32/convert-to-latin1.c +36 -0
  108. package/deps/libutf/test/fuzz/utf32/convert-to-utf16.c +38 -0
  109. package/deps/libutf/test/fuzz/utf32/convert-to-utf8.c +38 -0
  110. package/deps/libutf/test/fuzz/utf8/convert-to-latin1.c +33 -0
  111. package/deps/libutf/test/fuzz/utf8/convert-to-utf16.c +35 -0
  112. package/deps/libutf/test/fuzz/utf8/convert-to-utf32.c +35 -0
  113. package/deps/libutf/test/utf16/utf8-convert.c +45 -0
  114. package/deps/libutf/test/utf16/utf8-length.c +41 -0
  115. package/deps/libutf/test/utf16/validate-invalid.c +50 -0
  116. package/deps/libutf/test/utf16/validate.c +32 -0
  117. package/deps/libutf/test/utf32/string-append.c +74 -0
  118. package/deps/libutf/test/utf32/string-compare.c +108 -0
  119. package/deps/libutf/test/utf32/string-erase.c +79 -0
  120. package/deps/libutf/test/utf32/string-index.c +102 -0
  121. package/deps/libutf/test/utf32/string-insert.c +92 -0
  122. package/deps/libutf/test/utf32/string-last-index.c +71 -0
  123. package/deps/libutf/test/utf32/string-prepend.c +51 -0
  124. package/deps/libutf/test/utf32/string-replace.c +88 -0
  125. package/deps/libutf/test/utf32/string-reserve.c +99 -0
  126. package/deps/libutf/test/utf32/string-substring.c +93 -0
  127. package/deps/libutf/test/utf8/latin1-convert.c +23 -0
  128. package/deps/libutf/test/utf8/string-append.c +23 -0
  129. package/deps/libutf/test/utf8/string-compare.c +67 -0
  130. package/deps/libutf/test/utf8/string-erase.c +75 -0
  131. package/deps/libutf/test/utf8/string-index.c +99 -0
  132. package/deps/libutf/test/utf8/string-last-index.c +68 -0
  133. package/deps/libutf/test/utf8/string-prepend.c +23 -0
  134. package/deps/libutf/test/utf8/string-replace.c +74 -0
  135. package/deps/libutf/test/utf8/string-reserve.c +51 -0
  136. package/deps/libutf/test/utf8/string-substring.c +68 -0
  137. package/deps/libutf/test/utf8/utf16-convert.c +32 -0
  138. package/deps/libutf/test/utf8/utf16-length.c +29 -0
  139. package/deps/libutf/test/utf8/validate-invalid.c +26 -0
  140. package/deps/libutf/test/utf8/validate.c +21 -0
  141. package/global.d.ts +21 -0
  142. package/global.js +6 -0
  143. package/index.d.ts +769 -0
  144. package/index.js +1339 -0
  145. package/lib/ascii.js +36 -0
  146. package/lib/base64.js +25 -0
  147. package/lib/base64url.js +25 -0
  148. package/lib/checked.js +23 -0
  149. package/lib/constants.d.ts +7 -0
  150. package/lib/constants.js +3 -0
  151. package/lib/hex.js +20 -0
  152. package/lib/latin1.js +14 -0
  153. package/lib/utf16le.js +20 -0
  154. package/lib/utf8.js +18 -0
  155. package/package.json +64 -0
@@ -0,0 +1,1655 @@
1
+ #ifndef UTF_STRING_H
2
+ #define UTF_STRING_H
3
+
4
+ #ifdef __cplusplus
5
+ extern "C" {
6
+ #endif
7
+
8
+ #include <assert.h>
9
+ #include <stdbool.h>
10
+ #include <stddef.h>
11
+ #include <stdint.h>
12
+ #include <stdio.h>
13
+ #include <stdlib.h>
14
+ #include <string.h>
15
+
16
+ #include "../utf.h"
17
+
18
+ /**
19
+ * UTF-8
20
+ */
21
+
22
+ typedef struct utf8_string_s utf8_string_t;
23
+ typedef struct utf8_string_view_s utf8_string_view_t;
24
+
25
+ struct utf8_string_s {
26
+ utf8_t *data;
27
+ size_t len;
28
+ union {
29
+ size_t cap;
30
+ utf8_t buf[8];
31
+ };
32
+ };
33
+
34
+ struct utf8_string_view_s {
35
+ const utf8_t *data;
36
+ size_t len;
37
+ };
38
+
39
+ inline void
40
+ utf8_string_init(utf8_string_t *string) {
41
+ string->data = string->buf;
42
+ string->len = 0;
43
+ }
44
+
45
+ inline utf8_string_view_t
46
+ utf8_string_view_init(const utf8_t *data, size_t len) {
47
+ utf8_string_view_t view = {data, len};
48
+ return view;
49
+ }
50
+
51
+ inline void
52
+ utf8_string_destroy(utf8_string_t *string) {
53
+ if (string->data != string->buf) free(string->data);
54
+ }
55
+
56
+ inline int
57
+ utf8_string_reserve(utf8_string_t *string, size_t len) {
58
+ size_t cap = string->data == string->buf ? sizeof(string->buf) : string->cap;
59
+
60
+ if (len <= cap) return 0;
61
+
62
+ // Round up to next power of two; bail out if the rounding would overflow.
63
+ if (len > (SIZE_MAX >> 1) + 1) return -1;
64
+
65
+ // https://graphics.stanford.edu/~seander/bithacks.html#RoundUpPowerOf2
66
+ len--;
67
+ len |= len >> 1;
68
+ len |= len >> 2;
69
+ len |= len >> 4;
70
+ len |= len >> 8;
71
+ len |= len >> 16;
72
+ #if SIZE_MAX == UINT64_MAX
73
+ len |= len >> 32;
74
+ #endif
75
+ len++;
76
+
77
+ cap = len;
78
+
79
+ utf8_t *data;
80
+
81
+ if (string->data == string->buf) {
82
+ data = (utf8_t *) malloc(cap);
83
+
84
+ if (data == NULL) return -1;
85
+
86
+ memcpy(data, string->data, string->len);
87
+ } else {
88
+ data = (utf8_t *) realloc(string->data, cap);
89
+
90
+ if (data == NULL) return -1;
91
+ }
92
+
93
+ string->data = data;
94
+ string->cap = cap;
95
+
96
+ return 0;
97
+ }
98
+
99
+ inline int
100
+ utf8_string_shrink_to_fit(utf8_string_t *string) {
101
+ if (string->data == string->buf) return 0;
102
+
103
+ size_t cap = string->len;
104
+
105
+ if (cap <= sizeof(string->buf)) {
106
+ memcpy(string->buf, string->data, cap);
107
+
108
+ free(string->data);
109
+
110
+ string->data = string->buf;
111
+ } else {
112
+ utf8_t *data = (utf8_t *) realloc(string->data, cap);
113
+
114
+ if (data == NULL) return -1;
115
+
116
+ string->data = data;
117
+ string->cap = cap;
118
+ }
119
+
120
+ return 0;
121
+ }
122
+
123
+ inline utf8_string_view_t
124
+ utf8_string_view(const utf8_string_t *string) {
125
+ return utf8_string_view_init(string->data, string->len);
126
+ }
127
+
128
+ inline void
129
+ utf8_string_clear(utf8_string_t *string) {
130
+ string->len = 0;
131
+ }
132
+
133
+ inline bool
134
+ utf8_string_empty(const utf8_string_t *string) {
135
+ return string->len == 0;
136
+ }
137
+
138
+ inline bool
139
+ utf8_string_view_empty(const utf8_string_view_t view) {
140
+ return view.len == 0;
141
+ }
142
+
143
+ inline int
144
+ utf8_string_copy(const utf8_string_t *string, utf8_string_t *result) {
145
+ int err;
146
+
147
+ err = utf8_string_reserve(result, string->len);
148
+ if (err < 0) return err;
149
+
150
+ memcpy(result->data, string->data, string->len);
151
+
152
+ result->len = string->len;
153
+
154
+ return 0;
155
+ }
156
+
157
+ inline int
158
+ utf8_string_view_copy(const utf8_string_view_t view, utf8_string_t *result) {
159
+ int err;
160
+
161
+ err = utf8_string_reserve(result, view.len);
162
+ if (err < 0) return err;
163
+
164
+ memcpy(result->data, view.data, view.len);
165
+
166
+ result->len = view.len;
167
+
168
+ return 0;
169
+ }
170
+
171
+ inline int
172
+ utf8_string_append(utf8_string_t *string, const utf8_string_t *other) {
173
+ int err;
174
+
175
+ err = utf8_string_reserve(string, string->len + other->len);
176
+ if (err < 0) return -1;
177
+
178
+ memcpy(&string->data[string->len], other->data, other->len);
179
+
180
+ string->len += other->len;
181
+
182
+ return 0;
183
+ }
184
+
185
+ inline int
186
+ utf8_string_append_view(utf8_string_t *string, const utf8_string_view_t view) {
187
+ int err;
188
+
189
+ err = utf8_string_reserve(string, string->len + view.len);
190
+ if (err < 0) return -1;
191
+
192
+ memcpy(&string->data[string->len], view.data, view.len);
193
+
194
+ string->len += view.len;
195
+
196
+ return 0;
197
+ }
198
+
199
+ inline int
200
+ utf8_string_append_character(utf8_string_t *string, utf8_t c) {
201
+ int err;
202
+
203
+ err = utf8_string_reserve(string, string->len + 1);
204
+ if (err < 0) return -1;
205
+
206
+ string->data[string->len] = c;
207
+
208
+ string->len += 1;
209
+
210
+ return 0;
211
+ }
212
+
213
+ inline int
214
+ utf8_string_append_literal(utf8_string_t *string, const utf8_t *literal, size_t n) {
215
+ int err;
216
+
217
+ if (n == (size_t) -1) n = strlen((const char *) literal);
218
+
219
+ err = utf8_string_reserve(string, string->len + n);
220
+ if (err < 0) return -1;
221
+
222
+ memcpy(&string->data[string->len], literal, n);
223
+
224
+ string->len += n;
225
+
226
+ return 0;
227
+ }
228
+
229
+ inline int
230
+ utf8_string_prepend(utf8_string_t *string, const utf8_string_t *other) {
231
+ int err;
232
+
233
+ err = utf8_string_reserve(string, string->len + other->len);
234
+ if (err < 0) return -1;
235
+
236
+ memmove(&string->data[other->len], string->data, string->len);
237
+
238
+ memcpy(string->data, other->data, other->len);
239
+
240
+ string->len += other->len;
241
+
242
+ return 0;
243
+ }
244
+
245
+ inline int
246
+ utf8_string_prepend_view(utf8_string_t *string, const utf8_string_view_t view) {
247
+ int err;
248
+
249
+ err = utf8_string_reserve(string, string->len + view.len);
250
+ if (err < 0) return -1;
251
+
252
+ memmove(&string->data[view.len], string->data, string->len);
253
+
254
+ memcpy(string->data, view.data, view.len);
255
+
256
+ string->len += view.len;
257
+
258
+ return 0;
259
+ }
260
+
261
+ inline int
262
+ utf8_string_prepend_character(utf8_string_t *string, utf8_t c) {
263
+ int err;
264
+
265
+ err = utf8_string_reserve(string, string->len + 1);
266
+ if (err < 0) return -1;
267
+
268
+ memmove(&string->data[1], string->data, string->len);
269
+
270
+ string->data[0] = c;
271
+
272
+ string->len += 1;
273
+
274
+ return 0;
275
+ }
276
+
277
+ inline int
278
+ utf8_string_prepend_literal(utf8_string_t *string, const utf8_t *literal, size_t n) {
279
+ int err;
280
+
281
+ if (n == (size_t) -1) n = strlen((const char *) literal);
282
+
283
+ err = utf8_string_reserve(string, string->len + n);
284
+ if (err < 0) return -1;
285
+
286
+ memmove(&string->data[n], string->data, string->len);
287
+
288
+ memcpy(string->data, literal, n);
289
+
290
+ string->len += n;
291
+
292
+ return 0;
293
+ }
294
+
295
+ inline int
296
+ utf8_string_insert(utf8_string_t *string, size_t pos, const utf8_string_t *other) {
297
+ int err;
298
+
299
+ if (pos > string->len) return -1;
300
+
301
+ size_t inserted_len = string->len + other->len;
302
+
303
+ err = utf8_string_reserve(string, inserted_len);
304
+ if (err < 0) return err;
305
+
306
+ memmove(&string->data[pos + other->len], &string->data[pos], string->len - pos);
307
+
308
+ memcpy(&string->data[pos], other->data, other->len);
309
+
310
+ string->len = inserted_len;
311
+
312
+ return 0;
313
+ }
314
+
315
+ inline int
316
+ utf8_string_insert_view(utf8_string_t *string, size_t pos, const utf8_string_view_t other) {
317
+ int err;
318
+
319
+ if (pos > string->len) return -1;
320
+
321
+ size_t inserted_len = string->len + other.len;
322
+
323
+ err = utf8_string_reserve(string, inserted_len);
324
+ if (err < 0) return err;
325
+
326
+ memmove(&string->data[pos + other.len], &string->data[pos], string->len - pos);
327
+
328
+ memcpy(&string->data[pos], other.data, other.len);
329
+
330
+ string->len = inserted_len;
331
+
332
+ return 0;
333
+ }
334
+
335
+ inline int
336
+ utf8_string_insert_character(utf8_string_t *string, size_t pos, utf8_t c) {
337
+ int err;
338
+
339
+ if (pos > string->len) return -1;
340
+
341
+ size_t inserted_len = string->len + 1;
342
+
343
+ err = utf8_string_reserve(string, inserted_len);
344
+ if (err < 0) return err;
345
+
346
+ memmove(&string->data[pos + 1], &string->data[pos], string->len - pos);
347
+
348
+ string->data[pos] = c;
349
+
350
+ string->len = inserted_len;
351
+
352
+ return 0;
353
+ }
354
+
355
+ inline int
356
+ utf8_string_insert_literal(utf8_string_t *string, size_t pos, const utf8_t *literal, size_t n) {
357
+ int err;
358
+
359
+ if (pos > string->len) return -1;
360
+
361
+ if (n == (size_t) -1) n = strlen((const char *) literal);
362
+
363
+ size_t inserted_len = string->len + n;
364
+
365
+ err = utf8_string_reserve(string, inserted_len);
366
+ if (err < 0) return err;
367
+
368
+ memmove(&string->data[pos + n], &string->data[pos], string->len - pos);
369
+
370
+ memcpy(&string->data[pos], literal, n);
371
+
372
+ string->len = inserted_len;
373
+
374
+ return 0;
375
+ }
376
+
377
+ inline int
378
+ utf8_string_replace(utf8_string_t *string, size_t pos, size_t len, const utf8_string_t *replacement) {
379
+ int err;
380
+
381
+ if (pos > string->len) return -1;
382
+ if (len > string->len - pos) len = string->len - pos;
383
+
384
+ size_t replaced_len = string->len + replacement->len - len;
385
+
386
+ err = utf8_string_reserve(string, replaced_len);
387
+ if (err < 0) return err;
388
+
389
+ memmove(&string->data[pos + replacement->len], &string->data[pos + len], string->len - pos - len);
390
+
391
+ memcpy(&string->data[pos], replacement->data, replacement->len);
392
+
393
+ string->len = replaced_len;
394
+
395
+ return 0;
396
+ }
397
+
398
+ inline int
399
+ utf8_string_replace_view(utf8_string_t *string, size_t pos, size_t len, const utf8_string_view_t replacement) {
400
+ int err;
401
+
402
+ if (pos > string->len) return -1;
403
+ if (len > string->len - pos) len = string->len - pos;
404
+
405
+ size_t replaced_len = string->len + replacement.len - len;
406
+
407
+ err = utf8_string_reserve(string, replaced_len);
408
+ if (err < 0) return err;
409
+
410
+ memmove(&string->data[pos + replacement.len], &string->data[pos + len], string->len - pos - len);
411
+
412
+ memcpy(&string->data[pos], replacement.data, replacement.len);
413
+
414
+ string->len = replaced_len;
415
+
416
+ return 0;
417
+ }
418
+
419
+ inline int
420
+ utf8_string_replace_character(utf8_string_t *string, size_t pos, size_t len, utf8_t c) {
421
+ int err;
422
+
423
+ if (pos > string->len) return -1;
424
+ if (len > string->len - pos) len = string->len - pos;
425
+
426
+ size_t replaced_len = string->len + 1 - len;
427
+
428
+ err = utf8_string_reserve(string, replaced_len);
429
+ if (err < 0) return err;
430
+
431
+ memmove(&string->data[pos + 1], &string->data[pos + len], string->len - pos - len);
432
+
433
+ string->data[pos] = c;
434
+
435
+ string->len = replaced_len;
436
+
437
+ return 0;
438
+ }
439
+
440
+ inline int
441
+ utf8_string_replace_literal(utf8_string_t *string, size_t pos, size_t len, const utf8_t *literal, size_t n) {
442
+ int err;
443
+
444
+ if (pos > string->len) return -1;
445
+ if (len > string->len - pos) len = string->len - pos;
446
+
447
+ if (n == (size_t) -1) n = strlen((const char *) literal);
448
+
449
+ size_t replaced_len = string->len + n - len;
450
+
451
+ err = utf8_string_reserve(string, replaced_len);
452
+ if (err < 0) return err;
453
+
454
+ memmove(&string->data[pos + n], &string->data[pos + len], string->len - pos - len);
455
+
456
+ memcpy(&string->data[pos], literal, n);
457
+
458
+ string->len = replaced_len;
459
+
460
+ return 0;
461
+ }
462
+
463
+ inline int
464
+ utf8_string_erase(utf8_string_t *string, size_t pos, size_t len) {
465
+ if (pos > string->len) return -1;
466
+ if (len > string->len - pos) len = string->len - pos;
467
+
468
+ memmove(&string->data[pos], &string->data[pos + len], string->len - pos - len);
469
+
470
+ string->len -= len;
471
+
472
+ return 0;
473
+ }
474
+
475
+ inline int
476
+ utf8_string_concat(const utf8_string_t *string, const utf8_string_t *other, utf8_string_t *result) {
477
+ int err;
478
+
479
+ utf8_string_init(result);
480
+
481
+ err = utf8_string_reserve(result, string->len + other->len);
482
+ if (err < 0) return err;
483
+
484
+ err = utf8_string_append(result, string);
485
+ assert(err == 0);
486
+
487
+ err = utf8_string_append(result, other);
488
+ assert(err == 0);
489
+
490
+ return 0;
491
+ }
492
+
493
+ inline int
494
+ utf8_string_view_concat(const utf8_string_view_t view, const utf8_string_t *other, utf8_string_t *result) {
495
+ int err;
496
+
497
+ utf8_string_init(result);
498
+
499
+ err = utf8_string_reserve(result, view.len + other->len);
500
+ if (err < 0) return err;
501
+
502
+ err = utf8_string_append_view(result, view);
503
+ assert(err == 0);
504
+
505
+ err = utf8_string_append(result, other);
506
+ assert(err == 0);
507
+
508
+ return 0;
509
+ }
510
+
511
+ inline int
512
+ utf8_string_concat_view(const utf8_string_t *string, const utf8_string_view_t other, utf8_string_t *result) {
513
+ int err;
514
+
515
+ utf8_string_init(result);
516
+
517
+ err = utf8_string_reserve(result, string->len + other.len);
518
+ if (err < 0) return err;
519
+
520
+ err = utf8_string_append(result, string);
521
+ assert(err == 0);
522
+
523
+ err = utf8_string_append_view(result, other);
524
+ assert(err == 0);
525
+
526
+ return 0;
527
+ }
528
+
529
+ inline int
530
+ utf8_string_view_concat_view(const utf8_string_view_t view, const utf8_string_view_t other, utf8_string_t *result) {
531
+ int err;
532
+
533
+ utf8_string_init(result);
534
+
535
+ err = utf8_string_reserve(result, view.len + other.len);
536
+ if (err < 0) return err;
537
+
538
+ err = utf8_string_append_view(result, view);
539
+ assert(err == 0);
540
+
541
+ err = utf8_string_append_view(result, other);
542
+ assert(err == 0);
543
+
544
+ return 0;
545
+ }
546
+
547
+ inline int
548
+ utf8_string_concat_character(const utf8_string_t *string, utf8_t c, utf8_string_t *result) {
549
+ int err;
550
+
551
+ utf8_string_init(result);
552
+
553
+ err = utf8_string_reserve(result, string->len + 1);
554
+ if (err < 0) return err;
555
+
556
+ err = utf8_string_append(result, string);
557
+ assert(err == 0);
558
+
559
+ err = utf8_string_append_character(result, c);
560
+ assert(err == 0);
561
+
562
+ return 0;
563
+ }
564
+
565
+ inline int
566
+ utf8_string_view_concat_character(const utf8_string_view_t view, utf8_t c, utf8_string_t *result) {
567
+ int err;
568
+
569
+ utf8_string_init(result);
570
+
571
+ err = utf8_string_reserve(result, view.len + 1);
572
+ if (err < 0) return err;
573
+
574
+ err = utf8_string_append_view(result, view);
575
+ assert(err == 0);
576
+
577
+ err = utf8_string_append_character(result, c);
578
+ assert(err == 0);
579
+
580
+ return 0;
581
+ }
582
+
583
+ inline int
584
+ utf8_string_concat_literal(const utf8_string_t *string, const utf8_t *literal, size_t n, utf8_string_t *result) {
585
+ int err;
586
+
587
+ utf8_string_init(result);
588
+
589
+ err = utf8_string_reserve(result, string->len + n);
590
+ if (err < 0) return err;
591
+
592
+ err = utf8_string_append(result, string);
593
+ assert(err == 0);
594
+
595
+ err = utf8_string_append_literal(result, literal, n);
596
+ assert(err == 0);
597
+
598
+ return 0;
599
+ }
600
+
601
+ inline int
602
+ utf8_string_view_concat_literal(const utf8_string_view_t view, const utf8_t *literal, size_t n, utf8_string_t *result) {
603
+ int err;
604
+
605
+ utf8_string_init(result);
606
+
607
+ err = utf8_string_reserve(result, view.len + n);
608
+ if (err < 0) return err;
609
+
610
+ err = utf8_string_append_view(result, view);
611
+ assert(err == 0);
612
+
613
+ err = utf8_string_append_literal(result, literal, n);
614
+ assert(err == 0);
615
+
616
+ return 0;
617
+ }
618
+
619
+ inline int
620
+ utf8_string_compare(const utf8_string_t *string, const utf8_string_t *other) {
621
+ size_t a_len = string->len;
622
+ size_t b_len = other->len;
623
+
624
+ // The shorter of the two lengths, over which the contents are compared. The
625
+ // comparison is one of bytes rather than of C strings, a length delimited
626
+ // string being free to hold a null byte.
627
+ size_t len = a_len < b_len ? a_len : b_len;
628
+
629
+ int result = len == 0 ? 0 : memcmp(string->data, other->data, len);
630
+
631
+ if (result == 0) return a_len < b_len
632
+ ? -1
633
+ : a_len > b_len ? 1
634
+ : 0;
635
+
636
+ return result;
637
+ }
638
+
639
+ inline int
640
+ utf8_string_view_compare(const utf8_string_view_t view, const utf8_string_view_t other) {
641
+ size_t a_len = view.len;
642
+ size_t b_len = other.len;
643
+
644
+ // The shorter of the two lengths, over which the contents are compared. The
645
+ // comparison is one of bytes rather than of C strings, a length delimited
646
+ // string being free to hold a null byte.
647
+ size_t len = a_len < b_len ? a_len : b_len;
648
+
649
+ int result = len == 0 ? 0 : memcmp(view.data, other.data, len);
650
+
651
+ if (result == 0) return a_len < b_len
652
+ ? -1
653
+ : a_len > b_len ? 1
654
+ : 0;
655
+
656
+ return result;
657
+ }
658
+
659
+ inline int
660
+ utf8_string_compare_literal(const utf8_string_t *string, const utf8_t *literal, size_t n) {
661
+ if (n == (size_t) -1) n = strlen((const char *) literal);
662
+
663
+ size_t a_len = string->len;
664
+ size_t b_len = n;
665
+
666
+ // The shorter of the two lengths, over which the contents are compared. The
667
+ // comparison is one of bytes rather than of C strings, a length delimited
668
+ // string being free to hold a null byte.
669
+ size_t len = a_len < b_len ? a_len : b_len;
670
+
671
+ int result = len == 0 ? 0 : memcmp(string->data, literal, len);
672
+
673
+ if (result == 0) return a_len < b_len
674
+ ? -1
675
+ : a_len > b_len ? 1
676
+ : 0;
677
+
678
+ return result;
679
+ }
680
+
681
+ inline int
682
+ utf8_string_view_compare_literal(const utf8_string_view_t view, const utf8_t *literal, size_t n) {
683
+ if (n == (size_t) -1) n = strlen((const char *) literal);
684
+
685
+ size_t a_len = view.len;
686
+ size_t b_len = n;
687
+
688
+ // The shorter of the two lengths, over which the contents are compared. The
689
+ // comparison is one of bytes rather than of C strings, a length delimited
690
+ // string being free to hold a null byte.
691
+ size_t len = a_len < b_len ? a_len : b_len;
692
+
693
+ int result = len == 0 ? 0 : memcmp(view.data, literal, len);
694
+
695
+ if (result == 0) return a_len < b_len
696
+ ? -1
697
+ : a_len > b_len ? 1
698
+ : 0;
699
+
700
+ return result;
701
+ }
702
+
703
+ inline utf8_string_view_t
704
+ utf8_string_substring(const utf8_string_t *string, size_t start, size_t end) {
705
+ if (end == (size_t) -1 || end > string->len) end = string->len;
706
+ if (start > end) start = end;
707
+
708
+ return utf8_string_view_init(&string->data[start], end - start);
709
+ }
710
+
711
+ inline utf8_string_view_t
712
+ utf8_string_view_substring(const utf8_string_view_t view, size_t start, size_t end) {
713
+ if (end == (size_t) -1 || end > view.len) end = view.len;
714
+ if (start > end) start = end;
715
+
716
+ return utf8_string_view_init(&view.data[start], end - start);
717
+ }
718
+
719
+ inline int
720
+ utf8_string_substring_copy(const utf8_string_t *string, size_t start, size_t end, utf8_string_t *result) {
721
+ int err;
722
+
723
+ if (end == (size_t) -1 || end > string->len) end = string->len;
724
+ if (start > end) start = end;
725
+
726
+ size_t len = end - start;
727
+
728
+ err = utf8_string_reserve(result, len);
729
+ if (err < 0) return -1;
730
+
731
+ memcpy(result->data, &string->data[start], len);
732
+
733
+ result->len = len;
734
+
735
+ return 0;
736
+ }
737
+
738
+ inline int
739
+ utf8_string_view_substring_copy(const utf8_string_view_t view, size_t start, size_t end, utf8_string_t *result) {
740
+ int err;
741
+
742
+ if (end == (size_t) -1 || end > view.len) end = view.len;
743
+ if (start > end) start = end;
744
+
745
+ size_t len = end - start;
746
+
747
+ err = utf8_string_reserve(result, len);
748
+ if (err < 0) return -1;
749
+
750
+ memcpy(result->data, &view.data[start], len);
751
+
752
+ result->len = len;
753
+
754
+ return 0;
755
+ }
756
+
757
+ inline size_t
758
+ utf8_string_index_of_character(const utf8_string_t *string, size_t pos, utf8_t c) {
759
+ // Also catches a pos of (size_t) -1, which must not be turned into a length.
760
+ if (pos >= string->len) return (size_t) -1;
761
+
762
+ const utf8_t *found = (const utf8_t *) memchr(&string->data[pos], c, string->len - pos);
763
+
764
+ return found == NULL ? (size_t) -1 : (size_t) (found - string->data);
765
+ }
766
+
767
+ inline size_t
768
+ utf8_string_view_index_of_character(const utf8_string_view_t view, size_t pos, utf8_t c) {
769
+ // Also catches a pos of (size_t) -1, which must not be turned into a length.
770
+ if (pos >= view.len) return (size_t) -1;
771
+
772
+ const utf8_t *found = (const utf8_t *) memchr(&view.data[pos], c, view.len - pos);
773
+
774
+ return found == NULL ? (size_t) -1 : (size_t) (found - view.data);
775
+ }
776
+
777
+ inline size_t
778
+ utf8_string_last_index_of_character(const utf8_string_t *string, size_t pos, utf8_t c) {
779
+ if (string->len == 0) return (size_t) -1;
780
+ if (pos == (size_t) -1) pos = string->len - 1;
781
+ else if (pos >= string->len) return (size_t) -1;
782
+
783
+ for (size_t i = pos; i <= pos; i--) {
784
+ if (string->data[i] == c) {
785
+ return i;
786
+ }
787
+ }
788
+
789
+ return (size_t) -1;
790
+ }
791
+
792
+ inline size_t
793
+ utf8_string_view_last_index_of_character(const utf8_string_view_t view, size_t pos, utf8_t c) {
794
+ if (view.len == 0) return (size_t) -1;
795
+ if (pos == (size_t) -1) pos = view.len - 1;
796
+ else if (pos >= view.len) return (size_t) -1;
797
+
798
+ for (size_t i = pos; i <= pos; i--) {
799
+ if (view.data[i] == c) {
800
+ return i;
801
+ }
802
+ }
803
+
804
+ return (size_t) -1;
805
+ }
806
+
807
+ /**
808
+ * UTF-32
809
+ */
810
+
811
+ typedef struct utf32_string_s utf32_string_t;
812
+ typedef struct utf32_string_view_s utf32_string_view_t;
813
+
814
+ /**
815
+ * The number of code points that the inline buffer of a string holds. Unlike
816
+ * for UTF-8, where the two coincide, the capacity of a string counts code
817
+ * points rather than the bytes that they occupy.
818
+ *
819
+ * A code point takes four times the room of a UTF-8 code unit, so a buffer of
820
+ * the same length as that of `utf8_string_t` would grow the string by more than
821
+ * it tends to save in allocations. This is kept short enough that a string
822
+ * remains cheap to hold an array of, on the understanding that a caller who
823
+ * knows how much it needs is better served by reserving that upfront.
824
+ */
825
+ #define UTF32_STRING_INLINE_CAPACITY 8
826
+
827
+ struct utf32_string_s {
828
+ utf32_t *data;
829
+ size_t len;
830
+ union {
831
+ size_t cap;
832
+ utf32_t buf[UTF32_STRING_INLINE_CAPACITY];
833
+ };
834
+ };
835
+
836
+ struct utf32_string_view_s {
837
+ const utf32_t *data;
838
+ size_t len;
839
+ };
840
+
841
+ /**
842
+ * Returns the length of a null terminated sequence of code points. This stands
843
+ * in for the `strlen` that the UTF-8 string uses, there being no equivalent for
844
+ * code points in the standard library.
845
+ */
846
+ static inline size_t
847
+ utf32__string_literal_length(const utf32_t *literal) {
848
+ size_t len = 0;
849
+
850
+ while (literal[len] != 0) {
851
+ len++;
852
+ }
853
+
854
+ return len;
855
+ }
856
+
857
+ inline void
858
+ utf32_string_init(utf32_string_t *string) {
859
+ string->data = string->buf;
860
+ string->len = 0;
861
+ }
862
+
863
+ inline utf32_string_view_t
864
+ utf32_string_view_init(const utf32_t *data, size_t len) {
865
+ utf32_string_view_t view = {data, len};
866
+ return view;
867
+ }
868
+
869
+ inline void
870
+ utf32_string_destroy(utf32_string_t *string) {
871
+ if (string->data != string->buf) free(string->data);
872
+ }
873
+
874
+ inline int
875
+ utf32_string_reserve(utf32_string_t *string, size_t len) {
876
+ size_t cap = string->data == string->buf ? UTF32_STRING_INLINE_CAPACITY : string->cap;
877
+
878
+ if (len <= cap) return 0;
879
+
880
+ // Round up to next power of two; bail out if the rounding would overflow.
881
+ if (len > (SIZE_MAX >> 1) + 1) return -1;
882
+
883
+ // https://graphics.stanford.edu/~seander/bithacks.html#RoundUpPowerOf2
884
+ len--;
885
+ len |= len >> 1;
886
+ len |= len >> 2;
887
+ len |= len >> 4;
888
+ len |= len >> 8;
889
+ len |= len >> 16;
890
+ #if SIZE_MAX == UINT64_MAX
891
+ len |= len >> 32;
892
+ #endif
893
+ len++;
894
+
895
+ cap = len;
896
+
897
+ // The capacity counts code points, and so must also fit once scaled to the
898
+ // number of bytes that they occupy.
899
+ if (cap > SIZE_MAX / sizeof(utf32_t)) return -1;
900
+
901
+ utf32_t *data;
902
+
903
+ if (string->data == string->buf) {
904
+ data = (utf32_t *) malloc(cap * sizeof(utf32_t));
905
+
906
+ if (data == NULL) return -1;
907
+
908
+ memcpy(data, string->data, string->len * sizeof(utf32_t));
909
+ } else {
910
+ data = (utf32_t *) realloc(string->data, cap * sizeof(utf32_t));
911
+
912
+ if (data == NULL) return -1;
913
+ }
914
+
915
+ string->data = data;
916
+ string->cap = cap;
917
+
918
+ return 0;
919
+ }
920
+
921
+ inline int
922
+ utf32_string_shrink_to_fit(utf32_string_t *string) {
923
+ if (string->data == string->buf) return 0;
924
+
925
+ size_t cap = string->len;
926
+
927
+ if (cap <= UTF32_STRING_INLINE_CAPACITY) {
928
+ memcpy(string->buf, string->data, cap * sizeof(utf32_t));
929
+
930
+ free(string->data);
931
+
932
+ string->data = string->buf;
933
+ } else {
934
+ utf32_t *data = (utf32_t *) realloc(string->data, cap * sizeof(utf32_t));
935
+
936
+ if (data == NULL) return -1;
937
+
938
+ string->data = data;
939
+ string->cap = cap;
940
+ }
941
+
942
+ return 0;
943
+ }
944
+
945
+ inline utf32_string_view_t
946
+ utf32_string_view(const utf32_string_t *string) {
947
+ return utf32_string_view_init(string->data, string->len);
948
+ }
949
+
950
+ inline void
951
+ utf32_string_clear(utf32_string_t *string) {
952
+ string->len = 0;
953
+ }
954
+
955
+ inline bool
956
+ utf32_string_empty(const utf32_string_t *string) {
957
+ return string->len == 0;
958
+ }
959
+
960
+ inline bool
961
+ utf32_string_view_empty(const utf32_string_view_t view) {
962
+ return view.len == 0;
963
+ }
964
+
965
+ inline int
966
+ utf32_string_copy(const utf32_string_t *string, utf32_string_t *result) {
967
+ int err;
968
+
969
+ err = utf32_string_reserve(result, string->len);
970
+ if (err < 0) return err;
971
+
972
+ memcpy(result->data, string->data, string->len * sizeof(utf32_t));
973
+
974
+ result->len = string->len;
975
+
976
+ return 0;
977
+ }
978
+
979
+ inline int
980
+ utf32_string_view_copy(const utf32_string_view_t view, utf32_string_t *result) {
981
+ int err;
982
+
983
+ err = utf32_string_reserve(result, view.len);
984
+ if (err < 0) return err;
985
+
986
+ memcpy(result->data, view.data, view.len * sizeof(utf32_t));
987
+
988
+ result->len = view.len;
989
+
990
+ return 0;
991
+ }
992
+
993
+ inline int
994
+ utf32_string_append(utf32_string_t *string, const utf32_string_t *other) {
995
+ int err;
996
+
997
+ err = utf32_string_reserve(string, string->len + other->len);
998
+ if (err < 0) return -1;
999
+
1000
+ memcpy(&string->data[string->len], other->data, other->len * sizeof(utf32_t));
1001
+
1002
+ string->len += other->len;
1003
+
1004
+ return 0;
1005
+ }
1006
+
1007
+ inline int
1008
+ utf32_string_append_view(utf32_string_t *string, const utf32_string_view_t view) {
1009
+ int err;
1010
+
1011
+ err = utf32_string_reserve(string, string->len + view.len);
1012
+ if (err < 0) return -1;
1013
+
1014
+ memcpy(&string->data[string->len], view.data, view.len * sizeof(utf32_t));
1015
+
1016
+ string->len += view.len;
1017
+
1018
+ return 0;
1019
+ }
1020
+
1021
+ inline int
1022
+ utf32_string_append_character(utf32_string_t *string, utf32_t c) {
1023
+ int err;
1024
+
1025
+ err = utf32_string_reserve(string, string->len + 1);
1026
+ if (err < 0) return -1;
1027
+
1028
+ string->data[string->len] = c;
1029
+
1030
+ string->len += 1;
1031
+
1032
+ return 0;
1033
+ }
1034
+
1035
+ inline int
1036
+ utf32_string_append_literal(utf32_string_t *string, const utf32_t *literal, size_t n) {
1037
+ int err;
1038
+
1039
+ if (n == (size_t) -1) n = utf32__string_literal_length(literal);
1040
+
1041
+ err = utf32_string_reserve(string, string->len + n);
1042
+ if (err < 0) return -1;
1043
+
1044
+ memcpy(&string->data[string->len], literal, n * sizeof(utf32_t));
1045
+
1046
+ string->len += n;
1047
+
1048
+ return 0;
1049
+ }
1050
+
1051
+ inline int
1052
+ utf32_string_prepend(utf32_string_t *string, const utf32_string_t *other) {
1053
+ int err;
1054
+
1055
+ err = utf32_string_reserve(string, string->len + other->len);
1056
+ if (err < 0) return -1;
1057
+
1058
+ memmove(&string->data[other->len], string->data, string->len * sizeof(utf32_t));
1059
+
1060
+ memcpy(string->data, other->data, other->len * sizeof(utf32_t));
1061
+
1062
+ string->len += other->len;
1063
+
1064
+ return 0;
1065
+ }
1066
+
1067
+ inline int
1068
+ utf32_string_prepend_view(utf32_string_t *string, const utf32_string_view_t view) {
1069
+ int err;
1070
+
1071
+ err = utf32_string_reserve(string, string->len + view.len);
1072
+ if (err < 0) return -1;
1073
+
1074
+ memmove(&string->data[view.len], string->data, string->len * sizeof(utf32_t));
1075
+
1076
+ memcpy(string->data, view.data, view.len * sizeof(utf32_t));
1077
+
1078
+ string->len += view.len;
1079
+
1080
+ return 0;
1081
+ }
1082
+
1083
+ inline int
1084
+ utf32_string_prepend_character(utf32_string_t *string, utf32_t c) {
1085
+ int err;
1086
+
1087
+ err = utf32_string_reserve(string, string->len + 1);
1088
+ if (err < 0) return -1;
1089
+
1090
+ memmove(&string->data[1], string->data, string->len * sizeof(utf32_t));
1091
+
1092
+ string->data[0] = c;
1093
+
1094
+ string->len += 1;
1095
+
1096
+ return 0;
1097
+ }
1098
+
1099
+ inline int
1100
+ utf32_string_prepend_literal(utf32_string_t *string, const utf32_t *literal, size_t n) {
1101
+ int err;
1102
+
1103
+ if (n == (size_t) -1) n = utf32__string_literal_length(literal);
1104
+
1105
+ err = utf32_string_reserve(string, string->len + n);
1106
+ if (err < 0) return -1;
1107
+
1108
+ memmove(&string->data[n], string->data, string->len * sizeof(utf32_t));
1109
+
1110
+ memcpy(string->data, literal, n * sizeof(utf32_t));
1111
+
1112
+ string->len += n;
1113
+
1114
+ return 0;
1115
+ }
1116
+
1117
+ inline int
1118
+ utf32_string_insert(utf32_string_t *string, size_t pos, const utf32_string_t *other) {
1119
+ int err;
1120
+
1121
+ if (pos > string->len) return -1;
1122
+
1123
+ size_t inserted_len = string->len + other->len;
1124
+
1125
+ err = utf32_string_reserve(string, inserted_len);
1126
+ if (err < 0) return err;
1127
+
1128
+ memmove(&string->data[pos + other->len], &string->data[pos], (string->len - pos) * sizeof(utf32_t));
1129
+
1130
+ memcpy(&string->data[pos], other->data, other->len * sizeof(utf32_t));
1131
+
1132
+ string->len = inserted_len;
1133
+
1134
+ return 0;
1135
+ }
1136
+
1137
+ inline int
1138
+ utf32_string_insert_view(utf32_string_t *string, size_t pos, const utf32_string_view_t other) {
1139
+ int err;
1140
+
1141
+ if (pos > string->len) return -1;
1142
+
1143
+ size_t inserted_len = string->len + other.len;
1144
+
1145
+ err = utf32_string_reserve(string, inserted_len);
1146
+ if (err < 0) return err;
1147
+
1148
+ memmove(&string->data[pos + other.len], &string->data[pos], (string->len - pos) * sizeof(utf32_t));
1149
+
1150
+ memcpy(&string->data[pos], other.data, other.len * sizeof(utf32_t));
1151
+
1152
+ string->len = inserted_len;
1153
+
1154
+ return 0;
1155
+ }
1156
+
1157
+ inline int
1158
+ utf32_string_insert_character(utf32_string_t *string, size_t pos, utf32_t c) {
1159
+ int err;
1160
+
1161
+ if (pos > string->len) return -1;
1162
+
1163
+ size_t inserted_len = string->len + 1;
1164
+
1165
+ err = utf32_string_reserve(string, inserted_len);
1166
+ if (err < 0) return err;
1167
+
1168
+ memmove(&string->data[pos + 1], &string->data[pos], (string->len - pos) * sizeof(utf32_t));
1169
+
1170
+ string->data[pos] = c;
1171
+
1172
+ string->len = inserted_len;
1173
+
1174
+ return 0;
1175
+ }
1176
+
1177
+ inline int
1178
+ utf32_string_insert_literal(utf32_string_t *string, size_t pos, const utf32_t *literal, size_t n) {
1179
+ int err;
1180
+
1181
+ if (pos > string->len) return -1;
1182
+
1183
+ if (n == (size_t) -1) n = utf32__string_literal_length(literal);
1184
+
1185
+ size_t inserted_len = string->len + n;
1186
+
1187
+ err = utf32_string_reserve(string, inserted_len);
1188
+ if (err < 0) return err;
1189
+
1190
+ memmove(&string->data[pos + n], &string->data[pos], (string->len - pos) * sizeof(utf32_t));
1191
+
1192
+ memcpy(&string->data[pos], literal, n * sizeof(utf32_t));
1193
+
1194
+ string->len = inserted_len;
1195
+
1196
+ return 0;
1197
+ }
1198
+
1199
+ inline int
1200
+ utf32_string_replace(utf32_string_t *string, size_t pos, size_t len, const utf32_string_t *replacement) {
1201
+ int err;
1202
+
1203
+ if (pos > string->len) return -1;
1204
+ if (len > string->len - pos) len = string->len - pos;
1205
+
1206
+ size_t replaced_len = string->len + replacement->len - len;
1207
+
1208
+ err = utf32_string_reserve(string, replaced_len);
1209
+ if (err < 0) return err;
1210
+
1211
+ memmove(&string->data[pos + replacement->len], &string->data[pos + len], (string->len - pos - len) * sizeof(utf32_t));
1212
+
1213
+ memcpy(&string->data[pos], replacement->data, replacement->len * sizeof(utf32_t));
1214
+
1215
+ string->len = replaced_len;
1216
+
1217
+ return 0;
1218
+ }
1219
+
1220
+ inline int
1221
+ utf32_string_replace_view(utf32_string_t *string, size_t pos, size_t len, const utf32_string_view_t replacement) {
1222
+ int err;
1223
+
1224
+ if (pos > string->len) return -1;
1225
+ if (len > string->len - pos) len = string->len - pos;
1226
+
1227
+ size_t replaced_len = string->len + replacement.len - len;
1228
+
1229
+ err = utf32_string_reserve(string, replaced_len);
1230
+ if (err < 0) return err;
1231
+
1232
+ memmove(&string->data[pos + replacement.len], &string->data[pos + len], (string->len - pos - len) * sizeof(utf32_t));
1233
+
1234
+ memcpy(&string->data[pos], replacement.data, replacement.len * sizeof(utf32_t));
1235
+
1236
+ string->len = replaced_len;
1237
+
1238
+ return 0;
1239
+ }
1240
+
1241
+ inline int
1242
+ utf32_string_replace_character(utf32_string_t *string, size_t pos, size_t len, utf32_t c) {
1243
+ int err;
1244
+
1245
+ if (pos > string->len) return -1;
1246
+ if (len > string->len - pos) len = string->len - pos;
1247
+
1248
+ size_t replaced_len = string->len + 1 - len;
1249
+
1250
+ err = utf32_string_reserve(string, replaced_len);
1251
+ if (err < 0) return err;
1252
+
1253
+ memmove(&string->data[pos + 1], &string->data[pos + len], (string->len - pos - len) * sizeof(utf32_t));
1254
+
1255
+ string->data[pos] = c;
1256
+
1257
+ string->len = replaced_len;
1258
+
1259
+ return 0;
1260
+ }
1261
+
1262
+ inline int
1263
+ utf32_string_replace_literal(utf32_string_t *string, size_t pos, size_t len, const utf32_t *literal, size_t n) {
1264
+ int err;
1265
+
1266
+ if (pos > string->len) return -1;
1267
+ if (len > string->len - pos) len = string->len - pos;
1268
+
1269
+ if (n == (size_t) -1) n = utf32__string_literal_length(literal);
1270
+
1271
+ size_t replaced_len = string->len + n - len;
1272
+
1273
+ err = utf32_string_reserve(string, replaced_len);
1274
+ if (err < 0) return err;
1275
+
1276
+ memmove(&string->data[pos + n], &string->data[pos + len], (string->len - pos - len) * sizeof(utf32_t));
1277
+
1278
+ memcpy(&string->data[pos], literal, n * sizeof(utf32_t));
1279
+
1280
+ string->len = replaced_len;
1281
+
1282
+ return 0;
1283
+ }
1284
+
1285
+ inline int
1286
+ utf32_string_erase(utf32_string_t *string, size_t pos, size_t len) {
1287
+ if (pos > string->len) return -1;
1288
+ if (len > string->len - pos) len = string->len - pos;
1289
+
1290
+ memmove(&string->data[pos], &string->data[pos + len], (string->len - pos - len) * sizeof(utf32_t));
1291
+
1292
+ string->len -= len;
1293
+
1294
+ return 0;
1295
+ }
1296
+
1297
+ inline int
1298
+ utf32_string_concat(const utf32_string_t *string, const utf32_string_t *other, utf32_string_t *result) {
1299
+ int err;
1300
+
1301
+ utf32_string_init(result);
1302
+
1303
+ err = utf32_string_reserve(result, string->len + other->len);
1304
+ if (err < 0) return err;
1305
+
1306
+ err = utf32_string_append(result, string);
1307
+ assert(err == 0);
1308
+
1309
+ err = utf32_string_append(result, other);
1310
+ assert(err == 0);
1311
+
1312
+ return 0;
1313
+ }
1314
+
1315
+ inline int
1316
+ utf32_string_view_concat(const utf32_string_view_t view, const utf32_string_t *other, utf32_string_t *result) {
1317
+ int err;
1318
+
1319
+ utf32_string_init(result);
1320
+
1321
+ err = utf32_string_reserve(result, view.len + other->len);
1322
+ if (err < 0) return err;
1323
+
1324
+ err = utf32_string_append_view(result, view);
1325
+ assert(err == 0);
1326
+
1327
+ err = utf32_string_append(result, other);
1328
+ assert(err == 0);
1329
+
1330
+ return 0;
1331
+ }
1332
+
1333
+ inline int
1334
+ utf32_string_concat_view(const utf32_string_t *string, const utf32_string_view_t other, utf32_string_t *result) {
1335
+ int err;
1336
+
1337
+ utf32_string_init(result);
1338
+
1339
+ err = utf32_string_reserve(result, string->len + other.len);
1340
+ if (err < 0) return err;
1341
+
1342
+ err = utf32_string_append(result, string);
1343
+ assert(err == 0);
1344
+
1345
+ err = utf32_string_append_view(result, other);
1346
+ assert(err == 0);
1347
+
1348
+ return 0;
1349
+ }
1350
+
1351
+ inline int
1352
+ utf32_string_view_concat_view(const utf32_string_view_t view, const utf32_string_view_t other, utf32_string_t *result) {
1353
+ int err;
1354
+
1355
+ utf32_string_init(result);
1356
+
1357
+ err = utf32_string_reserve(result, view.len + other.len);
1358
+ if (err < 0) return err;
1359
+
1360
+ err = utf32_string_append_view(result, view);
1361
+ assert(err == 0);
1362
+
1363
+ err = utf32_string_append_view(result, other);
1364
+ assert(err == 0);
1365
+
1366
+ return 0;
1367
+ }
1368
+
1369
+ inline int
1370
+ utf32_string_concat_character(const utf32_string_t *string, utf32_t c, utf32_string_t *result) {
1371
+ int err;
1372
+
1373
+ utf32_string_init(result);
1374
+
1375
+ err = utf32_string_reserve(result, string->len + 1);
1376
+ if (err < 0) return err;
1377
+
1378
+ err = utf32_string_append(result, string);
1379
+ assert(err == 0);
1380
+
1381
+ err = utf32_string_append_character(result, c);
1382
+ assert(err == 0);
1383
+
1384
+ return 0;
1385
+ }
1386
+
1387
+ inline int
1388
+ utf32_string_view_concat_character(const utf32_string_view_t view, utf32_t c, utf32_string_t *result) {
1389
+ int err;
1390
+
1391
+ utf32_string_init(result);
1392
+
1393
+ err = utf32_string_reserve(result, view.len + 1);
1394
+ if (err < 0) return err;
1395
+
1396
+ err = utf32_string_append_view(result, view);
1397
+ assert(err == 0);
1398
+
1399
+ err = utf32_string_append_character(result, c);
1400
+ assert(err == 0);
1401
+
1402
+ return 0;
1403
+ }
1404
+
1405
+ inline int
1406
+ utf32_string_concat_literal(const utf32_string_t *string, const utf32_t *literal, size_t n, utf32_string_t *result) {
1407
+ int err;
1408
+
1409
+ utf32_string_init(result);
1410
+
1411
+ err = utf32_string_reserve(result, string->len + n);
1412
+ if (err < 0) return err;
1413
+
1414
+ err = utf32_string_append(result, string);
1415
+ assert(err == 0);
1416
+
1417
+ err = utf32_string_append_literal(result, literal, n);
1418
+ assert(err == 0);
1419
+
1420
+ return 0;
1421
+ }
1422
+
1423
+ inline int
1424
+ utf32_string_view_concat_literal(const utf32_string_view_t view, const utf32_t *literal, size_t n, utf32_string_t *result) {
1425
+ int err;
1426
+
1427
+ utf32_string_init(result);
1428
+
1429
+ err = utf32_string_reserve(result, view.len + n);
1430
+ if (err < 0) return err;
1431
+
1432
+ err = utf32_string_append_view(result, view);
1433
+ assert(err == 0);
1434
+
1435
+ err = utf32_string_append_literal(result, literal, n);
1436
+ assert(err == 0);
1437
+
1438
+ return 0;
1439
+ }
1440
+
1441
+ /**
1442
+ * Compares the code points of `a` and `b`, of which the first `len` are
1443
+ * compared. This stands in for the `memcmp` that the UTF-8 string uses, which
1444
+ * would order the code points by their bytes rather than by their value.
1445
+ */
1446
+ static inline int
1447
+ utf32__string_compare(const utf32_t *a, const utf32_t *b, size_t len) {
1448
+ for (size_t i = 0; i < len; i++) {
1449
+ if (a[i] != b[i]) return a[i] < b[i] ? -1 : 1;
1450
+ }
1451
+
1452
+ return 0;
1453
+ }
1454
+
1455
+ inline int
1456
+ utf32_string_compare(const utf32_string_t *string, const utf32_string_t *other) {
1457
+ size_t a_len = string->len;
1458
+ size_t b_len = other->len;
1459
+
1460
+ // The shorter of the two lengths, over which the contents are compared. The
1461
+ // comparison is one of code points rather than of C strings, a length
1462
+ // delimited string being free to hold a null code point.
1463
+ size_t len = a_len < b_len ? a_len : b_len;
1464
+
1465
+ int result = len == 0 ? 0 : utf32__string_compare(string->data, other->data, len);
1466
+
1467
+ if (result == 0) return a_len < b_len
1468
+ ? -1
1469
+ : a_len > b_len ? 1
1470
+ : 0;
1471
+
1472
+ return result;
1473
+ }
1474
+
1475
+ inline int
1476
+ utf32_string_view_compare(const utf32_string_view_t view, const utf32_string_view_t other) {
1477
+ size_t a_len = view.len;
1478
+ size_t b_len = other.len;
1479
+
1480
+ // The shorter of the two lengths, over which the contents are compared. The
1481
+ // comparison is one of code points rather than of C strings, a length
1482
+ // delimited string being free to hold a null code point.
1483
+ size_t len = a_len < b_len ? a_len : b_len;
1484
+
1485
+ int result = len == 0 ? 0 : utf32__string_compare(view.data, other.data, len);
1486
+
1487
+ if (result == 0) return a_len < b_len
1488
+ ? -1
1489
+ : a_len > b_len ? 1
1490
+ : 0;
1491
+
1492
+ return result;
1493
+ }
1494
+
1495
+ inline int
1496
+ utf32_string_compare_literal(const utf32_string_t *string, const utf32_t *literal, size_t n) {
1497
+ if (n == (size_t) -1) n = utf32__string_literal_length(literal);
1498
+
1499
+ size_t a_len = string->len;
1500
+ size_t b_len = n;
1501
+
1502
+ // The shorter of the two lengths, over which the contents are compared. The
1503
+ // comparison is one of code points rather than of C strings, a length
1504
+ // delimited string being free to hold a null code point.
1505
+ size_t len = a_len < b_len ? a_len : b_len;
1506
+
1507
+ int result = len == 0 ? 0 : utf32__string_compare(string->data, literal, len);
1508
+
1509
+ if (result == 0) return a_len < b_len
1510
+ ? -1
1511
+ : a_len > b_len ? 1
1512
+ : 0;
1513
+
1514
+ return result;
1515
+ }
1516
+
1517
+ inline int
1518
+ utf32_string_view_compare_literal(const utf32_string_view_t view, const utf32_t *literal, size_t n) {
1519
+ if (n == (size_t) -1) n = utf32__string_literal_length(literal);
1520
+
1521
+ size_t a_len = view.len;
1522
+ size_t b_len = n;
1523
+
1524
+ // The shorter of the two lengths, over which the contents are compared. The
1525
+ // comparison is one of code points rather than of C strings, a length
1526
+ // delimited string being free to hold a null code point.
1527
+ size_t len = a_len < b_len ? a_len : b_len;
1528
+
1529
+ int result = len == 0 ? 0 : utf32__string_compare(view.data, literal, len);
1530
+
1531
+ if (result == 0) return a_len < b_len
1532
+ ? -1
1533
+ : a_len > b_len ? 1
1534
+ : 0;
1535
+
1536
+ return result;
1537
+ }
1538
+
1539
+ inline utf32_string_view_t
1540
+ utf32_string_substring(const utf32_string_t *string, size_t start, size_t end) {
1541
+ if (end == (size_t) -1 || end > string->len) end = string->len;
1542
+ if (start > end) start = end;
1543
+
1544
+ return utf32_string_view_init(&string->data[start], end - start);
1545
+ }
1546
+
1547
+ inline utf32_string_view_t
1548
+ utf32_string_view_substring(const utf32_string_view_t view, size_t start, size_t end) {
1549
+ if (end == (size_t) -1 || end > view.len) end = view.len;
1550
+ if (start > end) start = end;
1551
+
1552
+ return utf32_string_view_init(&view.data[start], end - start);
1553
+ }
1554
+
1555
+ inline int
1556
+ utf32_string_substring_copy(const utf32_string_t *string, size_t start, size_t end, utf32_string_t *result) {
1557
+ int err;
1558
+
1559
+ if (end == (size_t) -1 || end > string->len) end = string->len;
1560
+ if (start > end) start = end;
1561
+
1562
+ size_t len = end - start;
1563
+
1564
+ err = utf32_string_reserve(result, len);
1565
+ if (err < 0) return -1;
1566
+
1567
+ memcpy(result->data, &string->data[start], len * sizeof(utf32_t));
1568
+
1569
+ result->len = len;
1570
+
1571
+ return 0;
1572
+ }
1573
+
1574
+ inline int
1575
+ utf32_string_view_substring_copy(const utf32_string_view_t view, size_t start, size_t end, utf32_string_t *result) {
1576
+ int err;
1577
+
1578
+ if (end == (size_t) -1 || end > view.len) end = view.len;
1579
+ if (start > end) start = end;
1580
+
1581
+ size_t len = end - start;
1582
+
1583
+ err = utf32_string_reserve(result, len);
1584
+ if (err < 0) return -1;
1585
+
1586
+ memcpy(result->data, &view.data[start], len * sizeof(utf32_t));
1587
+
1588
+ result->len = len;
1589
+
1590
+ return 0;
1591
+ }
1592
+
1593
+ inline size_t
1594
+ utf32_string_index_of_character(const utf32_string_t *string, size_t pos, utf32_t c) {
1595
+ // Also catches a pos of (size_t) -1, which must not be turned into a length.
1596
+ if (pos >= string->len) return (size_t) -1;
1597
+
1598
+ for (size_t i = pos; i < string->len; i++) {
1599
+ if (string->data[i] == c) {
1600
+ return i;
1601
+ }
1602
+ }
1603
+
1604
+ return (size_t) -1;
1605
+ }
1606
+
1607
+ inline size_t
1608
+ utf32_string_view_index_of_character(const utf32_string_view_t view, size_t pos, utf32_t c) {
1609
+ // Also catches a pos of (size_t) -1, which must not be turned into a length.
1610
+ if (pos >= view.len) return (size_t) -1;
1611
+
1612
+ for (size_t i = pos; i < view.len; i++) {
1613
+ if (view.data[i] == c) {
1614
+ return i;
1615
+ }
1616
+ }
1617
+
1618
+ return (size_t) -1;
1619
+ }
1620
+
1621
+ inline size_t
1622
+ utf32_string_last_index_of_character(const utf32_string_t *string, size_t pos, utf32_t c) {
1623
+ if (string->len == 0) return (size_t) -1;
1624
+ if (pos == (size_t) -1) pos = string->len - 1;
1625
+ else if (pos >= string->len) return (size_t) -1;
1626
+
1627
+ for (size_t i = pos; i <= pos; i--) {
1628
+ if (string->data[i] == c) {
1629
+ return i;
1630
+ }
1631
+ }
1632
+
1633
+ return (size_t) -1;
1634
+ }
1635
+
1636
+ inline size_t
1637
+ utf32_string_view_last_index_of_character(const utf32_string_view_t view, size_t pos, utf32_t c) {
1638
+ if (view.len == 0) return (size_t) -1;
1639
+ if (pos == (size_t) -1) pos = view.len - 1;
1640
+ else if (pos >= view.len) return (size_t) -1;
1641
+
1642
+ for (size_t i = pos; i <= pos; i--) {
1643
+ if (view.data[i] == c) {
1644
+ return i;
1645
+ }
1646
+ }
1647
+
1648
+ return (size_t) -1;
1649
+ }
1650
+
1651
+ #ifdef __cplusplus
1652
+ }
1653
+ #endif
1654
+
1655
+ #endif // UTF_STRING_H