@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.
- package/LICENSE +201 -0
- package/README.md +26 -0
- package/binding.c +1077 -0
- package/binding.gyp +32 -0
- package/binding.js +1 -0
- package/build/Release/bare_buffer.node +0 -0
- package/deps/libbase64/.clang-format +10 -0
- package/deps/libbase64/.gitattributes +1 -0
- package/deps/libbase64/.github/workflows/integrate.yml +45 -0
- package/deps/libbase64/.github/workflows/nightly.yml +28 -0
- package/deps/libbase64/.prettierrc +1 -0
- package/deps/libbase64/CMakeLists.txt +71 -0
- package/deps/libbase64/LICENSE +201 -0
- package/deps/libbase64/NOTICE +13 -0
- package/deps/libbase64/README.md +11 -0
- package/deps/libbase64/include/base64.h +323 -0
- package/deps/libbase64/package.json +25 -0
- package/deps/libbase64/src/base64.c +22 -0
- package/deps/libbase64/test/CMakeLists.txt +31 -0
- package/deps/libbase64/test/decode-invalid.c +35 -0
- package/deps/libbase64/test/decode-length.c +23 -0
- package/deps/libbase64/test/decode.c +36 -0
- package/deps/libbase64/test/encode-length.c +22 -0
- package/deps/libbase64/test/encode.c +42 -0
- package/deps/libbase64/test/fuzz/CMakeLists.txt +18 -0
- package/deps/libbase64/test/fuzz/decode/utf16le.c +53 -0
- package/deps/libbase64/test/fuzz/decode/utf8.c +47 -0
- package/deps/libbase64/test/fuzz/encode/utf16le.c +56 -0
- package/deps/libbase64/test/fuzz/encode/utf8.c +56 -0
- package/deps/libhex/.clang-format +10 -0
- package/deps/libhex/.gitattributes +1 -0
- package/deps/libhex/.github/workflows/integrate.yml +45 -0
- package/deps/libhex/.github/workflows/nightly.yml +28 -0
- package/deps/libhex/.prettierrc +1 -0
- package/deps/libhex/CMakeLists.txt +72 -0
- package/deps/libhex/LICENSE +201 -0
- package/deps/libhex/NOTICE +13 -0
- package/deps/libhex/README.md +11 -0
- package/deps/libhex/include/hex.h +163 -0
- package/deps/libhex/package.json +25 -0
- package/deps/libhex/src/hex.c +16 -0
- package/deps/libhex/test/CMakeLists.txt +31 -0
- package/deps/libhex/test/decode-invalid.c +37 -0
- package/deps/libhex/test/decode-length.c +23 -0
- package/deps/libhex/test/decode.c +25 -0
- package/deps/libhex/test/encode-length.c +22 -0
- package/deps/libhex/test/encode.c +25 -0
- package/deps/libhex/test/fuzz/CMakeLists.txt +18 -0
- package/deps/libhex/test/fuzz/decode/utf16le.c +53 -0
- package/deps/libhex/test/fuzz/decode/utf8.c +47 -0
- package/deps/libhex/test/fuzz/encode/utf16le.c +36 -0
- package/deps/libhex/test/fuzz/encode/utf8.c +36 -0
- package/deps/libutf/.clang-format +10 -0
- package/deps/libutf/.gitattributes +1 -0
- package/deps/libutf/.github/workflows/integrate.yml +45 -0
- package/deps/libutf/.github/workflows/nightly.yml +28 -0
- package/deps/libutf/.prettierrc +1 -0
- package/deps/libutf/CMakeLists.txt +105 -0
- package/deps/libutf/LICENSE +201 -0
- package/deps/libutf/NOTICE +13 -0
- package/deps/libutf/README.md +11 -0
- package/deps/libutf/include/utf/string.h +1655 -0
- package/deps/libutf/include/utf.h +132 -0
- package/deps/libutf/package.json +24 -0
- package/deps/libutf/src/ascii/validate.c +47 -0
- package/deps/libutf/src/endianness.c +19 -0
- package/deps/libutf/src/endianness.h +54 -0
- package/deps/libutf/src/latin1/convert-to-utf16.c +37 -0
- package/deps/libutf/src/latin1/convert-to-utf32.c +34 -0
- package/deps/libutf/src/latin1/convert-to-utf8.c +58 -0
- package/deps/libutf/src/latin1/length-from-utf16.c +26 -0
- package/deps/libutf/src/latin1/length-from-utf32.c +26 -0
- package/deps/libutf/src/latin1/length-from-utf8.c +34 -0
- package/deps/libutf/src/utf16/convert-to-latin1.c +41 -0
- package/deps/libutf/src/utf16/convert-to-utf32.c +56 -0
- package/deps/libutf/src/utf16/convert-to-utf8.c +80 -0
- package/deps/libutf/src/utf16/length-from-latin1.c +26 -0
- package/deps/libutf/src/utf16/length-from-utf32.c +33 -0
- package/deps/libutf/src/utf16/length-from-utf8.c +38 -0
- package/deps/libutf/src/utf16/validate.c +53 -0
- package/deps/libutf/src/utf32/convert-to-latin1.c +40 -0
- package/deps/libutf/src/utf32/convert-to-utf16.c +56 -0
- package/deps/libutf/src/utf32/convert-to-utf8.c +71 -0
- package/deps/libutf/src/utf32/length-from-latin1.c +26 -0
- package/deps/libutf/src/utf32/length-from-utf16.c +35 -0
- package/deps/libutf/src/utf32/length-from-utf8.c +35 -0
- package/deps/libutf/src/utf32/string.c +149 -0
- package/deps/libutf/src/utf32/validate.c +39 -0
- package/deps/libutf/src/utf8/convert-to-latin1.c +70 -0
- package/deps/libutf/src/utf8/convert-to-utf16.c +95 -0
- package/deps/libutf/src/utf8/convert-to-utf32.c +110 -0
- package/deps/libutf/src/utf8/length-from-latin1.c +32 -0
- package/deps/libutf/src/utf8/length-from-utf16.c +48 -0
- package/deps/libutf/src/utf8/length-from-utf32.c +35 -0
- package/deps/libutf/src/utf8/string.c +149 -0
- package/deps/libutf/src/utf8/validate.c +107 -0
- package/deps/libutf/test/CMakeLists.txt +56 -0
- package/deps/libutf/test/fuzz/CMakeLists.txt +26 -0
- package/deps/libutf/test/fuzz/corpus/.gitignore +2 -0
- package/deps/libutf/test/fuzz/crashes/.gitignore +2 -0
- package/deps/libutf/test/fuzz/latin1/convert-to-utf16.c +32 -0
- package/deps/libutf/test/fuzz/latin1/convert-to-utf32.c +32 -0
- package/deps/libutf/test/fuzz/latin1/convert-to-utf8.c +33 -0
- package/deps/libutf/test/fuzz/utf16/convert-to-latin1.c +36 -0
- package/deps/libutf/test/fuzz/utf16/convert-to-utf32.c +38 -0
- package/deps/libutf/test/fuzz/utf16/convert-to-utf8.c +38 -0
- package/deps/libutf/test/fuzz/utf32/convert-to-latin1.c +36 -0
- package/deps/libutf/test/fuzz/utf32/convert-to-utf16.c +38 -0
- package/deps/libutf/test/fuzz/utf32/convert-to-utf8.c +38 -0
- package/deps/libutf/test/fuzz/utf8/convert-to-latin1.c +33 -0
- package/deps/libutf/test/fuzz/utf8/convert-to-utf16.c +35 -0
- package/deps/libutf/test/fuzz/utf8/convert-to-utf32.c +35 -0
- package/deps/libutf/test/utf16/utf8-convert.c +45 -0
- package/deps/libutf/test/utf16/utf8-length.c +41 -0
- package/deps/libutf/test/utf16/validate-invalid.c +50 -0
- package/deps/libutf/test/utf16/validate.c +32 -0
- package/deps/libutf/test/utf32/string-append.c +74 -0
- package/deps/libutf/test/utf32/string-compare.c +108 -0
- package/deps/libutf/test/utf32/string-erase.c +79 -0
- package/deps/libutf/test/utf32/string-index.c +102 -0
- package/deps/libutf/test/utf32/string-insert.c +92 -0
- package/deps/libutf/test/utf32/string-last-index.c +71 -0
- package/deps/libutf/test/utf32/string-prepend.c +51 -0
- package/deps/libutf/test/utf32/string-replace.c +88 -0
- package/deps/libutf/test/utf32/string-reserve.c +99 -0
- package/deps/libutf/test/utf32/string-substring.c +93 -0
- package/deps/libutf/test/utf8/latin1-convert.c +23 -0
- package/deps/libutf/test/utf8/string-append.c +23 -0
- package/deps/libutf/test/utf8/string-compare.c +67 -0
- package/deps/libutf/test/utf8/string-erase.c +75 -0
- package/deps/libutf/test/utf8/string-index.c +99 -0
- package/deps/libutf/test/utf8/string-last-index.c +68 -0
- package/deps/libutf/test/utf8/string-prepend.c +23 -0
- package/deps/libutf/test/utf8/string-replace.c +74 -0
- package/deps/libutf/test/utf8/string-reserve.c +51 -0
- package/deps/libutf/test/utf8/string-substring.c +68 -0
- package/deps/libutf/test/utf8/utf16-convert.c +32 -0
- package/deps/libutf/test/utf8/utf16-length.c +29 -0
- package/deps/libutf/test/utf8/validate-invalid.c +26 -0
- package/deps/libutf/test/utf8/validate.c +21 -0
- package/global.d.ts +21 -0
- package/global.js +6 -0
- package/index.d.ts +769 -0
- package/index.js +1339 -0
- package/lib/ascii.js +36 -0
- package/lib/base64.js +25 -0
- package/lib/base64url.js +25 -0
- package/lib/checked.js +23 -0
- package/lib/constants.d.ts +7 -0
- package/lib/constants.js +3 -0
- package/lib/hex.js +20 -0
- package/lib/latin1.js +14 -0
- package/lib/utf16le.js +20 -0
- package/lib/utf8.js +18 -0
- 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
|