Vault
4.1
|
00001 /* 00002 Copyright c1997-2014 Trygve Isaacson. All rights reserved. 00003 This file is part of the Code Vault version 4.1 00004 http://www.bombaydigital.com/ 00005 License: MIT. See LICENSE.md in the Vault top level directory. 00006 */ 00007 00008 #ifndef vstring_h 00009 #define vstring_h 00010 00013 #include "vtypes.h" 00014 00015 #include "vcodepoint.h" 00016 #include "vstringiterator.h" 00017 00018 class VChar; 00019 00024 typedef std::vector<VString> VStringVector; 00028 typedef std::vector<VString*> VStringPtrVector; 00029 00030 #ifndef V_EFFICIENT_SPRINTF 00031 class VMutex; 00032 #endif 00033 00034 #ifdef VAULT_QT_SUPPORT 00035 #include <qstring.h> 00036 #endif 00037 00060 /* 00061 Best practices for VString creation: 00062 00063 - To pass a temporary VString constructed with vararg formatting, use VSTRING_FORMAT: 00064 functionThatTakesAString(VSTRING_FORMAT("my %s format %d string", "hey!", 42)); 00065 00066 - To construct a local or instance variable with vararg formatting, use VSTRING_ARGS: 00067 VString s(VSTRING_ARGS("my %s format %d string", "hey!", 42)); 00068 ... mMyInstanceVar(VSTRING_ARGS("my %s format %d string", "hey!", 42)) ... 00069 00070 - To simply construct a VString from a literal, you can just supply the literal, but 00071 if you care about optimizing compatibility "non-strict" formatting, you may prefer 00072 to use VSTRING_COPY. It depends whether you are assigning or initializing. Initializing 00073 does not benefit from this. 00074 VString x("my string literal"); 00075 VString y = VSTRING_COPY("my literal"); 00076 00077 - Where you may want to future-proof to distinguish between making a copy of a temporary 00078 buffer vs. simply referring to a literal (a feature I have been expirimenting with to 00079 determine feasibility), use VSTRING_COPY to indicate that a copy must be made. Notice 00080 the difference between this and the simple literal constructor above; in theory, the 00081 literal does not need to be copied, but here we do need to copy because the temp buffer 00082 may live a shorter life than the string. 00083 VString s = VSTRING_COPY(some_temp_buffer_returned_by_a_system_api); 00084 00085 - So in fact the above is a good distinction: 00086 If constructing with a literal, just pass it in unadorned. 00087 If constructing with a temporary char* buffer, wrap it with VSTRING_COPY to ensure 00088 copying if I later optimize away literal copying. (This is the dilemma; how do I know 00089 what the pointer points to?) 00090 */ 00091 00092 #ifdef VAULT_VSTRING_STRICT_FORMATTING 00093 #define VSTRING_FORMAT(format_string, ...) VString(0, format_string, __VA_ARGS__) 00094 #define VSTRING_ARGS(format_string, ...) true, format_string, __VA_ARGS__ 00095 #define VSTRING_COPY(literal_string) VString(literal_string) 00096 #else 00097 #define VSTRING_FORMAT(format_string, ...) VString(format_string, __VA_ARGS__) 00098 #define VSTRING_ARGS(format_string, ...) format_string, __VA_ARGS__ 00099 #define VSTRING_COPY(literal_string) VString((char*)literal_string) // call non-formatting ctor 00100 #endif 00101 00102 // The following macros define the proper formatting directives for the basic POD types, 00103 // and VString constructors for converting those types to strings. For convenience, we 00104 // also define a boolean string constructor. 00105 // My advice and practice in Vault code: 00106 // - %s (char*), and %c (char) are pervasively well-understood and should be used as is. Often %d as well. 00107 // - The other formatters are provided here and should usually be used by name for clarity, except where 00108 // their presence makes code less understandable because of verbosity. 00109 // For example: 00110 // VSTRING_FORMAT("Hello, %s.", p->getName().chars()); <-- No need to avoid using %s for (char*) values. 00111 // VSTRING_FORMAT("Answer is %d.", 42); <-- No need to avoid using %d for int values. 00112 // VSTRING_FORMAT("Vector size is " VSTRING_FORMATTER_SIZE, vec.size()); <-- Useful because size_t formatting is sketchy. 00113 // VSTRING_FORMAT("My 32-bit value is " VSTRING_FORMATTER_S32, myVs32Value); <-- Useful because 32-bit int formatter may depend on compiler mode. 00114 // VSTRING_FORMAT("Jumbo 64-bit size is " VSTRING_FORMATTER_S64, myVs64Value); <-- Useful because 64-bit int formatter may depend on compiler mode. 00115 // VSTRING_FORMAT("Result dimensions: %lld*%lld*%lld", x, y, z); <-- Code would be less readable if VSTRING_FORMATTER_S64 were used 3x here, but this is not totally correct on unusual 64-bit platforms. 00116 00117 #define VSTRING_FORMATTER_INT "%d" 00118 #define VSTRING_FORMATTER_UINT "%u" 00119 #define VSTRING_FORMATTER_LONG "%ld" 00120 #define VSTRING_FORMATTER_ULONG "%lu" 00121 #ifdef VCOMPILER_MSVC 00122 #define VSTRING_FORMATTER_SIZE "%Iu" // VC++ libraries do not conform to IEEE1003.1 here. 00123 #else 00124 #define VSTRING_FORMATTER_SIZE "%zu" 00125 #endif 00126 #define VSTRING_FORMATTER_S8 "%hhd" // Note: %hhd is not universally supported; converting value to other type may be better. 00127 #define VSTRING_FORMATTER_U8 "%hhu" // Note: %hhu is not universally supported; converting value to other type may be better. 00128 #define VSTRING_FORMATTER_S16 "%hd" 00129 #define VSTRING_FORMATTER_U16 "%hu" 00130 00131 #ifdef Vx32_IS_xINT /* Don't redefine if types are same; else form is untested environment. */ 00132 #define VSTRING_FORMATTER_S32 VSTRING_FORMATTER_INT 00133 #define VSTRING_FORMATTER_U32 VSTRING_FORMATTER_UINT 00134 #else 00135 #define VSTRING_FORMATTER_S32 VSTRING_FORMATTER_LONG 00136 #define VSTRING_FORMATTER_U32 VSTRING_FORMATTER_ULONG 00137 #endif 00138 00139 #ifdef Vx64_IS_xINT /* Don't redefine if types are same; else form is normal environment. */ 00140 #define VSTRING_FORMATTER_S64 VSTRING_FORMATTER_INT 00141 #define VSTRING_FORMATTER_U64 VSTRING_FORMATTER_UINT 00142 #else 00143 #define VSTRING_FORMATTER_S64 "%lld" 00144 #define VSTRING_FORMATTER_U64 "%llu" 00145 #endif 00146 00147 #define VSTRING_FORMATTER_FLOAT "%f" 00148 #define VSTRING_FORMATTER_DOUBLE "%lf" 00149 #define VSTRING_FORMATTER_PTR "%p" 00150 00151 // Consider these macros a public API for declaring strings that are built by converting integers 00152 // of various sizes, etc. This is preferable to specifying the proper formatting directives manually. 00153 #define VSTRING_INT(n) VSTRING_FORMAT(VSTRING_FORMATTER_INT, n) ///< Creates a string by formatting an int value. 00154 #define VSTRING_UINT(n) VSTRING_FORMAT(VSTRING_FORMATTER_UINT, n) ///< Creates a string by formatting an unsigned int value. 00155 #define VSTRING_LONG(n) VSTRING_FORMAT(VSTRING_FORMATTER_LONG, n) ///< Creates a string by formatting a long value. 00156 #define VSTRING_ULONG(n) VSTRING_FORMAT(VSTRING_FORMATTER_ULONG, n) ///< Creates a string by formatting an unsigned long value. 00157 #define VSTRING_SIZE(z) VSTRING_FORMAT(VSTRING_FORMATTER_SIZE, z) ///< Creates a string by formatting a size_t value. 00158 #define VSTRING_S8(n) VSTRING_FORMAT(VSTRING_FORMATTER_S8, n) ///< Creates a string by formatting an 8-bit int value. 00159 #define VSTRING_U8(n) VSTRING_FORMAT(VSTRING_FORMATTER_U8, n) ///< Creates a string by formatting an unsigned 8-bit int value. 00160 #define VSTRING_S16(n) VSTRING_FORMAT(VSTRING_FORMATTER_S16, n) ///< Creates a string by formatting a 16-bit int value. 00161 #define VSTRING_U16(n) VSTRING_FORMAT(VSTRING_FORMATTER_U16, n) ///< Creates a string by formatting an unsigned 16-bit int value. 00162 #define VSTRING_S32(n) VSTRING_FORMAT(VSTRING_FORMATTER_S32, n) ///< Creates a string by formatting a 32-bit int value. 00163 #define VSTRING_U32(n) VSTRING_FORMAT(VSTRING_FORMATTER_U32, n) ///< Creates a string by formatting an unsigned 32-bit int value. 00164 #define VSTRING_S64(n) VSTRING_FORMAT(VSTRING_FORMATTER_S64, n) ///< Creates a string by formatting a 64-bit int value. 00165 #define VSTRING_U64(n) VSTRING_FORMAT(VSTRING_FORMATTER_U64, n) ///< Creates a string by formatting an unsigned 64-bit int value. 00166 #define VSTRING_FLOAT(n) VSTRING_FORMAT(VSTRING_FORMATTER_FLOAT, n) ///< Creates a string by formatting a float value. 00167 #define VSTRING_DOUBLE(n) VSTRING_FORMAT(VSTRING_FORMATTER_DOUBLE, n) ///< Creates a string by formatting a double value. 00168 #define VSTRING_PTR(p) VSTRING_FORMAT(VSTRING_FORMATTER_PTR, p) ///< Creates a string by formatting a pointer as hexadecimal preceded by 0x. 00169 #define VSTRING_BOOL(b) VString(b ? "true" : "false") ///< Creates a string from a boolean as the text "true" or "false". 00170 00189 class VString { 00190 public: 00191 00195 static const VString& EMPTY(); 00204 static const VString& NATIVE_LINE_ENDING(); 00209 static const VString& UNIX_LINE_ENDING(); 00214 static const VString& MAC_CLASSIC_LINE_ENDING(); 00218 static const VString& DOS_LINE_ENDING(); 00219 00223 VString(); 00228 VString(const VChar& c); 00233 VString(const VString& s); 00240 explicit VString(char c); 00247 #ifdef VAULT_VSTRING_STRICT_FORMATTING 00248 VString(const char* s); 00249 #else /* non-strict formatting */ 00250 //lint -e1776 Converting a string literal to char * is not const safe [OK: Intentionally non-const to disambiguate API; function treats parameter as const.] 00251 VString(char* s); 00252 #endif /* VAULT_VSTRING_STRICT_FORMATTING */ 00253 00254 #ifdef VAULT_VARARG_STRING_FORMATTING_SUPPORT 00255 00263 #ifdef VAULT_VSTRING_STRICT_FORMATTING 00264 VString(Vs8 dummy, const char* formatText, ...); 00265 #else /* non-strict formatting */ 00266 VString(const char* formatText, ...); 00267 #endif /* VAULT_VSTRING_STRICT_FORMATTING */ 00268 00269 #endif /* VAULT_VARARG_STRING_FORMATTING_SUPPORT */ 00270 00275 VString(const std::wstring& ws); 00276 00277 #ifdef VAULT_QT_SUPPORT 00278 00282 VString(const QString& s); 00283 #endif 00284 00285 #ifdef VAULT_BOOST_STRING_FORMATTING_SUPPORT 00286 00290 VString(const boost::format& fmt); 00291 #endif 00292 00293 #ifdef VAULT_CORE_FOUNDATION_SUPPORT 00294 00298 VString(const CFStringRef& s); 00299 #endif 00300 00304 VString(const VCodePoint& cp); 00305 00309 ~VString(); 00310 00315 VString& operator=(const VString& s); 00320 VString& operator=(const VString* s); 00321 00322 #ifdef VAULT_QT_SUPPORT 00323 00327 VString& operator=(const QString& s); 00328 #endif 00329 00330 #ifdef VAULT_BOOST_STRING_FORMATTING_SUPPORT 00331 00335 VString& operator=(const boost::format& fmt); 00336 #endif 00337 00338 #ifdef VAULT_CORE_FOUNDATION_SUPPORT 00339 00343 VString& operator=(const CFStringRef& s); 00344 #endif 00345 00349 VString& operator=(const VCodePoint& cp); 00350 00355 VString& operator=(const VChar& c); 00360 VString& operator=(char c); 00365 VString& operator=(const char* s); 00370 VString& operator=(const std::wstring& ws); 00375 VString& operator=(int i); 00380 VString& operator=(Vu8 i); 00385 VString& operator=(Vs8 i); 00390 VString& operator=(Vu16 i); 00395 VString& operator=(Vs16 i); 00400 VString& operator=(Vu32 i); 00401 00402 #ifndef Vx32_IS_xINT /* don't redefine if types are same */ 00403 00407 VString& operator=(Vs32 i); 00408 #endif /* not Vx32_IS_xINT */ 00409 00414 VString& operator=(Vu64 i); 00415 00416 #ifndef Vx64_IS_xINT /* don't redefine if types are same */ 00417 00421 VString& operator=(Vs64 i); 00422 #endif /* not Vx64_IS_xINT */ 00423 00428 VString& operator=(VDouble d); 00429 00430 00435 VString operator+(const char c) const; 00440 VString operator+(const char* s) const; 00445 VString operator+(const std::wstring& ws) const; 00450 VString operator+(const VString& s) const; 00451 00452 #ifdef VAULT_BOOST_STRING_FORMATTING_SUPPORT 00453 00457 VString operator+(const boost::format& fmt) const; 00458 #endif 00459 00463 VString operator+(const VCodePoint& cp) const; 00464 00469 VString& operator+=(const VChar& c); 00474 VString& operator+=(const VString& s); 00479 VString& operator+=(char c); 00484 VString& operator+=(const char* s); 00489 VString& operator+=(const std::wstring& ws); 00490 00491 #ifdef VAULT_BOOST_STRING_FORMATTING_SUPPORT 00492 00496 VString& operator+=(const boost::format& fmt); 00497 #endif 00498 00502 VString& operator+=(const VCodePoint& cp); 00503 00508 VString& operator+=(int i); 00513 VString& operator+=(Vu8 i); 00518 VString& operator+=(Vs8 i); 00523 VString& operator+=(Vu16 i); 00528 VString& operator+=(Vs16 i); 00533 VString& operator+=(Vu32 i); 00534 #ifndef Vx32_IS_xINT /* don't redefine if types are same */ 00535 00539 VString& operator+=(Vs32 i); 00540 #endif /* not Vx32_IS_xINT */ 00541 00545 VString& operator+=(Vu64 i); 00546 #ifndef Vx64_IS_xINT /* don't redefine if types are same */ 00547 00551 VString& operator+=(Vs64 i); 00552 #endif /* not Vx64_IS_xINT */ 00553 00557 VString& operator+=(VDouble f); 00562 void readFromIStream(std::istream& in); 00567 void appendFromIStream(std::istream& in); 00568 00569 typedef VStringIterator<VString&> iterator; 00570 typedef VStringIterator<const VString&> const_iterator; 00571 typedef VStringIterator<VString&> reverse_iterator; 00572 typedef VStringIterator<const VString&> const_reverse_iterator; 00573 00574 iterator begin(); 00575 const_iterator begin() const; 00576 iterator end(); 00577 const_iterator end() const; 00578 00579 reverse_iterator rbegin(); 00580 const_reverse_iterator rbegin() const; 00581 reverse_iterator rend(); 00582 const_reverse_iterator rend() const; 00583 00584 #ifdef VAULT_VARARG_STRING_FORMATTING_SUPPORT 00585 00590 void format(const char* formatText, ...); 00591 #endif 00592 00605 void insert(const VCodePoint& cp, const VString::iterator& position); 00618 void insert(const VString& s, const VString::iterator& position); 00630 void insert(char c, const VString::iterator& position); 00631 00641 void insert(const VCodePoint& cp, int offset = 0); 00652 void insert(const VString& s, int offset = 0); 00662 void insert(char c, int offset = 0); 00663 00669 int getNumCodePoints() const; 00675 int length() const; 00681 void truncateCodePoints(int maxNumCodePoints); 00687 void truncateLength(int maxLength); 00692 bool isEmpty() const; 00697 bool isNotEmpty() const; 00704 VChar at(int i) const; 00711 VChar operator[](int i) const; 00719 char& operator[](int i); 00726 char charAt(int i) const; 00733 operator const char*() const; 00750 const char* chars() const; 00751 00757 std::wstring toUTF16() const; 00758 00759 #ifdef VAULT_QT_SUPPORT 00760 00764 QString qstring() const; 00765 #endif 00766 00767 #ifdef VAULT_CORE_FOUNDATION_SUPPORT 00768 00774 CFStringRef cfstring() const; 00775 #endif 00776 00783 bool equalsIgnoreCase(const VString& s) const; 00790 bool equalsIgnoreCase(const char* s) const; 00797 int compare(const VString& s) const; 00804 int compare(const char* s) const; 00811 int compareIgnoreCase(const VString& s) const; 00818 int compareIgnoreCase(const char* s) const; 00824 bool startsWith(const VString& s) const; 00830 bool startsWithIgnoreCase(const VString& s) const; 00836 bool startsWith(const VCodePoint& cp) const; 00842 bool startsWith(char c) const; 00848 bool endsWith(const VString& s) const; 00854 bool endsWithIgnoreCase(const VString& s) const; 00860 bool endsWith(const VCodePoint& cp) const; 00866 bool endsWith(char c) const; 00873 VString::const_iterator find(const VCodePoint& cp) const; 00874 VString::iterator find(const VCodePoint& cp); 00886 VString::const_iterator find(const VCodePoint& cp, const VString::const_iterator& startPosition, const VString::const_iterator& endPosition) const; 00887 VString::iterator find(const VCodePoint& cp, const VString::iterator& startPosition, const VString::iterator& endPosition); 00894 int indexOf(char c, int fromIndex = 0) const; 00902 int indexOfIgnoreCase(char c, int fromIndex = 0) const; 00909 int indexOf(const VString& s, int fromIndex = 0) const; 00917 int indexOfIgnoreCase(const VString& s, int fromIndex = 0) const; 00925 int lastIndexOf(char c, int fromIndex = -1) const; 00934 int lastIndexOfIgnoreCase(char c, int fromIndex = -1) const; 00942 int lastIndexOf(const VString& s, int fromIndex = -1) const; 00951 int lastIndexOfIgnoreCase(const VString& s, int fromIndex = -1) const; 00965 bool regionMatches(int thisIndex, const VString& otherString, int otherIndex, int regionLength, bool caseSensitive = true) const; 00972 bool contains(char c, int fromIndex = 0) const; 00980 bool containsIgnoreCase(char c, int fromIndex = 0) const; 00987 bool contains(const VString& s, int fromIndex = 0) const; 00995 bool containsIgnoreCase(const VString& s, int fromIndex = 0) const; 01005 int replace(const VString& searchString, const VString& replacementString, bool caseSensitiveSearch = true); 01015 int replace(const VCodePoint& searchChar, const VCodePoint& replacementChar, bool caseSensitiveSearch = true); 01016 01020 void toLowerCase(); 01024 void toUpperCase(); 01034 int parseInt() const; 01043 Vs64 parseS64() const; 01052 Vu64 parseU64() const; 01059 VDouble parseDouble() const; 01066 void set(int i, const VChar& c); 01078 void getSubstring(VString& toString, int startIndex/* = 0*/, int endIndex = -1) const; 01079 void getSubstring(VString& toString, VString::const_iterator rangeStart, VString::const_iterator rangeEnd) const; 01095 void substringInPlace(int startIndex/* = 0*/, int endIndex = -1); 01108 void split(VStringVector& result, const VCodePoint& delimiter, int limit = 0, bool stripTrailingEmpties = true) const; 01120 VStringVector split(const VCodePoint& delimiter, int limit = 0, bool stripTrailingEmpties = true) const; 01126 void trim(); 01135 void copyToBuffer(char* toBuffer, int bufferSize) const; 01143 void copyFromBuffer(const char* fromBuffer, int startIndex, int endIndex); 01148 void copyFromCString(const char* fromBuffer); 01156 void copyToPascalString(char* pascalBuffer) const; 01161 void copyFromPascalString(const char* pascalBuffer); 01169 void setFourCharacterCode(Vu32 fourCharacterCode); 01176 Vu32 getFourCharacterCode() const; 01177 01178 #ifdef VAULT_VARARG_STRING_FORMATTING_SUPPORT 01179 01185 void vaFormat(const char* formatText, va_list args); 01186 #endif 01187 01194 void preflight(int stringLength); 01201 void preflightWithSimulatedFailure(); 01210 char* buffer(); 01222 Vu8* getDataBuffer(); 01230 const Vu8* getDataBufferConst() const; 01243 char* orphanDataBuffer(); 01251 void postflight(int stringLength); 01252 01253 friend inline bool operator==(const VString& lhs, const VString& rhs); 01254 friend inline bool operator==(const VString& lhs, const char* rhs); 01255 friend inline bool operator==(const char* lhs, const VString& rhs); 01256 friend inline bool operator==(const VString& lhs, char rhs); 01257 01258 friend inline bool operator!=(const VString& lhs, const VString& rhs); 01259 friend inline bool operator!=(const VString& lhs, const char* rhs); 01260 friend inline bool operator!=(const char* lhs, const VString& rhs); 01261 friend inline bool operator!=(const VString& lhs, char rhs); 01262 01263 friend inline bool operator<(const VString& lhs, const VString& rhs); 01264 friend inline bool operator<(const VString& lhs, const char* rhs); 01265 friend inline bool operator<(const char* lhs, const VString& rhs); 01266 01267 friend inline bool operator<=(const VString& lhs, const VString& rhs); 01268 friend inline bool operator<=(const VString& lhs, const char* rhs); 01269 friend inline bool operator<=(const char* lhs, const VString& rhs); 01270 01271 friend inline bool operator>=(const VString& lhs, const VString& rhs); 01272 friend inline bool operator>=(const VString& lhs, const char* rhs); 01273 friend inline bool operator>=(const char* lhs, const VString& rhs); 01274 01275 friend inline bool operator>(const VString& lhs, const VString& rhs); 01276 friend inline bool operator>(const VString& lhs, const char* rhs); 01277 friend inline bool operator>(const char* lhs, const VString& rhs); 01278 01279 private: 01280 01281 void _setLength(int stringLength); 01282 Vs64 _parseSignedInteger() const; 01283 Vu64 _parseUnsignedInteger() const; 01284 01286 void _assertInvariant() const; 01287 01288 #ifdef VAULT_VARARG_STRING_FORMATTING_SUPPORT 01289 01296 static int _determineSprintfLength(const char* formatText, va_list args); 01297 #endif 01298 01304 void _assignFromUTF16WideString(const std::wstring& utf16WideString); 01305 01306 #ifdef VAULT_CORE_FOUNDATION_SUPPORT 01307 void _assignFromCFString(const CFStringRef& s); 01308 #endif 01309 01310 /* 01311 New Vault 4.0 feature: SSO (small string optimization). 01312 Prior to 4.0, VString already optimized empty strings, avoiding heap allocation for that case, and dealing 01313 with a few special cases around not having a buffer. It also took care to allocate needed heap space in 01314 chunks so as to avoid excessive re-allocation for strings that grew repeatedly. 01315 With 4.0, the SSO feature means that for small strings ( <= 6 characters in a 32-bit build, <= 14 characters 01316 in a 64-bit build) it can store the string data internally inside the VString without allocating a heap buffer, 01317 and without adding any new size overhead to VString itself. In short, the "buffer size" and "buffer pointer" 01318 instance variables used to manage the heap buffer have their space inside VString re-purposed for storing 01319 the characters of the short string. If the string gets too large, then heap allocation is required as before. 01320 01321 Internally, we use a union to overlay the data, and have an internal flag in the union, mUsingInternalBuffer, 01322 that tells us which buffer (and which part of the union) is in effect. To make most efficient use of space 01323 and avoid adding overhead, I have carefully examined how the compilers lay out and align the data, and I have 01324 ordered the union data to avoid bloat. If not for that concern, I would have put mStringLength, mNumCodePoints, 01325 and mUsingInternalBuffer outside the union since they apply to both parts of the union; however, that would have 01326 an the effect on union alignment on 64-bit of wasting several bytes. So instead, those instance variables 01327 are overlaid in both parts of the union, or put in the first part, but only the ones named in the first ("mI") 01328 part are referenced in the code. 01329 */ 01330 01331 // The internal buffer lengths are carefully chosen to fit within the existing object footprint's unused space. 01332 // 32-bit and 64-bit builds have different alignment/padding, so they have different amounts of unused space. 01333 // For testing, you can set the size to 1 to prevent use of the internal buffer other than for empty strings. 01334 #ifdef VCOMPILER_64BIT 01335 #define VSTRING_INTERNAL_BUFFER_SIZE 15 01336 #else 01337 #define VSTRING_INTERNAL_BUFFER_SIZE 7 01338 #endif 01339 01340 // Internal low-level utility functions for bookkeeping the union data. 01341 01347 void _construct(); 01356 const char* _get() const { return mU.mI.mUsingInternalBuffer ? mU.mI.mInternalBuffer : mU.mX.mHeapBufferPtr; } 01365 char* _set() { return mU.mI.mUsingInternalBuffer ? mU.mI.mInternalBuffer : mU.mX.mHeapBufferPtr; } 01375 int _getBufferLength() const { return mU.mI.mUsingInternalBuffer ? VSTRING_INTERNAL_BUFFER_SIZE : mU.mX.mHeapBufferLength; } 01381 void _determineNumCodePoints() const; 01382 01383 // Finally, the union that defines our internal structure. 01384 union { 01385 01386 // When mI.mUsingInternalBuffer == true, we use mI.mInternalBuffer to store the string data. 01387 struct { 01388 int mStringLength; 01389 mutable int mNumCodePoints; 01390 bool mUsingInternalBuffer : 1; 01391 int mPadBits : 7; 01392 char mInternalBuffer[VSTRING_INTERNAL_BUFFER_SIZE]; 01393 } mI; 01394 01395 // When mI.mUsingInternalBuffer == false, we use mX.mHeapBufferLength and mX.mHeapBufferPtr to store the string data. 01396 struct { 01397 int mStringLength_Alias; 01398 int mNumCodePoints_Alias; 01399 int mHeapBufferLength; 01400 char* mHeapBufferPtr; 01401 } mX; 01402 01403 } mU; 01404 01405 friend class VStringUnit; 01406 }; 01407 01408 inline bool operator==(const VString& lhs, const VString& rhs) { return ::strcmp(lhs, rhs) == 0; } 01409 inline bool operator==(const VString& lhs, const char* rhs) { return ::strcmp(lhs, rhs) == 0; } 01410 inline bool operator==(const char* lhs, const VString& rhs) { return ::strcmp(lhs, rhs) == 0; } 01411 inline bool operator==(const VString& lhs, char rhs) { return (lhs.length() == 1) && (lhs.charAt(0) == rhs); } 01412 01413 inline bool operator!=(const VString& lhs, const VString& rhs) { return !operator==(lhs, rhs); } 01414 inline bool operator!=(const VString& lhs, const char* rhs) { return !operator==(lhs, rhs); } 01415 inline bool operator!=(const char* lhs, const VString& rhs) { return !operator==(lhs, rhs); } 01416 inline bool operator!=(const VString& lhs, char rhs) { return !operator==(lhs, rhs); } 01417 01418 inline bool operator<(const VString& lhs, const VString& rhs) { return ::strcmp(lhs, rhs) < 0; } 01419 inline bool operator<(const VString& lhs, const char* rhs) { return ::strcmp(lhs, rhs) < 0; } 01420 inline bool operator<(const char* lhs, const VString& rhs) { return ::strcmp(lhs, rhs) < 0; } 01421 01422 inline bool operator<=(const VString& lhs, const VString& rhs) { return !operator>(lhs, rhs); } 01423 inline bool operator<=(const VString& lhs, const char* rhs) { return !operator>(lhs, rhs); } 01424 inline bool operator<=(const char* lhs, const VString& rhs) { return !operator>(lhs, rhs); } 01425 01426 inline bool operator>=(const VString& lhs, const VString& rhs) { return !operator<(lhs, rhs); } 01427 inline bool operator>=(const VString& lhs, const char* rhs) { return !operator<(lhs, rhs); } 01428 inline bool operator>=(const char* lhs, const VString& rhs) { return !operator<(lhs, rhs); } 01429 01430 inline bool operator>(const VString& lhs, const VString& rhs) { return operator<(rhs, lhs); } 01431 inline bool operator>(const VString& lhs, const char* rhs) { return operator<(rhs, lhs); } 01432 inline bool operator>(const char* lhs, const VString& rhs) { return operator<(rhs, lhs); } 01433 01434 inline std::istream& operator>>(std::istream& in, VString& s) { s.readFromIStream(in); return in; } 01435 inline std::ostream& operator<<(std::ostream& out, const VString& s) { return out << s.chars(); } 01436 inline VString& operator<<(VString& s, std::istream& in) { s.appendFromIStream(in); return s; } 01437 01438 inline VString& operator<<(VString& s, const char* in) { s += in; return s; } 01439 inline VString& operator<<(VString& s, int i) { s += i; return s; } 01440 inline VString& operator<<(VString& s, Vu8 i) { s += i; return s; } 01441 inline VString& operator<<(VString& s, Vs8 i) { s += i; return s; } 01442 inline VString& operator<<(VString& s, Vu16 i) { s += i; return s; } 01443 inline VString& operator<<(VString& s, Vs16 i) { s += i; return s; } 01444 inline VString& operator<<(VString& s, Vu32 i) { s += i; return s; } 01445 01446 #ifndef Vx32_IS_xINT /* don't redefine if types are same */ 01447 inline VString& operator<<(VString& s, Vs32 i) { s += i; return s; } 01448 #endif /* not Vx32_IS_xINT */ 01449 01450 inline VString& operator<<(VString& s, Vu64 i) { s += i; return s; } 01451 01452 #ifndef Vx64_IS_xINT /* don't redefine if types are same */ 01453 inline VString& operator<<(VString& s, Vs64 i) { s += i; return s; } 01454 #endif /* not Vx64_IS_xINT */ 01455 01456 inline VString& operator<<(VString& s, VDouble f) { s += f; return s; } 01457 01458 #endif /* vstring_h */