-
Notifications
You must be signed in to change notification settings - Fork 0
/
string.hpp
370 lines (298 loc) · 12.8 KB
/
string.hpp
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
#pragma once
#include <stdarg.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <algorithm>
#include <initializer_list>
#include <memory>
#include <nall/platform.hpp>
#include <nall/array-view.hpp>
#include <nall/atoi.hpp>
#include <nall/function.hpp>
#include <nall/intrinsics.hpp>
#include <nall/memory.hpp>
#include <nall/primitives.hpp>
#include <nall/shared-pointer.hpp>
#include <nall/stdint.hpp>
#include <nall/unique-pointer.hpp>
#include <nall/utility.hpp>
#include <nall/varint.hpp>
#include <nall/vector.hpp>
#include <nall/view.hpp>
namespace nall {
struct string;
struct string_format;
struct string_view {
using type = string_view;
//view.hpp
string_view();
string_view(const string_view& source);
string_view(string_view&& source);
string_view(const char* data);
string_view(const char* data, u32 size);
string_view(const string& source);
template<typename... P> string_view(P&&... p);
~string_view();
auto operator=(const string_view& source) -> type&;
auto operator=(string_view&& source) -> type&;
auto operator==(const char* source) const -> bool { return strcmp(data(), source) == 0; }
auto operator!=(const char* source) const -> bool { return strcmp(data(), source) != 0; }
explicit operator bool() const;
operator const char*() const;
auto data() const -> const char*;
auto size() const -> u32;
auto begin() const { return &_data[0]; }
auto end() const { return &_data[size()]; }
protected:
string* _string;
const char* _data;
mutable s32 _size;
};
//adaptive (SSO + COW) is by far the best choice, the others exist solely to:
//1) demonstrate the performance benefit of combining SSO + COW
//2) rule out allocator bugs by trying different allocators when needed
#define NALL_STRING_ALLOCATOR_ADAPTIVE
//#define NALL_STRING_ALLOCATOR_COPY_ON_WRITE
//#define NALL_STRING_ALLOCATOR_SMALL_STRING_OPTIMIZATION
//#define NALL_STRING_ALLOCATOR_VECTOR
//cast.hpp
template<typename T> struct stringify;
//format.hpp
template<typename... P> auto print(P&&...) -> void;
template<typename... P> auto print(FILE*, P&&...) -> void;
template<typename T> auto pad(const T& value, long precision = 0, char padchar = ' ') -> string;
template<typename T> auto hex(T value, long precision = 0, char padchar = '0') -> string;
template<typename T> auto octal(T value, long precision = 0, char padchar = '0') -> string;
template<typename T> auto binary(T value, long precision = 0, char padchar = '0') -> string;
//match.hpp
auto tokenize(const char* s, const char* p) -> bool;
auto tokenize(vector<string>& list, const char* s, const char* p) -> bool;
//utf8.hpp
auto characters(string_view self, s32 offset = 0, s32 length = -1) -> u32;
//utility.hpp
auto slice(string_view self, s32 offset = 0, s32 length = -1) -> string;
template<typename T> auto fromInteger(char* result, T value) -> char*;
template<typename T> auto fromNatural(char* result, T value) -> char*;
template<typename T> auto fromHex(char* result, T value) -> char*;
template<typename T> auto fromReal(char* str, T value) -> u32;
struct string {
using type = string;
protected:
#if defined(NALL_STRING_ALLOCATOR_ADAPTIVE)
enum : u32 { SSO = 24 };
union {
struct { //copy-on-write
char* _data;
u32* _refs;
};
struct { //small-string-optimization
char _text[SSO];
};
};
auto _allocate() -> void;
auto _copy() -> void;
auto _resize() -> void;
#endif
#if defined(NALL_STRING_ALLOCATOR_COPY_ON_WRITE)
char* _data;
mutable u32* _refs;
auto _allocate() -> char*;
auto _copy() -> char*;
#endif
#if defined(NALL_STRING_ALLOCATOR_SMALL_STRING_OPTIMIZATION)
enum : u32 { SSO = 24 };
union {
char* _data;
char _text[SSO];
};
#endif
#if defined(NALL_STRING_ALLOCATOR_VECTOR)
char* _data;
#endif
u32 _capacity;
u32 _size;
public:
string();
string(string& source) : string() { operator=(source); }
string(const string& source) : string() { operator=(source); }
string(string&& source) : string() { operator=(move(source)); }
template<typename T = char> auto get() -> T*;
template<typename T = char> auto data() const -> const T*;
template<typename T = char> auto size() const -> u32 { return _size / sizeof(T); }
template<typename T = char> auto capacity() const -> u32 { return _capacity / sizeof(T); }
auto reset() -> type&;
auto reserve(u32) -> type&;
auto resize(u32) -> type&;
auto operator=(const string&) -> type&;
auto operator=(string&&) -> type&;
template<typename T, typename... P> string(T&& s, P&&... p) : string() {
append(forward<T>(s), forward<P>(p)...);
}
~string() { reset(); }
explicit operator bool() const { return _size; }
operator const char*() const { return (const char*)data(); }
operator array_span<char>() { return {(char*)get(), size()}; }
operator array_view<char>() const { return {(const char*)data(), size()}; }
operator array_span<u8>() { return {(u8*)get(), size()}; }
operator array_view<u8>() const { return {(const u8*)data(), size()}; }
auto operator==(const string& source) const -> bool {
return size() == source.size() && memory::compare(data(), source.data(), size()) == 0;
}
auto operator!=(const string& source) const -> bool {
return size() != source.size() || memory::compare(data(), source.data(), size()) != 0;
}
auto operator==(const char* source) const -> bool { return strcmp(data(), source) == 0; }
auto operator!=(const char* source) const -> bool { return strcmp(data(), source) != 0; }
auto operator==(string_view source) const -> bool { return compare(source) == 0; }
auto operator!=(string_view source) const -> bool { return compare(source) != 0; }
auto operator< (string_view source) const -> bool { return compare(source) < 0; }
auto operator<=(string_view source) const -> bool { return compare(source) <= 0; }
auto operator> (string_view source) const -> bool { return compare(source) > 0; }
auto operator>=(string_view source) const -> bool { return compare(source) >= 0; }
auto begin() -> char* { return &get()[0]; }
auto end() -> char* { return &get()[size()]; }
auto begin() const -> const char* { return &data()[0]; }
auto end() const -> const char* { return &data()[size()]; }
//atoi.hpp
auto boolean() const -> bool;
auto integer() const -> s64;
auto natural() const -> u64;
auto hex() const -> u64;
auto real() const -> f64;
//core.hpp
auto operator[](u32) const -> const char&;
auto operator()(u32, char = 0) const -> char;
template<typename... P> auto assign(P&&...) -> type&;
template<typename T, typename... P> auto prepend(const T&, P&&...) -> type&;
template<typename... P> auto prepend(const nall::string_format&, P&&...) -> type&;
template<typename T> auto _prepend(const stringify<T>&) -> type&;
template<typename T, typename... P> auto append(const T&, P&&...) -> type&;
template<typename... P> auto append(const nall::string_format&, P&&...) -> type&;
template<typename T> auto _append(const stringify<T>&) -> type&;
auto length() const -> u32;
//find.hpp
auto contains(string_view characters) const -> maybe<u32>;
template<bool, bool> auto _find(s32, string_view) const -> maybe<u32>;
auto find(string_view source) const -> maybe<u32>;
auto ifind(string_view source) const -> maybe<u32>;
auto qfind(string_view source) const -> maybe<u32>;
auto iqfind(string_view source) const -> maybe<u32>;
auto findFrom(s32 offset, string_view source) const -> maybe<u32>;
auto ifindFrom(s32 offset, string_view source) const -> maybe<u32>;
auto findNext(s32 offset, string_view source) const -> maybe<u32>;
auto ifindNext(s32 offset, string_view source) const -> maybe<u32>;
auto findPrevious(s32 offset, string_view source) const -> maybe<u32>;
auto ifindPrevious(s32 offset, string_view source) const -> maybe<u32>;
//format.hpp
auto format(const nall::string_format& params) -> type&;
//compare.hpp
template<bool> static auto _compare(const char*, u32, const char*, u32) -> s32;
static auto compare(string_view, string_view) -> s32;
static auto icompare(string_view, string_view) -> s32;
auto compare(string_view source) const -> s32;
auto icompare(string_view source) const -> s32;
auto equals(string_view source) const -> bool;
auto iequals(string_view source) const -> bool;
auto beginsWith(string_view source) const -> bool;
auto ibeginsWith(string_view source) const -> bool;
auto endsWith(string_view source) const -> bool;
auto iendsWith(string_view source) const -> bool;
//convert.hpp
auto downcase() -> type&;
auto upcase() -> type&;
auto qdowncase() -> type&;
auto qupcase() -> type&;
auto transform(string_view from, string_view to) -> type&;
//match.hpp
auto match(string_view source) const -> bool;
auto imatch(string_view source) const -> bool;
//replace.hpp
template<bool, bool> auto _replace(string_view, string_view, long) -> type&;
auto replace(string_view from, string_view to, long limit = LONG_MAX) -> type&;
auto ireplace(string_view from, string_view to, long limit = LONG_MAX) -> type&;
auto qreplace(string_view from, string_view to, long limit = LONG_MAX) -> type&;
auto iqreplace(string_view from, string_view to, long limit = LONG_MAX) -> type&;
//split.hpp
auto split(string_view key, long limit = LONG_MAX) const -> vector<string>;
auto isplit(string_view key, long limit = LONG_MAX) const -> vector<string>;
auto qsplit(string_view key, long limit = LONG_MAX) const -> vector<string>;
auto iqsplit(string_view key, long limit = LONG_MAX) const -> vector<string>;
//trim.hpp
auto trim(string_view lhs, string_view rhs, long limit = LONG_MAX) -> type&;
auto trimLeft(string_view lhs, long limit = LONG_MAX) -> type&;
auto trimRight(string_view rhs, long limit = LONG_MAX) -> type&;
auto itrim(string_view lhs, string_view rhs, long limit = LONG_MAX) -> type&;
auto itrimLeft(string_view lhs, long limit = LONG_MAX) -> type&;
auto itrimRight(string_view rhs, long limit = LONG_MAX) -> type&;
auto strip() -> type&;
auto stripLeft() -> type&;
auto stripRight() -> type&;
//utf8.hpp
auto characters(s32 offset = 0, s32 length = -1) const -> u32;
//utility.hpp
static auto read(string_view filename) -> string;
static auto repeat(string_view pattern, u32 times) -> string;
auto fill(char fill = ' ') -> type&;
auto hash() const -> u32;
auto remove(u32 offset, u32 length) -> type&;
auto reverse() -> type&;
auto size(s32 length, char fill = ' ') -> type&;
auto slice(s32 offset = 0, s32 length = -1) const -> string;
};
template<> struct vector<string> : vector_base<string> {
using type = vector<string>;
using vector_base<string>::vector_base;
vector(const vector& source) { vector_base::operator=(source); }
vector(vector& source) { vector_base::operator=(source); }
vector(vector&& source) { vector_base::operator=(move(source)); }
template<typename... P> vector(P&&... p) { append(forward<P>(p)...); }
auto operator=(const vector& source) -> type& { return vector_base::operator=(source), *this; }
auto operator=(vector& source) -> type& { return vector_base::operator=(source), *this; }
auto operator=(vector&& source) -> type& { return vector_base::operator=(move(source)), *this; }
//vector.hpp
template<typename... P> auto append(const string&, P&&...) -> type&;
auto append() -> type&;
auto isort() -> type&;
auto find(string_view source) const -> maybe<u32>;
auto ifind(string_view source) const -> maybe<u32>;
auto match(string_view pattern) const -> vector<string>;
auto merge(string_view separator = "") const -> string;
auto strip() -> type&;
//split.hpp
template<bool, bool> auto _split(string_view, string_view, long) -> type&;
};
struct string_format : vector<string> {
using type = string_format;
template<typename... P> string_format(P&&... p) { reserve(sizeof...(p)); append(forward<P>(p)...); }
template<typename T, typename... P> auto append(const T&, P&&... p) -> type&;
auto append() -> type&;
};
inline auto operator"" _s(const char* value, std::size_t) -> string { return {value}; }
}
#include <nall/string/view.hpp>
#include <nall/string/pascal.hpp>
#include <nall/string/atoi.hpp>
#include <nall/string/cast.hpp>
#include <nall/string/compare.hpp>
#include <nall/string/convert.hpp>
#include <nall/string/core.hpp>
#include <nall/string/find.hpp>
#include <nall/string/format.hpp>
#include <nall/string/match.hpp>
#include <nall/string/replace.hpp>
#include <nall/string/split.hpp>
#include <nall/string/trim.hpp>
#include <nall/string/utf8.hpp>
#include <nall/string/utility.hpp>
#include <nall/string/vector.hpp>
#include <nall/string/eval/node.hpp>
#include <nall/string/eval/literal.hpp>
#include <nall/string/eval/parser.hpp>
#include <nall/string/eval/evaluator.hpp>
#include <nall/string/markup/node.hpp>
#include <nall/string/markup/find.hpp>
#include <nall/string/markup/bml.hpp>
#include <nall/string/markup/xml.hpp>
#include <nall/string/transform/cml.hpp>
#include <nall/string/transform/dml.hpp>