Kiwano Engine v1.3.x
String.h
1// Copyright (c) 2016-2018 Kiwano - Nomango
2//
3// Permission is hereby granted, free of charge, to any person obtaining a copy
4// of this software and associated documentation files (the "Software"), to deal
5// in the Software without restriction, including without limitation the rights
6// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
7// copies of the Software, and to permit persons to whom the Software is
8// furnished to do so, subject to the following conditions:
9//
10// The above copyright notice and this permission notice shall be included in
11// all copies or substantial portions of the Software.
12//
13// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
14// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
15// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
16// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
17// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
18// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
19// THE SOFTWARE.
20
21#pragma once
22#include <string>
23#include <type_traits>
24
25namespace kiwano
26{
27
30template <typename CharTy>
31using BasicString = std::basic_string<CharTy>;
32
35using String = BasicString<char>;
36
39using WideString = BasicString<wchar_t>;
40
43template <typename CharTy>
44class BasicStringView;
45
48using StringView = BasicStringView<char>;
49
52using WideStringView = BasicStringView<wchar_t>;
53
54namespace strings
55{
56
59String Format(const char* format, ...);
60
63WideString Format(const wchar_t* format, ...);
64
67String FormatArgs(const char* format, va_list args);
68
71WideString FormatArgs(const wchar_t* format, va_list args);
72
75String WideToNarrow(WideStringView str);
76
79WideString NarrowToWide(StringView str);
80
83String WideToUTF8(WideStringView str);
84
87WideString UTF8ToWide(StringView str);
88
89} // namespace strings
90
93template <typename CharTy>
95{
96public:
97 using value_type = CharTy;
98 using pointer = CharTy*;
99 using const_pointer = const CharTy*;
100 using reference = CharTy&;
101 using const_reference = const CharTy&;
102 using traits_type = std::char_traits<CharTy>;
103 using size_type = std::size_t;
104 using string_type = BasicString<CharTy>;
105
107 : ptr_(nullptr)
108 , count_(0)
109 {
110 }
111
112 BasicStringView(const_pointer c_str)
113 {
114 ptr_ = c_str;
115 if (c_str)
116 {
117 count_ = traits_type::length(c_str);
118 }
119 else
120 {
121 count_ = 0;
122 }
123 }
124
125 BasicStringView(const_pointer c_str, size_type count)
126 {
127 ptr_ = c_str;
128 if (c_str)
129 {
130 count_ = count;
131 }
132 else
133 {
134 count_ = 0;
135 }
136 }
137
138 BasicStringView(const string_type& str)
139 : ptr_(str.c_str())
140 , count_(str.length())
141 {
142 }
143
145 : ptr_(rhs.ptr_)
146 , count_(rhs.count_)
147 {
148 }
149
150 inline const value_type* data() const
151 {
152 return ptr_;
153 }
154
155 inline bool empty() const
156 {
157 return !ptr_ || !count_;
158 }
159
160 inline size_type find(value_type ch) const
161 {
162 const auto ptr = traits_type::find(ptr_, count_, ch);
163 if (ptr)
164 {
165 return ptr - ptr_;
166 }
167 return string_type::npos;
168 }
169
170 inline BasicStringView substr(size_type pos, size_type count = string_type::npos) const
171 {
172 if (pos >= count_)
173 return BasicStringView();
174
175 if (count == string_type::npos)
176 return BasicStringView(ptr_ + pos, count_ - pos);
177
178 KGE_ASSERT(pos + count <= count_);
179 return BasicStringView(ptr_ + pos, count);
180 }
181
182 inline size_type size() const
183 {
184 return count_;
185 }
186
187 inline value_type at(size_type index) const
188 {
189 return operator[](index);
190 }
191
192 inline value_type operator[](size_type index) const
193 {
194 if (empty() || index >= count_)
195 throw std::out_of_range("operator[] out of index");
196 return ptr_[index];
197 }
198
199 inline BasicStringView& operator=(const BasicStringView& rhs)
200 {
201 ptr_ = rhs.ptr_;
202 count_ = rhs.count_;
203 return *this;
204 }
205
206 friend bool operator==(const BasicStringView& lhs, const BasicStringView& rhs)
207 {
208 return lhs.size() == rhs.size() ? std::char_traits<value_type>::compare(lhs.data(), rhs.data(), lhs.size()) == 0
209 : false;
210 }
211
212 inline operator string_type() const
213 {
214 return string_type(ptr_, count_);
215 }
216
217public:
218 //
219 // Iterators for BasicStringView
220 //
222 {
223 const value_type* ptr_;
224 size_type pos_;
225 size_type count_;
226
227 public:
228 using iterator_category = std::random_access_iterator_tag;
229 using value_type = value_type;
230 using pointer = value_type*;
231 using reference = value_type&;
232 using difference_type = ptrdiff_t;
233
234 inline Iterator(pointer ptr, size_type pos, size_type count)
235 : ptr_(ptr)
236 , pos_(pos)
237 , count_(count)
238 {
239 }
240
241 inline Iterator(const Iterator& rhs)
242 : ptr_(rhs.ptr_)
243 , pos_(rhs.pos_)
244 , count_(rhs.count_)
245 {
246 }
247
248 inline Iterator& operator=(const Iterator& rhs)
249 {
250 ptr_ = rhs.ptr_;
251 pos_ = rhs.pos_;
252 count_ = rhs.count_;
253 return *this;
254 }
255
256 inline const value_type& operator*() const
257 {
258 KGE_ASSERT(pos_ < count_);
259 return ptr_[pos_];
260 }
261
262 inline const value_type* operator->() const
263 {
264 return std::pointer_traits<pointer>::pointer_to(**this);
265 }
266
267 inline Iterator& operator+=(size_type count)
268 {
269 KGE_ASSERT(pos_ + count >= 0 && pos_ + count <= count_);
270 pos_ += count;
271 return (*this);
272 }
273
274 inline Iterator& operator-=(size_type count)
275 {
276 KGE_ASSERT(pos_ - count >= 0 && pos_ - count <= count_);
277 pos_ -= count;
278 return (*this);
279 }
280
281 inline const Iterator operator+(size_type count) const
282 {
283 Iterator iter(*this);
284 iter += count;
285 return iter;
286 }
287
288 inline const Iterator& operator-(size_type count) const
289 {
290 Iterator iter(*this);
291 iter -= count;
292 return iter;
293 }
294
295 inline Iterator& operator++()
296 {
297 KGE_ASSERT(pos_ < count_);
298 ++pos_;
299 return (*this);
300 }
301
302 inline Iterator operator++(int)
303 {
304 Iterator old = (*this);
305 ++(*this);
306 return old;
307 }
308
309 inline Iterator& operator--()
310 {
311 KGE_ASSERT(pos_ > 0);
312 --pos_;
313 return (*this);
314 }
315
316 inline Iterator operator--(int)
317 {
318 Iterator old = (*this);
319 --(*this);
320 return old;
321 }
322
323 inline const value_type& operator[](size_type index) const
324 {
325 Iterator iter = (*this + index);
326 return iter.ptr_[iter.pos_];
327 }
328
329 inline difference_type operator-(const Iterator& other) const
330 {
331 KGE_ASSERT(ptr_ == other.ptr_ && count_ == other.count_);
332 return static_cast<difference_type>(pos_ - other.pos_);
333 }
334
335 inline bool operator==(const Iterator& other) const
336 {
337 return ptr_ == other.ptr_ && pos_ == other.pos_ && count_ == other.count_;
338 }
339
340 inline bool operator!=(const Iterator& other) const
341 {
342 return !(*this == other);
343 }
344
345 inline bool operator<(const Iterator& other) const
346 {
347 return ptr_ < other.ptr_ || pos_ < other.pos_ || count_ < other.count_;
348 }
349
350 inline bool operator<=(const Iterator& other) const
351 {
352 return (*this < other) || (*this == other);
353 }
354
355 inline bool operator>(const Iterator& other) const
356 {
357 return !(*this <= other);
358 }
359
360 inline bool operator>=(const Iterator& other) const
361 {
362 return !(*this < other);
363 }
364
365 inline operator bool() const
366 {
367 return ptr_ != nullptr && pos_ != count_;
368 }
369 };
370
371 using const_iterator = Iterator;
372 using iterator = const_iterator;
373 using const_reverse_iterator = std::reverse_iterator<const_iterator>;
374 using reverse_iterator = const_reverse_iterator;
375
376 inline const_iterator begin() const
377 {
378 return const_iterator(ptr_, 0, count_);
379 }
380
381 inline const_iterator cbegin() const
382 {
383 return begin();
384 }
385
386 inline const_iterator end() const
387 {
388 return const_iterator(ptr_, count_, count_);
389 }
390
391 inline const_iterator cend() const
392 {
393 return end();
394 }
395
396 inline const_reverse_iterator rbegin() const
397 {
398 return const_reverse_iterator(end());
399 }
400
401 inline const_reverse_iterator crbegin() const
402 {
403 return rbegin();
404 }
405
406 inline const_reverse_iterator rend() const
407 {
408 return const_reverse_iterator(begin());
409 }
410
411 inline const_reverse_iterator crend() const
412 {
413 return rend();
414 }
415
416 inline const value_type& front() const
417 {
418 if (empty())
419 throw std::out_of_range("front() called on empty list");
420 return ptr_[0];
421 }
422
423 inline const value_type& back() const
424 {
425 if (empty())
426 throw std::out_of_range("back() called on empty list");
427 return ptr_[count_];
428 }
429
430private:
431 const value_type* ptr_;
432 size_type count_;
433};
434
435} // namespace kiwano
436
437namespace std
438{
439
440template <class _Char>
441struct hash<::kiwano::BasicStringView<_Char>>
442{
443 inline size_t operator()(const ::kiwano::BasicStringView<_Char>& v) const
444 {
445 std::hash<_Char> hasher;
446
447 size_t result = 0;
448 for (size_t i = 0; i < v.size(); ++i)
449 result = (result << 1) ^ hasher(v[i]);
450 return result;
451 }
452};
453
454} // namespace std
Definition: String.h:222
基础字符串视图
Definition: String.h:95