-
Notifications
You must be signed in to change notification settings - Fork 0
/
str.h
365 lines (294 loc) · 12.4 KB
/
str.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
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
//-----------------------------------------------------------------------------
// Application Core Library
// Copyright (c) 2009-2012 DuJardin Consulting, LLC.
// Portions Copyright (c) 2009 GarageGames, Inc.
//-----------------------------------------------------------------------------
#ifndef _ACL_STRING_H_
#define _ACL_STRING_H_
#include <cstdarg>
#ifndef _ACL_TYPES_H_
#include "core/types.h"
#endif
namespace ACLib
{
typedef UTF8 StringChar;
/// The String class represents a 0-terminated array of characters.
///
/// @note Strings are not thread-safe.
class String
{
public:
class StringData;
/// Default mode is case sensitive starting from the left
enum Mode
{
Case = 0, ///< Case sensitive
NoCase = 1, ///< Case insensitive
Left = 0, ///< Start at left end of string
Right = 2, ///< Start at right end of string
};
typedef U32 SizeType;
typedef StringChar ValueType;
static const SizeType NPos; ///< Indicates 'not found' when using find() functions
/// A predefined empty string.
static const String EmptyString;
String();
String(const String &str);
String(const StringChar *str);
String(const StringChar *str, SizeType size);
String(const UTF16 *str);
~String();
const UTF8 *c_str() const; ///< Return the string as a native type
const UTF16 *utf16() const;
const UTF8* utf8() const { return c_str(); }
SizeType length() const; ///< Returns the length of the string in bytes.
SizeType size() const; ///< Returns the length of the string in bytes including the NULL terminator.
SizeType numChars() const; ///< Returns the length of the string in characters.
bool isEmpty() const; ///< Is this an empty string [""]?
bool isNotEmpty() const { return !isEmpty(); } ///< Is this not an empty string [""]?
/// Erases all characters in a string.
void clear() { *this = EmptyString; }
bool isShared() const; ///< Is this string's reference count greater than 1?
bool isSame( const String& str ) const; ///< Return true if both strings refer to the same shared data.
U32 getHashCaseSensitive() const; ///< Get the case-sensitive hash of the string [only calculates the hash as necessary]
U32 getHashCaseInsensitive() const; ///< Get the case-insensitive hash of the string [only calculates the hash as necessary]
String& operator=(StringChar);
String& operator+=(StringChar);
String& operator=(const StringChar*);
String& operator+=(const StringChar*);
String& operator=(const String&);
String& operator+=(const String&);
/**
Compare this string with another.
@param str The string to compare against.
@param len If len is non-zero, then at most len characters are compared.
@param mode Comparison mode.
@return Difference between the first two characters that don't match.
*/
S32 compare(const StringChar *str, SizeType len = 0, U32 mode = Case|Left) const;
S32 compare(const String &str, SizeType len = 0, U32 mode = Case|Left) const; ///< @see compare(const StringChar *, SizeType, U32) const
/**
Compare two strings for equality.
It will use the string hashes to determine inequality.
@param str The string to compare against.
@param mode Comparison mode - case sensitive or not.
*/
bool equal(const String &str, U32 mode = Case) const;
SizeType find(StringChar c, SizeType pos = 0, U32 mode = Case|Left) const;
SizeType find(const StringChar *str, SizeType pos = 0, U32 mode = Case|Left) const;
SizeType find(const String &str, SizeType pos = 0, U32 mode = Case|Left) const;
String &insert(SizeType pos, const StringChar c) { return insert(pos,&c,1); }
String &insert(SizeType pos, const StringChar *str);
String &insert(SizeType pos, const String &str);
String &insert(SizeType pos, const StringChar *str, SizeType len);
String &erase(SizeType pos, SizeType len);
String &replace(SizeType pos, SizeType len, const StringChar *str);
String &replace(SizeType pos, SizeType len, const String &str);
/// Replace all occurrences of character 'c1' with 'c2'
String &replace( StringChar c1, StringChar c2 );
/// Replace all occurrences of StringData 's1' with StringData 's2'
String &replace(const String &s1, const String &s2);
String substr( SizeType pos, SizeType len = -1 ) const;
/// Remove leading and trailing whitespace.
String trim() const;
/// Return true if the string starts with the given text.
bool startsWith( const char* text ) const;
/// Return true if the string ends with the given text.
bool endsWith( const char* text ) const;
operator const StringChar*() const { return c_str(); }
StringChar operator []( U32 i ) const { return c_str()[i]; }
StringChar operator []( S32 i ) const { return c_str()[i]; }
bool operator==(const String &str) const;
bool operator!=(const String &str) const { return !(*this == str); }
bool operator==( StringChar c ) const;
bool operator!=( StringChar c ) const { return !(*this == c); }
bool operator<(const String &str) const;
bool operator>(const String &str) const;
bool operator<=(const String &str) const;
bool operator>=(const String &str) const;
friend String operator+(const String &a, StringChar c);
friend String operator+(StringChar c, const String &a);
friend String operator+(const String &a, const StringChar *b);
friend String operator+(const String &a, const String &b);
friend String operator+(const StringChar *a, const String &b);
public:
/// @name String Utility routines
/// @{
static String ToString(const char *format, ...);
static String VToString(const char* format, void* args);
static inline String ToString(U32 v) { return ToString("%u", v); }
static inline String ToString(S32 v) { return ToString("%d", v); }
static inline String ToString(S64 v) { return ToString("%d", v); }
static inline String ToString(F32 v) { return ToString("%g", v); }
static String SpanToString(const char* start, const char* end);
static String ToLower(const String &string);
static String ToUpper(const String &string);
static String GetTrailingNumber(const char* str, S32& number);
/// @}
/// @name Interning
///
/// Interning maps identical strings to unique instances so that equality
/// amounts to simple pointer comparisons.
///
/// Note that using interned strings within global destructors is not safe
/// as table destruction runs within this phase as well. Uses o interned
/// strings in global destructors is thus dependent on object file ordering.
///
/// Also, interned strings are not reference-counted. Once interned, a
/// string will persist until shutdown. This is to avoid costly concurrent
/// reference counting that would otherwise be necessary.
///
/// @{
/// Return the interned version of the string.
/// @note Interning is case-sensitive.
String intern() const;
/// Return true if this string is interned.
bool isInterned() const;
/// @}
/** An internal support class for ToString().
StrFormat manages the formatting of arbitrary length strings.
The class starts with a default internal fixed size buffer and
moves to dynamic allocation from the heap when that is exceeded.
Constructing the class on the stack will result in its most
efficient use. This class is meant to be used as a helper class,
and not for the permanent storage of string data.
@code
char* indexString(U32 index)
{
StrFormat format("Index: %d",index);
char* str = new char[format.size()];
format.copy(str);
return str;
}
@endcode
*/
class StrFormat
{
public:
StrFormat()
: _dynamicBuffer( NULL ),
_dynamicSize( 0 ),
_len( 0 )
{
_fixedBuffer[0] = '\0';
}
StrFormat(const char *formatStr, void *args)
: _dynamicBuffer( NULL ),
_dynamicSize( 0 ),
_len( 0 )
{
format(formatStr, args);
}
~StrFormat();
S32 format( const char *format, void *args );
S32 formatAppend( const char *format, void *args );
S32 append(const char * str, S32 len);
S32 append(const char * str);
String getString() { return String(c_str(),_len); }
const char * c_str() { return _dynamicBuffer ? _dynamicBuffer : _fixedBuffer; }
void reset()
{
_len = 0;
_fixedBuffer[0] = '\0';
}
/// Copy the formatted string into the output buffer which must be at least size() characters.
char *copy(char* buffer) const;
/// Return the length of the formated string (does not include the terminating 0)
U32 length() const { return _len; };
public:
char _fixedBuffer[2048]; //< Fixed size buffer
char *_dynamicBuffer; //< Temporary format buffer
U32 _dynamicSize; //< Dynamic buffer size
U32 _len; //< Len of the formatted string
};
private:
String(StringData *str)
: _string( str ) {}
// Generate compile error if operator bool is used. Without this we use
// operator const char *, which is always true...including operator bool
// causes an ambiguous cast compile error. Making it private is simply
// more insurance that it isn't used on different compilers.
// NOTE: disable on GCC since it causes hyper casting to U32 on gcc.
#ifndef ACL_COMPILER_GCC
operator const bool() const { return false; }
#endif
static void copy(StringChar *dst, const StringChar *src, U32 size);
StringData *_string;
};
// Utility class for formatting strings.
class StringBuilder
{
protected:
///
String::StrFormat mFormat;
public:
StringBuilder() {}
U32 length() const
{
return mFormat.length();
}
void copy( char* buffer ) const
{
mFormat.copy( buffer );
}
String end()
{
return mFormat.getString();
}
S32 append( char ch )
{
char str[2];
str[0]=ch;
str[1]='\0';
return mFormat.append(str);
}
S32 append( const char* str )
{
return mFormat.append(str);
}
S32 append( const String& str )
{
return mFormat.append( str.c_str(), str.length() );
}
S32 append( const char* str, U32 length )
{
return mFormat.append(str,length);
}
S32 format( const char* fmt, ... )
{
va_list args;
va_start(args, fmt);
return mFormat.formatAppend(fmt, &args);
}
};
// For use in hash tables and the like for explicitly requesting case sensitive hashing.
// Meant to only appear in hash table definition (casting will take care of the rest).
class StringCase : public String
{
public:
StringCase() : String() {}
StringCase(const String & s) : String(s) {}
};
// For use in hash tables and the like for explicitly requesting case insensitive hashing.
// Meant to only appear in hash table definition (casting will take care of the rest).
class StringNoCase : public String
{
public:
StringNoCase() : String() {}
StringNoCase(const String & s) : String(s) {}
};
class FileName : public String
{
public:
FileName() : String() {}
FileName(const String & s) : String(s) {}
FileName & operator=(const String & s) { String::operator=(s); return *this; }
};
//-----------------------------------------------------------------------------
extern String operator+(const String &a, StringChar c);
extern String operator+(StringChar c, const String &a);
extern String operator+(const String &a, const StringChar *b);
extern String operator+(const String &a, const String &b);
extern String operator+(const StringChar *a, const String &b);
};
#endif