-
-
Notifications
You must be signed in to change notification settings - Fork 21
/
Copy pathfixed_string.hpp
436 lines (371 loc) · 12.2 KB
/
fixed_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
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
#pragma once
//=========================================================================//
/*! @file
@brief 固定サイズ文字列クラス
@author 平松邦仁 ([email protected])
@copyright Copyright (C) 2017, 2024 Kunihito Hiramatsu @n
Released under the MIT license @n
https://github.com/hirakuni45/RX/blob/master/LICENSE
*/
//=========================================================================//
#include <algorithm>
#include <cstring>
#include <iterator>
#include <boost/functional/hash.hpp>
namespace utils {
//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++//
/*!
@brief 固定サイズ文字列クラス
@param[in] SIZE 文字列サイズ
*/
//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++//
template <uint32_t SIZE>
class fixed_string {
char str_[SIZE + 1];
uint32_t pos_;
static char* strncpy_(char* dst, const char* src, uint32_t n) noexcept
{
if(n == 0) return dst;
auto tmp = dst;
do {
auto ch = *src++;
*tmp++ = ch;
if(ch == 0) {
return dst;
}
} while(tmp < (dst + n)) ;
*tmp = 0;
return dst;
}
public:
//-----------------------------------------------------------------//
/*!
@brief コンストラクタ
@param[in] s 文字列
@param[in] n コピー最大数
*/
//-----------------------------------------------------------------//
constexpr fixed_string(const char* s = nullptr, uint32_t n = SIZE) noexcept : str_{ 0, }, pos_(0)
{
if(s != nullptr) {
strncpy_(str_, s, n);
str_[n] = 0;
pos_ = std::strlen(str_);
} else {
str_[0] = 0;
pos_ = 0;
}
str_[SIZE] = 0;
}
//-----------------------------------------------------------------//
/*!
@brief 格納可能な最大サイズを返す(終端の数を除外)
@return 格納可能な最大サイズ
*/
//-----------------------------------------------------------------//
uint32_t capacity() const noexcept { return SIZE; }
//-----------------------------------------------------------------//
/*!
@brief 現在のサイズを返す
@return 現在のサイズ
*/
//-----------------------------------------------------------------//
uint32_t size() const noexcept { return pos_; }
//-----------------------------------------------------------------//
/*!
@brief 空か調べる
@return 空の場合「true」
*/
//-----------------------------------------------------------------//
bool empty() const noexcept { return pos_ == 0; }
//-----------------------------------------------------------------//
/*!
@brief 文字列をクリア(リセット)
*/
//-----------------------------------------------------------------//
void clear() noexcept {
pos_ = 0;
str_[pos_] = 0;
}
//-----------------------------------------------------------------//
/*!
@brief 末尾の1要素を削除する。
*/
//-----------------------------------------------------------------//
void pop_back() noexcept {
if(pos_ > 0) {
--pos_;
str_[pos_] = 0;
}
}
//-----------------------------------------------------------------//
/*!
@brief 要素を削除する。
@param[in] org 先頭位置
@param[in] num 個数
@return 自分
*/
//-----------------------------------------------------------------//
fixed_string& erase(uint32_t org, uint32_t num) noexcept {
if(org < pos_ && (org + num) <= pos_) {
for(uint32_t i = 0; i < (pos_ - num); ++i) {
str_[org + i] = str_[org + i + num];
}
pos_ -= num;
str_[pos_] = 0;
}
return *this;
}
//-----------------------------------------------------------------//
/*!
@brief 配列の先頭
@return 配列の先頭
*/
//-----------------------------------------------------------------//
const char* begin() const noexcept { return &str_[0]; }
//-----------------------------------------------------------------//
/*!
@brief 配列の先頭
@return 配列の先頭
*/
//-----------------------------------------------------------------//
char* begin() noexcept { return &str_[0]; }
//-----------------------------------------------------------------//
/*!
@brief 配列の終端
@return 配列の終端
*/
//-----------------------------------------------------------------//
const char* end() const noexcept { return &str_[pos_]; }
//-----------------------------------------------------------------//
/*!
@brief 配列の終端
@return 配列の終端
*/
//-----------------------------------------------------------------//
char* end() noexcept { return &str_[pos_]; }
//-----------------------------------------------------------------//
/*!
@brief 末尾要素への参照を取得する。
@return 末尾要素への参照
*/
//-----------------------------------------------------------------//
char& back() noexcept {
auto pos = pos_;
if(pos > 0) --pos;
return str_[pos];
}
//-----------------------------------------------------------------//
/*!
@brief 末尾要素への参照を取得する。
@return 末尾要素への参照
*/
//-----------------------------------------------------------------//
const char& back() const noexcept {
auto pos = pos_;
if(pos > 0) --pos;
return str_[pos];
}
//-----------------------------------------------------------------//
/*!
@brief 文字列を返す
@return 文字列
*/
//-----------------------------------------------------------------//
const char* c_str() const noexcept { return str_; }
//-----------------------------------------------------------------//
/*!
@brief 交換
@param[in] src ソース
*/
//-----------------------------------------------------------------//
void swap(fixed_string& src) noexcept {
std::swap(src.str_, str_);
std::swap(src.pos_, pos_);
}
//-----------------------------------------------------------------//
/*!
@brief 代入
@param[in] src ソース
@return 自分
*/
//-----------------------------------------------------------------//
fixed_string& operator = (const char* src) noexcept {
strncpy_(str_, src, SIZE);
pos_ = std::strlen(str_);
return *this;
}
//-----------------------------------------------------------------//
/*!
@brief 代入
@param[in] src ソース
@return 自分
*/
//-----------------------------------------------------------------//
fixed_string& operator = (const fixed_string& src) noexcept {
strncpy_(str_, src.c_str(), SIZE);
pos_ = src.pos_;
return *this;
}
//-----------------------------------------------------------------//
/*!
@brief 文字を追加
@param[in] ch 文字
@return 自分
*/
//-----------------------------------------------------------------//
fixed_string& operator += (char ch) noexcept {
if(pos_ < SIZE) {
str_[pos_] = ch;
++pos_;
str_[pos_] = 0;
}
return *this;
}
//-----------------------------------------------------------------//
/*!
@brief 文字列を追加
@param[in] str 文字列
@return 自分
*/
//-----------------------------------------------------------------//
fixed_string& operator += (const char* str) noexcept {
if(str == nullptr) {
return *this;
}
uint32_t l = std::strlen(str);
if((pos_ + l) < SIZE) {
std::strcpy(&str_[pos_], str);
pos_ += l;
} else { // バッファが許す範囲でコピー
l = SIZE - pos_;
strncpy_(&str_[pos_], str, l);
pos_ = SIZE;
}
str_[pos_] = 0;
return *this;
}
//-----------------------------------------------------------------//
/*!
@brief 文字参照 @n
※範囲外ではテンポラリを返す(例外を投げない)
@param[in] pos 配列位置
@return 文字
*/
//-----------------------------------------------------------------//
char& operator [] (uint32_t pos) noexcept {
if(pos >= SIZE) {
static char tmp = 0;
return tmp;
}
return str_[pos];
}
//-----------------------------------------------------------------//
/*!
@brief 文字参照 const @n
※範囲外ではテンポラリを返す(例外を投げない)
@param[in] pos 配列位置
@return 文字
*/
//-----------------------------------------------------------------//
const char& operator [] (uint32_t pos) const noexcept {
if(pos >= SIZE) {
static char tmp = 0;
return tmp;
}
return str_[pos];
}
//-----------------------------------------------------------------//
/*!
@brief クラス一致比較
@param[in] th 文字列クラス
@return 同じなら「true」
*/
//-----------------------------------------------------------------//
int cmp(const fixed_string& th) const noexcept {
return std::strcmp(c_str(), th.c_str());
}
//-----------------------------------------------------------------//
/*!
@brief クラス一致比較(オペレーター)
@param[in] th 文字列クラス
@return 同じなら「true」
*/
//-----------------------------------------------------------------//
bool operator == (const fixed_string& th) const noexcept {
return std::strcmp(c_str(), th.c_str()) == 0;
}
//-----------------------------------------------------------------//
/*!
@brief クラス、不一致比較(オペレーター)
@param[in] th 文字列クラス
@return 同じなら「true」
*/
//-----------------------------------------------------------------//
bool operator != (const fixed_string& th) const noexcept {
return std::strcmp(c_str(), th.c_str()) != 0;
}
//-----------------------------------------------------------------//
/*!
@brief クラス大小比較(オペレーター)
@param[in] th 文字列クラス
@return 大小なら「true」
*/
//-----------------------------------------------------------------//
bool operator > (const fixed_string& th) const noexcept {
return std::strcmp(c_str(), th.c_str()) > 0;
}
//-----------------------------------------------------------------//
/*!
@brief クラス小大比較(オペレーター)
@param[in] th 文字列クラス
@return 小大なら「true」
*/
//-----------------------------------------------------------------//
bool operator < (const fixed_string& th) const noexcept {
return std::strcmp(c_str(), th.c_str()) < 0;
}
//-----------------------------------------------------------------//
/*!
@brief クラス大小一致比較(オペレーター)
@param[in] th 文字列
@return 大小一致なら「true」
*/
//-----------------------------------------------------------------//
bool operator >= (const fixed_string& th) const noexcept {
return std::strcmp(c_str(), th.c_str()) >= 0;
}
//-----------------------------------------------------------------//
/*!
@brief クラス小大一致比較(オペレーター)
@param[in] th 文字列クラス
@return 小大一致なら「true」
*/
//-----------------------------------------------------------------//
bool operator <= (const fixed_string& th) const noexcept {
return std::strcmp(c_str(), th.c_str()) <= 0;
}
//-----------------------------------------------------------------//
/*!
@brief ハッシュ値の計算
@return ハッシュ値
*/
//-----------------------------------------------------------------//
size_t hash() const noexcept
{
size_t h = 0;
for(uint32_t i = 0; i < pos_; ++i) {
boost::hash_combine(h, str_[i]);
}
return h;
}
};
typedef fixed_string<8> STR8;
typedef fixed_string<16> STR16;
typedef fixed_string<32> STR32;
typedef fixed_string<64> STR64;
typedef fixed_string<128> STR128;
typedef fixed_string<256> STR256;
template <class T>
inline size_t hash_value(const T& t) { return t.hash(); }
}