Public Functions
operator+(const String & a, const String & b)
operator+(const String & a, const StringChar * b)
operator+(const String & a, StringChar c)
operator+(const StringChar * a, const String & b)
operator+(StringChar c, const String & a)
1
2//-----------------------------------------------------------------------------
3// Copyright (c) 2012 GarageGames, LLC
4//
5// Permission is hereby granted, free of charge, to any person obtaining a copy
6// of this software and associated documentation files (the "Software"), to
7// deal in the Software without restriction, including without limitation the
8// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
9// sell copies of the Software, and to permit persons to whom the Software is
10// furnished to do so, subject to the following conditions:
11//
12// The above copyright notice and this permission notice shall be included in
13// all copies or substantial portions of the Software.
14//
15// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
20// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
21// IN THE SOFTWARE.
22//-----------------------------------------------------------------------------
23
24#ifndef _TORQUE_STRING_H_
25#define _TORQUE_STRING_H_
26
27#include <cstdarg>
28
29#ifndef _TORQUE_TYPES_H_
30#include "platform/types.h"
31#endif
32
33
34template< class T > class Vector;
35
36
37typedef UTF8 StringChar;
38
39
40/// The String class represents a 0-terminated array of characters.
41class String
42{
43public:
44 class StringData;
45
46 /// Default mode is case sensitive starting from the left
47 enum Mode
48 {
49 Case = 0, ///< Case sensitive
50 NoCase = 1, ///< Case insensitive
51 Left = 0, ///< Start at left end of string
52 Right = 2, ///< Start at right end of string
53 };
54
55 typedef U32 SizeType;
56 typedef StringChar ValueType;
57
58 static const SizeType NPos; ///< Indicates 'not found' when using find() functions
59
60 /// A predefined empty string.
61 static const String EmptyString;
62
63 String();
64 String(const String &str);
65 String(const StringChar *str);
66 String(const StringChar *str, SizeType size); ///< Copy from raw data
67 String(const UTF16 *str);
68 ~String();
69
70 const UTF8 *c_str() const; ///< Return the string as a native type
71 const UTF16 *utf16() const;
72 const UTF8* utf8() const { return c_str(); }
73
74 SizeType length() const; ///< Returns the length of the string in bytes.
75 SizeType size() const; ///< Returns the length of the string in bytes including the NULL terminator.
76 SizeType numChars() const; ///< Returns the length of the string in characters.
77 bool isEmpty() const; ///< Is this an empty string [""]?
78 static bool isEmpty(const char*); // is the input empty?
79 bool isNotEmpty() const { return !isEmpty(); } ///< Is this not an empty string [""]?
80
81 /// Erases all characters in a string.
82 void clear() { *this = EmptyString; }
83
84 bool isShared() const; ///< Is this string's reference count greater than 1?
85 bool isSame( const String& str ) const; ///< Return true if both strings refer to the same shared data.
86
87 U32 getHashCaseSensitive() const; ///< Get the case-sensitive hash of the string [only calculates the hash as necessary]
88 U32 getHashCaseInsensitive() const; ///< Get the case-insensitive hash of the string [only calculates the hash as necessary]
89
90 String& operator=(StringChar);
91 String& operator+=(StringChar);
92 String& operator=(const StringChar*);
93 String& operator+=(const StringChar*);
94 String& operator=(const String&);
95 String& operator+=(const String&);
96
97 /**
98 Compare this string with another.
99 @param str The string to compare against.
100 @param len If len is non-zero, then at most len characters are compared.
101 @param mode Comparison mode.
102 @return Difference between the first two characters that don't match.
103 */
104 S32 compare(const StringChar *str, SizeType len = 0, U32 mode = Case</a>|<a href="/coding/class/classstring/#classstring_1ad23530ba3c445d964722346a3c80771da84aa4530ee3fa8bfa8e0c2305744bff8">Left) const;
105 S32 compare(const String &str, SizeType len = 0, U32 mode = Case</a>|<a href="/coding/class/classstring/#classstring_1ad23530ba3c445d964722346a3c80771da84aa4530ee3fa8bfa8e0c2305744bff8">Left) const; ///< @see compare(const StringChar *, SizeType, U32) const
106
107 /**
108 Compare two strings for equality.
109 It will use the string hashes to determine inequality.
110 @param str The string to compare against.
111 @param mode Comparison mode - case sensitive or not.
112 */
113 bool equal(const String &str, U32 mode = Case) const;
114
115 SizeType find(StringChar c, SizeType pos = 0, U32 mode = Case</a>|<a href="/coding/class/classstring/#classstring_1ad23530ba3c445d964722346a3c80771da84aa4530ee3fa8bfa8e0c2305744bff8">Left) const;
116 SizeType find(const StringChar *str, SizeType pos = 0, U32 mode = Case</a>|<a href="/coding/class/classstring/#classstring_1ad23530ba3c445d964722346a3c80771da84aa4530ee3fa8bfa8e0c2305744bff8">Left) const;
117 SizeType find(const String &str, SizeType pos = 0, U32 mode = Case</a>|<a href="/coding/class/classstring/#classstring_1ad23530ba3c445d964722346a3c80771da84aa4530ee3fa8bfa8e0c2305744bff8">Left) const;
118
119 String &insert(SizeType pos, const StringChar c) { return insert(pos,&c,1); }
120 String &insert(SizeType pos, const StringChar *str);
121 String &insert(SizeType pos, const String &str);
122 String &insert(SizeType pos, const StringChar *str, SizeType len);
123
124 String &erase(SizeType pos, SizeType len);
125
126 String &replace(SizeType pos, SizeType len, const StringChar *str);
127 String &replace(SizeType pos, SizeType len, const String &str);
128
129 /// Replace all occurrences of character 'c1' with 'c2'
130 String &replace( StringChar c1, StringChar c2 );
131
132 /// Replace all occurrences of StringData 's1' with StringData 's2'
133 String &replace(const String &s1, const String &s2);
134
135 String substr( SizeType pos, SizeType len = -1 ) const;
136
137 /// Remove leading and trailing whitespace.
138 String trim() const;
139
140 /// Replace all characters that need to be escaped for the string to be a valid string literal with their
141 /// respective escape sequences.
142 String expandEscapes() const;
143
144 /// Replace all escape sequences in with their respective character codes.
145 String collapseEscapes() const;
146
147 /// Split the string into its components separated by the given delimiter.
148 void split( const char* delimiter, Vector< String>& outElements ) const;
149
150 /// Return true if the string starts with the given text.
151 bool startsWith( const char* text ) const;
152
153 /// Return true if the string ends with the given text.
154 bool endsWith( const char* text ) const;
155
156 operator const StringChar*() const { return c_str(); }
157
158 StringChar operator []( U32 i ) const { return c_str()[i]; }
159 StringChar operator []( S32 i ) const { return c_str()[i]; }
160
161 bool operator==(const String &str) const;
162 bool operator!=(const String &str) const { return !(*this == str); }
163 bool operator==( StringChar c ) const;
164 bool operator!=( StringChar c ) const { return !(*this == c); }
165 bool operator<(const String &str) const;
166 bool operator>(const String &str) const;
167 bool operator<=(const String &str) const;
168 bool operator>=(const String &str) const;
169
170 friend String operator+(const String &a, StringChar c);
171 friend String operator+(StringChar c, const String &a);
172 friend String operator+(const String &a, const StringChar *b);
173 friend String operator+(const String &a, const String &b);
174 friend String operator+(const StringChar *a, const String &b);
175
176public:
177 /// @name String Utility routines
178 /// @{
179
180 static String ToString(const char *format, ...);
181 static String VToString(const char* format, va_list args);
182
183 static String ToString( bool v );
184 static inline String ToString( U32 v ) { return ToString( "%u", v ); }
185 static inline String ToString( S32 v ) { return ToString( "%d", v ); }
186 static inline String ToString( F32 v ) { return ToString( "%g", v ); }
187 static inline String ToString( F64 v ) { return ToString( "%Lg", v ); }
188
189 static String SpanToString(const char* start, const char* end);
190
191 static String ToLower(const String &string);
192 static String ToUpper(const String &string);
193
194 static String GetTrailingNumber(const char* str, S32& number);
195 static String GetFirstNumber(const char* str, U32& startPos, U32& endPos);
196
197 /// @}
198
199 /// @name Interning
200 ///
201 /// Interning maps identical strings to unique instances so that equality
202 /// amounts to simple pointer comparisons.
203 ///
204 /// Note that using interned strings within global destructors is not safe
205 /// as table destruction runs within this phase as well. Uses o interned
206 /// strings in global destructors is thus dependent on object file ordering.
207 ///
208 /// Also, interned strings are not reference-counted. Once interned, a
209 /// string will persist until shutdown. This is to avoid costly concurrent
210 /// reference counting that would otherwise be necessary.
211 ///
212 /// @{
213
214 /// Return the interned version of the string.
215 /// @note Interning is case-sensitive.
216 String intern() const;
217
218 /// Return true if this string is interned.
219 bool isInterned() const;
220
221 /// @}
222
223 /** An internal support class for ToString().
224 StrFormat manages the formatting of arbitrary length strings.
225 The class starts with a default internal fixed size buffer and
226 moves to dynamic allocation from the heap when that is exceeded.
227 Constructing the class on the stack will result in its most
228 efficient use. This class is meant to be used as a helper class,
229 and not for the permanent storage of string data.
230 @code
231 char* indexString(U32 index)
232 {
233 StrFormat format("Index: %d",index);
234 char* str = new char[format.size()];
235 format.copy(str);
236 return str;
237 }
238 @endcode
239 */
240 class StrFormat
241 {
242 public:
243 StrFormat()
244 : _dynamicBuffer( NULL ),
245 _dynamicSize( 0 ),
246 _len( 0 )
247 {
248 _fixedBuffer[0] = '\0';
249 }
250
251 StrFormat(const char *formatStr, va_list args)
252 : _dynamicBuffer( NULL ),
253 _dynamicSize( 0 ),
254 _len( 0 )
255 {
256 format(formatStr, args);
257 }
258
259 ~StrFormat();
260
261 S32 format( const char *format, va_list args );
262 S32 formatAppend( const char *format, va_list args );
263 S32 append(const char * str, S32 len);
264 S32 append(const char * str);
265
266 String getString() { return String(c_str(),_len); }
267
268 const char * c_str() const { return _dynamicBuffer ? _dynamicBuffer : _fixedBuffer; }
269
270 void reset()
271 {
272 _len = 0;
273 _fixedBuffer[0] = '\0';
274 }
275
276 /// Copy the formatted string into the output buffer which must be at least size() characters.
277 char *copy(char* buffer) const;
278
279 /// Return the length of the formated string (does not include the terminating 0)
280 U32 length() const { return _len; };
281
282 public:
283 char _fixedBuffer[2048]; //< Fixed size buffer
284 char *_dynamicBuffer; //< Temporary format buffer
285 U32 _dynamicSize; //< Dynamic buffer size
286 U32 _len; //< Len of the formatted string
287 };
288
289private:
290 String(StringData *str)
291 : _string( str ) {}
292
293 // Generate compile error if operator bool is used. Without this we use
294 // operator const char *, which is always true...including operator bool
295 // causes an ambiguous cast compile error. Making it private is simply
296 // more insurance that it isn't used on different compilers.
297 // NOTE: disable on GCC since it causes hyper casting to U32 on gcc.
298#if !defined(TORQUE_COMPILER_GCC) && !defined(__clang__)
299 operator const bool() const { return false; }
300#endif
301
302 static void copy(StringChar *dst, const StringChar *src, U32 size);
303
304 StringData *_string;
305};
306
307// Utility class for formatting strings.
308class StringBuilder
309{
310 protected:
311
312 ///
313 String::StrFormat mFormat;
314
315 public:
316
317 StringBuilder() {}
318
319 U32 length() const
320 {
321 return mFormat.length();
322 }
323
324 void copy( char* buffer ) const
325 {
326 mFormat.copy( buffer );
327 }
328
329 const char* data() const
330 {
331 return mFormat.c_str();
332 }
333
334 String end()
335 {
336 return mFormat.getString();
337 }
338
339 S32 append( char ch )
340 {
341 char str[2];
342 str[0]=ch;
343 str[1]='\0';
344 return mFormat.append(str);
345 }
346 S32 append( const char* str )
347 {
348 return mFormat.append(str);
349 }
350 S32 append( const String& str )
351 {
352 return mFormat.append( str.c_str(), str.length() );
353 }
354 S32 append( const char* str, U32 length )
355 {
356 return mFormat.append(str,length);
357 }
358 S32 format( const char* fmt, ... )
359 {
360 va_list args;
361 va_start(args, fmt);
362 return mFormat.formatAppend(fmt, args);
363 }
364};
365
366// For use in hash tables and the like for explicitly requesting case sensitive hashing.
367// Meant to only appear in hash table definition (casting will take care of the rest).
368class StringCase : public String
369{
370public:
371 StringCase() : String() {}
372 StringCase(const String & s) : String(s) {}
373};
374
375// For use in hash tables and the like for explicitly requesting case insensitive hashing.
376// Meant to only appear in hash table definition (casting will take care of the rest).
377class StringNoCase : public String
378{
379public:
380 StringNoCase() : String() {}
381 StringNoCase(const String & s) : String(s) {}
382};
383
384class FileName : public String
385{
386public:
387 FileName() : String() {}
388 FileName(const String & s) : String(s) {}
389 FileName & operator=(const String & s) { String::operator=(s); return *this; }
390};
391
392//-----------------------------------------------------------------------------
393
394extern String operator+(const String &a, StringChar c);
395extern String operator+(StringChar c, const String &a);
396extern String operator+(const String &a, const StringChar *b);
397extern String operator+(const String &a, const String &b);
398extern String operator+(const StringChar *a, const String &b);
399
400#endif
401
402