-
Notifications
You must be signed in to change notification settings - Fork 14
/
string.h
211 lines (172 loc) · 8.32 KB
/
string.h
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
#pragma once
#include "core/dll.h"
#include "core/types.h"
#include "core/array.h"
#include "core/vector.h"
#include <utility>
namespace Core
{
/**
* Convert from UTF-16 to UTF-8.
* @param src Source string.
* @param srcLength Source string length.
* @param dst Destination string.
* @param dstLength Destination length including null terminator.
* @return Success.
* @pre src != nullptr.
* @pre dst != nullptr.
* @pre srcLength > 0.
* @pre dstLength > 1.
*/
CORE_DLL bool StringConvertUTF16toUTF8(const wchar* src, i32 srcLength, char* dst, i32 dstLength);
/**
* Convert from UTF-8 to UTF-16.
* @param src Source string.
* @param srcLength Source string length.
* @param dst Destination string.
* @param dstLength Destination length including null terminator.
* @return Success.
* @pre src != nullptr.
* @pre dst != nullptr.
* @pre srcLength > 0.
* @pre dstLength > 1.
*/
CORE_DLL bool StringConvertUTF8toUTF16(const char* src, i32 srcLength, wchar* dst, i32 dstLength);
/**
* String class.
*/
class CORE_DLL String
{
public:
using storage_type = Core::Vector<char>;
using index_type = storage_type::index_type;
using iterator = storage_type::iterator;
using const_iterator = storage_type::const_iterator;
static const index_type npos = -1;
String() {}
String(const char* str) { internalSet(str); }
String(const char* begin, const char* end) { internalSet(begin, end); }
String(const String& str) { internalSet(str.c_str()); }
String(String&& str) { swap(str); }
~String() {}
// Custom interfaces.
String& Printf(const char* fmt, ...);
String& Printfv(const char* fmt, va_list argList);
String& Appendf(const char* fmt, ...);
String& Appendfv(const char* fmt, va_list argList);
String& Append(const char* str);
// STL compatible interfaces.
void clear() { data_.clear(); }
const char* c_str() const { return data_.data(); }
i32 size() const { return data_.size() > 0 ? data_.size() - 1 : 0; }
char* data() { return data_.data(); }
const char* data() const { return data_.data(); }
void reserve(index_type capacity) { data_.reserve(capacity); }
void swap(String& other) { data_.swap(other.data_); }
void resize(index_type size)
{
data_.resize(size + 1);
data_.back() = '\0';
}
void shrink_to_fit() { data_.shrink_to_fit(); }
index_type find(const char* str, index_type subPos = 0) const;
index_type find(const String& str, index_type subPos = 0) const { return find(str.c_str(), subPos); }
String substr(index_type start, index_type len) const;
String replace(const char* search, const char* replacement) const;
iterator begin() { return data_.begin(); }
const_iterator begin() const { return data_.begin(); }
iterator end() { return data_.end() - 1; }
const_iterator end() const { return data_.end() - 1; }
char operator[](index_type idx) const { return data_[idx]; }
// cstring versions.
void append(const char* str) { internalAppend(str); }
void append(const char* str, index_type subPos, index_type subLen) { internalAppend(str, subPos, subLen); }
int compare(const char* str) const { return internalCompare(str); }
bool operator==(const char* str) const { return internalCompare(str) == 0; }
bool operator!=(const char* str) const { return internalCompare(str) != 0; }
bool operator<(const char* str) const { return internalCompare(str) < 0; }
bool operator>(const char* str) const { return internalCompare(str) > 0; }
bool operator<=(const char* str) const { return internalCompare(str) <= 0; }
bool operator>=(const char* str) const { return internalCompare(str) >= 0; }
// String versions.
void append(const String& str) { internalAppend(str.c_str()); }
int compare(const String& str) const { return internalCompare(str.c_str()); }
String& operator=(const char* str) { return internalSet(str); }
String& operator=(const String& str) { return internalSet(str.c_str()); }
String& operator=(String&& str)
{
swap(str);
return (*this);
}
String& operator+=(const char* str) { return internalAppend(str); }
String& operator+=(const String& str) { return internalAppend(str.c_str()); }
bool operator==(const String& str) const { return internalCompare(str.c_str()) == 0; }
bool operator!=(const String& str) const { return internalCompare(str.c_str()) != 0; }
bool operator<(const String& str) const { return internalCompare(str.c_str()) < 0; }
bool operator>(const String& str) const { return internalCompare(str.c_str()) > 0; }
bool operator<=(const String& str) const { return internalCompare(str.c_str()) <= 0; }
bool operator>=(const String& str) const { return internalCompare(str.c_str()) >= 0; }
private:
String& internalRemoveNullTerminator(bool forceRemove = true);
String& internalSet(const char* begin, const char* end = nullptr);
String& internalAppend(const char* str, index_type subPos = 0, index_type subLen = npos);
int internalCompare(const char* str) const;
storage_type data_;
};
class CORE_DLL StringView
{
public:
using const_iterator = String::const_iterator;
using index_type = String::index_type;
StringView(const char* begin = nullptr, const char* end = nullptr)
: begin_(begin)
, end_(end)
{
if(begin_ && !end_)
end_ = begin_ + strlen(begin_);
}
StringView(const String& str)
: begin_(str.begin())
, end_(str.end())
{
}
~StringView() = default;
String ToString() const { return String(begin_, end_); }
const_iterator begin() const { return begin_; }
const_iterator end() const { return end_; }
index_type size() const { return (index_type)(end_ - begin_); }
int compare(const char* str) const { return internalCompare(str, nullptr); }
int compare(const String& str) const { return internalCompare(str.begin(), str.end()); }
int compare(const StringView& str) const { return internalCompare(str.begin(), str.end()); }
bool operator==(const char* str) const { return internalCompare(str, nullptr) == 0; }
bool operator!=(const char* str) const { return internalCompare(str, nullptr) != 0; }
bool operator<(const char* str) const { return internalCompare(str, nullptr) < 0; }
bool operator>(const char* str) const { return internalCompare(str, nullptr) > 0; }
bool operator<=(const char* str) const { return internalCompare(str, nullptr) <= 0; }
bool operator>=(const char* str) const { return internalCompare(str, nullptr) >= 0; }
bool operator==(const String& str) const { return internalCompare(str.begin(), str.end()) == 0; }
bool operator!=(const String& str) const { return internalCompare(str.begin(), str.end()) != 0; }
bool operator<(const String& str) const { return internalCompare(str.begin(), str.end()) < 0; }
bool operator>(const String& str) const { return internalCompare(str.begin(), str.end()) > 0; }
bool operator<=(const String& str) const { return internalCompare(str.begin(), str.end()) <= 0; }
bool operator>=(const String& str) const { return internalCompare(str.begin(), str.end()) >= 0; }
bool operator==(const StringView& str) const { return internalCompare(str.begin(), str.end()) == 0; }
bool operator!=(const StringView& str) const { return internalCompare(str.begin(), str.end()) != 0; }
bool operator<(const StringView& str) const { return internalCompare(str.begin(), str.end()) < 0; }
bool operator>(const StringView& str) const { return internalCompare(str.begin(), str.end()) > 0; }
bool operator<=(const StringView& str) const { return internalCompare(str.begin(), str.end()) <= 0; }
bool operator>=(const StringView& str) const { return internalCompare(str.begin(), str.end()) >= 0; }
private:
int internalCompare(const char* begin, const char* end) const;
const char* begin_ = nullptr;
const char* end_ = nullptr;
};
inline bool operator==(const String& str, const StringView& view) { return view == str; }
inline bool operator!=(const String& str, const StringView& view) { return view != str; }
inline bool operator<(const String& str, const StringView& view) { return view >= str; }
inline bool operator>(const String& str, const StringView& view) { return view <= str; }
inline bool operator<=(const String& str, const StringView& view) { return view > str; }
inline bool operator>=(const String& str, const StringView& view) { return view < str; }
CORE_DLL u32 Hash(u32 input, const String& string);
CORE_DLL u32 Hash(u32 input, const StringView& string);
} // end namespace Core