Vault  4.1
vstring.h
Go to the documentation of this file.
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 */

Copyright ©1997-2014 Trygve Isaacson. All rights reserved. This documentation was generated with Doxygen.