"Fossies" - the Fresh Open Source Software Archive

Member "muscle/util/String.h" (21 Nov 2020, 69684 Bytes) of package /linux/privat/muscle7.62.zip:


As a special service "Fossies" has tried to format the requested source page into HTML format using (guessed) C and C++ source code syntax highlighting (style: standard) with prefixed line numbers and code folding option. Alternatively you can here view or download the uninterpreted source code file. For more information about "String.h" see the Fossies "Dox" file reference documentation and the latest Fossies "Diffs" side-by-side code changes report: 7.61_vs_7.62.

    1 /* This file is Copyright 2000-2013 Meyer Sound Laboratories Inc.  See the included LICENSE.txt file for details. */
    2 
    3 /* NOTE TO MACOS/X X-CODE USERS:  If you are trying to #include <string.h>
    4  * and X-Code is "helpfully" pulling in this file instead (because the
    5  * OS/X filesystem is case-insensitive), you can get around that problem
    6  * by adding "USE_HEADERMAP = NO" to your X-Code target settings.
    7  * ref:  http://lists.apple.com/archives/xcode-users/2004/Aug/msg00934.html
    8  *  --Jeremy
    9  */
   10 
   11 #ifndef MuscleString_h
   12 #define MuscleString_h
   13 
   14 #include <ctype.h> 
   15 #include "support/PseudoFlattenable.h"
   16 #include "syslog/SysLog.h"
   17 #include "system/GlobalMemoryAllocator.h"  // for muscleFree()
   18 #include "util/Hashtable.h"
   19 
   20 #ifdef __APPLE__
   21 // Using a forward declaration rather than an #include here to avoid pulling in other things like Mac's
   22 // Point and Rect typedefs, that can cause ambiguities with Muscle's Point and Rect classes.
   23 struct __CFString;
   24 typedef const struct __CFString * CFStringRef;
   25 #endif
   26 
   27 namespace muscle {
   28 
   29 #ifndef DOXYGEN_SHOULD_IGNORE_THIS
   30 # ifdef MUSCLE_COUNT_STRING_COPY_OPERATIONS
   31 enum {
   32    STRING_OP_DEFAULT_CTOR = 0,
   33    STRING_OP_CSTR_CTOR,
   34    STRING_OP_COPY_CTOR,
   35    STRING_OP_PARTIAL_COPY_CTOR,
   36    STRING_OP_SET_FROM_CSTR,
   37    STRING_OP_SET_FROM_STRING,
   38    STRING_OP_MOVE_CTOR,
   39    STRING_OP_MOVE_FROM_STRING,
   40    STRING_OP_DTOR,
   41    NUM_STRING_OPS
   42 };
   43 extern uint32 _stringOpCounts[NUM_STRING_OPS];
   44 extern void PrintAndClearStringCopyCounts(const char * optDesc = NULL);
   45 #  define MUSCLE_INCREMENT_STRING_OP_COUNT(which) _stringOpCounts[which]++
   46 # else
   47 #  define MUSCLE_INCREMENT_STRING_OP_COUNT(which)
   48 static inline void PrintAndClearStringCopyCounts(const char * optDesc = NULL) {(void) optDesc;}
   49 # endif
   50 #endif
   51 
   52 class Point;
   53 class Rect;
   54 
   55 #ifndef SMALL_MUSCLE_STRING_LENGTH
   56 /** Defines the number of ASCII characters that may be held "inline" in a String object, without requiring a separate heap allocation.  If not specified explicitly via a compiler argument (e.g. -DSMALL_MUSCLE_STRING_LENGTH=15), it defaults to 7, and 7 ASCII-chars plus one NUL byte exactly match the space required for a 64-bit pointer, and thus can be used with no space-penalty.  Beware that setting this to a value greater than 7 will cause sizeof(String) to increase.  */
   57 # define SMALL_MUSCLE_STRING_LENGTH 7
   58 #endif
   59 
   60 /** Same as strcmp(), except that it will sort numbers within the string numerically rather than lexically.
   61   * @param s1 The first of the two strings to compare using the number-aware comparison algorithm.
   62   * @param s2 The second of the two strings to compare using the number-aware comparison algorithm.
   63   * @returns 0 if the two strings are equal, >0 if (s2) is the "later" string, or <0 if (s1) is the "later" string.
   64   */
   65 int NumericAwareStrcmp(const char * s1, const char * s2);
   66 
   67 /** Same as NumericAwareStrcmp(), but case-insensitive.
   68   * @param s1 The first of the two strings to compare using the case-insensitive number-aware comparison algorithm.
   69   * @param s2 The second of the two strings to compare using the case-insensitive number-aware comparison algorithm.
   70   * @returns 0 if the two strings are equal, >0 if (s2) is the "later" string, or <0 if (s1) is the "later" string.
   71   */
   72 int NumericAwareStrcasecmp(const char * s1, const char * s2);
   73 
   74 /** Wrapper for strcasecmp(), which isn't always named the same on all OS's
   75   * @param s1 The first of the two strings to compare using the case-insensitive comparison algorithm.
   76   * @param s2 The second of the two strings to compare using the case-insensitive comparison algorithm.
   77   * @returns 0 if the two strings are equal, >0 if (s2) is the "later" string, or <0 if (s1) is the "later" string.
   78   */
   79 inline int Strcasecmp(const char * s1, const char * s2)
   80 {
   81 #ifdef WIN32
   82    return _stricmp(s1, s2);
   83 #else
   84    return strcasecmp(s1, s2);
   85 #endif
   86 }
   87 
   88 /** Wrapper for strncasecmp(), which isn't always named the same on all OS's
   89   * @param s1 The first of the two strings to compare using the case-insensitive comparison algorithm.
   90   * @param s2 The second of the two strings to compare using the case-insensitive comparison algorithm.
   91   * @param n The maximum number of bytes to compare (any bytes after the (nth) byte in the strings will be ignored)
   92   * @returns 0 if the two strings are equal, >0 if (s2) is the "later" string, or <0 if (s1) is the "later" string.
   93   */
   94 inline int Strncasecmp(const char * s1, const char * s2, size_t n)
   95 {
   96 #ifdef WIN32
   97    return _strnicmp(s1, s2, n);
   98 #else
   99    return strncasecmp(s1, s2, n);
  100 #endif
  101 }
  102 
  103 /** Wrapper for strcasestr(), which isn't always present on all OS's.
  104   * @param haystack The string to search in
  105   * @param needle The string to search for
  106   * @returns a pointer to (needle), if it exists inside (haystack), or NULL if it doesn't.
  107   * @note that the search is case-insensitive.
  108   */
  109 const char * Strcasestr(const char * haystack, const char * needle);
  110 
  111 /** Extended wrapper for strcasestr(), which isn't always named the same on all OS's
  112   * @param haystack The string to search in
  113   * @param haystackLen The number of text-bytes that (haystack) is pointing to (i.e. strlen(haystack))
  114   * @param needle The string to search for
  115   * @param needleLen The number of text-bytes that (needle) is pointing to (i.e. strlen(needle))
  116   * @param searchBackwards If set true, the last instance of (needle) in the (haystack) will be returned rather than the first.
  117   * @returns a pointer to a (needle), if one exists inside (haystack), or NULL if it doesn't.
  118   * @note that the search is case-insensitive.
  119   */
  120 const char * StrcasestrEx(const char * haystack, uint32 haystackLen, const char * needle, uint32 needleLen, bool searchBackwards);
  121 
  122 /** An arbitrary-length character-string class.  Represents a dynamically resizable, NUL-terminated ASCII string.
  123   * This class can be used to hold UTF8-encoded strings as well, but because the code in this class is not 
  124   * UTF8-aware, certain operations (such as Reverse() and ToLowerCase()) may not do the right thing when used in 
  125   * conjunction with non-ASCII UTF8 data.
  126   */
  127 class String MUSCLE_FINAL_CLASS : public PseudoFlattenable
  128 {
  129 public:
  130    /** Constructor.
  131     *  @param str If non-NULL, the initial value for this String.
  132     *  @param maxLen The maximum number of characters to place into
  133     *                this String (not including the NUL terminator byte).
  134     *                Default is unlimited (i.e. scan the entire string no matter how long it is)
  135     */
  136    String(const char * str = NULL, uint32 maxLen = MUSCLE_NO_LIMIT) : _bufferLen(sizeof(_strData._smallBuffer)), _length(0) 
  137    {
  138       MUSCLE_INCREMENT_STRING_OP_COUNT(str?STRING_OP_CSTR_CTOR:STRING_OP_DEFAULT_CTOR);
  139       ClearSmallBuffer(); 
  140       if (str) (void) SetCstr(str, maxLen);
  141    }
  142 
  143    /** @copydoc DoxyTemplate::DoxyTemplate(const DoxyTemplate &) */
  144    String(const String & rhs) : _bufferLen(sizeof(_strData._smallBuffer)), _length(0) 
  145    {
  146       MUSCLE_INCREMENT_STRING_OP_COUNT(STRING_OP_COPY_CTOR);
  147       ClearSmallBuffer(); (void) SetFromString(rhs);
  148    }
  149 
  150    /** This constructor sets this String to be a substring of the specified String.
  151      * @param str String to become a copy of.
  152      * @param beginIndex Index of the first character in (str) to include.
  153      * @param endIndex Index after the last character in (str) to include.  
  154      *                 Defaults to a very large number, so that by default the entire remainder of the string is included.
  155      */
  156    String(const String & str, uint32 beginIndex, uint32 endIndex=MUSCLE_NO_LIMIT) : _bufferLen(sizeof(_strData._smallBuffer)), _length(0) 
  157    {
  158       MUSCLE_INCREMENT_STRING_OP_COUNT(STRING_OP_PARTIAL_COPY_CTOR);
  159       ClearSmallBuffer(); (void) SetFromString(str, beginIndex, endIndex);
  160    }
  161 
  162 #ifdef __APPLE__
  163    /** Special MACOS/X-only convenience constructor that sets our state from a UTF8 Core Foundation String
  164      * @param cfStringRef A CFStringRef that we will get our string value from
  165      */
  166    String(const CFStringRef & cfStringRef) : _bufferLen(sizeof(_strData._smallBuffer)), _length(0) {(void) SetFromCFStringRef(cfStringRef);}
  167 #endif
  168 
  169    /** Destructor. */
  170    ~String() 
  171    {
  172       MUSCLE_INCREMENT_STRING_OP_COUNT(STRING_OP_DTOR);
  173       if (IsArrayDynamicallyAllocated()) muscleFree(_strData._bigBuffer);
  174    }
  175 
  176    /** Assignment Operator. 
  177      * @param val Pointer to the C-style string to copy from.  If NULL, this string will become an empty string.
  178      */
  179    String & operator = (const char * val) 
  180    {
  181       MUSCLE_INCREMENT_STRING_OP_COUNT(STRING_OP_SET_FROM_CSTR);
  182       (void) SetCstr(val); return *this;
  183    }
  184 
  185    /** @copydoc DoxyTemplate::operator=(const DoxyTemplate &) */
  186    String & operator = (const String & rhs) 
  187    {
  188       MUSCLE_INCREMENT_STRING_OP_COUNT(STRING_OP_SET_FROM_STRING);
  189       (void) SetFromString(rhs); return *this;
  190    }
  191 
  192    /** Append Operator. 
  193     *  @param rhs A string to append to this string.
  194     */
  195    String & operator += (const String & rhs);
  196 
  197    /** Append Operator. 
  198     *  @param rhs A string to append to this string.  If NULL, this operation is a no-op.
  199     */
  200    String & operator += (const char * rhs);
  201 
  202    /** Append Operator.
  203     *  @param ch A character to append to this string.
  204     */
  205    String & operator += (char ch)
  206    {
  207       if (EnsureBufferSize(Length()+2, true, false) == B_NO_ERROR)
  208       {
  209          GetBuffer()[_length++] = ch;
  210          WriteNULTerminatorByte();
  211       }
  212       return *this;
  213    }
  214    
  215    /** Remove Operator. 
  216     *  @param rhs A substring to remove from this string;  the
  217     *             last instance of the substring will be cut out.
  218     *             If (rhs) is not found, there is no effect.
  219     */
  220    String & operator -= (const String & rhs);
  221 
  222    /** Remove Operator. 
  223     *  @param rhs A substring to remove from this string;  the
  224     *             last instance of the substring will be cut out.
  225     *             If (rhs) is not found, there is no effect.
  226     */
  227    String & operator -= (const char * rhs);
  228 
  229    /** Remove Operator.
  230     *  @param ch A character to remove from this string;  the last
  231     *            instance of this char will be cut out.  If (ch) is
  232     *            not found, there is no effect.
  233     */
  234    String & operator -= (const char ch);
  235    
  236    /** Append 'Stream' Operator.
  237     *  @param rhs A String to append to this string.
  238     *  @return a non const String refrence to 'this' so you can chain appends.
  239     */
  240    String & operator << (const String & rhs) {return (*this += rhs);}
  241 
  242    /** Append 'Stream' Operator.
  243     *  @param rhs A const char* to append to this string.
  244     *  @return a non const String refrence to 'this' so you can chain appends.
  245     */
  246    String & operator << (const char * rhs) {return (*this += rhs);}
  247    
  248    /** Append 'Stream' Operator.
  249     *  @param rhs An int to append to this string.
  250     *  @return a non const String refrence to 'this' so you can chain appends.
  251     */
  252    String & operator << (int rhs);   
  253 
  254    /** Append 'Stream' Operator.
  255     *  @param rhs A float to append to this string. Formatting is set at 2 decimals of precision.
  256     *  @return a non const String refrence to 'this' so you can chain appends.
  257     */
  258    String & operator << (float rhs);   
  259 
  260    /** Append 'Stream' Operator.
  261     *  @param rhs A bool to append to this string. Converts to 'true' and 'false' strings appropriately.
  262     *  @return a non const String refrence to 'this' so you can chain appends.
  263     */
  264    String & operator << (bool rhs);
  265 
  266    /** Comparison Operator.  Returns true iff the two strings contain the same sequence of characters (as determined by memcmp()).
  267      * @param rhs A string to compare ourself with
  268      */
  269    bool operator == (const String & rhs) const {return ((this == &rhs)||((Length() == rhs.Length())&&(memcmp(Cstr(), rhs.Cstr(), Length()) == 0)));}
  270 
  271    /** Comparison Operator.  Returns true if the two strings are equal (as determined by strcmp())
  272      * @param rhs Pointer to a C string to compare with.  NULL pointers are considered a synonym for "".
  273      */
  274    bool operator == (const char * rhs) const {return (strcmp(Cstr(), rhs?rhs:"") == 0);}
  275 
  276    /** Comparison Operator.  Returns true if the two strings are not equal (as determined by memcmp())
  277      * @param rhs A string to compare ourself with
  278      */
  279    bool operator != (const String & rhs) const {return !(*this == rhs);}
  280 
  281    /** Comparison Operator.  Returns true if the two strings are not equal (as determined by strcmp())
  282      * @param rhs Pointer to a C string to compare to.  NULL pointers are considered a synonym for "".
  283      */
  284    bool operator != (const char * rhs) const {return (strcmp(Cstr(), rhs?rhs:"") != 0);}
  285 
  286    /** Comparison Operator.  Returns true if this string comes before (rhs) lexically (as determined by strcmp()). 
  287      * @param rhs A string to compare ourself with
  288      */
  289    bool operator < (const String & rhs) const {return (this == &rhs) ? false : (strcmp(Cstr(), rhs.Cstr()) < 0);}
  290 
  291    /** Comparison Operator.  Returns true if this string comes before (rhs) lexically (as determined by strcmp()). 
  292      * @param rhs Pointer to a C string to compare to.  NULL pointers are considered a synonym for "".
  293      */
  294    bool operator < (const char * rhs) const {return (strcmp(Cstr(), rhs?rhs:"") < 0);}
  295 
  296    /** Comparison Operator.  Returns true if this string comes after (rhs) lexically (as determined by strcmp()). 
  297      * @param rhs A string to compare ourself with
  298      */
  299    bool operator > (const String & rhs) const {return (this == &rhs) ? false : (strcmp(Cstr(), rhs.Cstr()) > 0);}
  300 
  301    /** Comparison Operator.  Returns true if this string comes after (rhs) lexically. 
  302      * @param rhs Pointer to a C string to compare to.  NULL pointers are considered a synonym for "".
  303      */
  304    bool operator > (const char * rhs) const {return (strcmp(Cstr(), rhs?rhs:"") > 0);}
  305 
  306    /** Comparison Operator.  Returns true if the two strings are equal, or this string comes before (rhs) lexically (as determined by strcmp()). 
  307      * @param rhs A string to compare ourself with
  308      */
  309    bool operator <= (const String & rhs) const {return (this == &rhs) ? true : (strcmp(Cstr(), rhs.Cstr()) <= 0);}
  310 
  311    /** Comparison Operator.  Returns true if the two strings are equal, or this string comes before (rhs) lexically (as determined by strcmp()). 
  312      * @param rhs Pointer to a C string to compare to.  NULL pointers are considered a synonym for "".
  313      */
  314    bool operator <= (const char * rhs) const {return (strcmp(Cstr(), rhs?rhs:"") <= 0);}
  315 
  316    /** Comparison Operator.  Returns true if the two strings are equal, or this string comes after (rhs) lexically (as determined by strcmp()). 
  317      * @param rhs A string to compare ourself with
  318      */
  319    bool operator >= (const String & rhs) const {return (this == &rhs) ? true : (strcmp(Cstr(), rhs.Cstr()) >= 0);}
  320 
  321    /** Comparison Operator.  Returns true if the two strings are equal, or this string comes after (rhs) lexically (as determined by strcmp()). 
  322      * @param rhs Pointer to a C string to compare to.  NULL pointers are considered a synonym for "".
  323      */
  324    bool operator >= (const char * rhs) const {return (strcmp(Cstr(), rhs?rhs:"") >= 0);}
  325 
  326    /** Array Operator.  Used to get easy access to the characters that make up this string.
  327     *  @param index Index of the character to return.  Be sure to only use valid indices!
  328     */
  329    char operator [] (uint32 index) const {VerifyIndex(index); return Cstr()[index];}
  330 
  331    /** Array Operator.  Used to get easy access to the characters that make up this string.
  332     *  @param index Index of the character to set.  Be sure to only use valid indices!
  333     */
  334    char & operator [] (uint32 index) {VerifyIndex(index); return GetBuffer()[index];}
  335 
  336    /** Adds a space to the end of this string. */
  337    void operator ++ (int) {(*this) += ' ';}
  338 
  339    /** Remove the last character from the end of this string.  It's a no-op if the string is already empty. */
  340    void operator -- (int) {TruncateChars(1);}
  341 
  342    /** Returns the character at the (index)'th position in the string.
  343     *  @param index A value between 0 and (Length()-1), inclusive.
  344     *  @return A character value.
  345     */
  346    char CharAt(uint32 index) const {return operator[](index);}
  347  
  348    /** Compares this string to another string using strcmp() 
  349      * @param rhs A string to compare ourself with
  350      * @returns 0 if the two strings are equal, a negative value if this string is "first", or a positive value of (rhs) is "first"
  351      */
  352    int CompareTo(const String & rhs) const {return strcmp(Cstr(), rhs.Cstr());}
  353 
  354    /** Compares this string to a C string using strcmp()
  355      * @param rhs Pointer to a C string to compare to.  NULL pointers are considered a synonym for "".
  356      * @returns 0 if the two strings are equal, a negative value if this string is "first", or a positive value of (rhs) is "first"
  357      */
  358    int CompareTo(const char * rhs) const {return strcmp(Cstr(), rhs?rhs:"");}
  359 
  360    /** Compares this string to another string using NumericAwareStrcmp() 
  361      * @param rhs A string to compare ourself with
  362      * @returns 0 if the two strings are equal, a negative value if this string is "first", or a positive value of (rhs) is "first"
  363      */
  364    int NumericAwareCompareTo(const String & rhs) const {return NumericAwareStrcmp(Cstr(), rhs.Cstr());}
  365 
  366    /** Compares this string to a C string using NumericAwareStrcmp()
  367      * @param rhs Pointer to a C string to compare to.  NULL pointers are considered a synonym for "".
  368      * @returns 0 if the two strings are equal, a negative value if this string is "first", or a positive value of (rhs) is "first"
  369      */
  370    int NumericAwareCompareTo(const char * rhs) const {return NumericAwareStrcmp(Cstr(), rhs?rhs:"");}
  371 
  372    /** Returns a read-only C-style pointer to our held character string. */
  373    const char * Cstr() const {return IsArrayDynamicallyAllocated() ? _strData._bigBuffer : _strData._smallBuffer;}
  374 
  375    /** Convenience synonym for Cstr(). */
  376    const char * operator()() const {return Cstr();}  
  377 
  378    /** Clears this string so that it contains no characters.  Equivalent to setting this string to "". */
  379    void Clear() {_length = 0; WriteNULTerminatorByte();}
  380 
  381    /** Similar to Clear(), except this version also frees up any dynamically allocated character array we may have cached. */
  382    void ClearAndFlush();
  383 
  384    /** Shrinks our internally allocated buffer down so that it is just big enough to hold the current string (plus numExtraBytes)
  385      * @param numExtraBytes an additional number of bytes that the buffer should have room for.  Defaults to zero.
  386      * @returns B_NO_ERROR on success, or an error code on failure (although I don't know why this method would ever fail).
  387      */
  388    status_t ShrinkToFit(uint32 numExtraBytes = 0) {return EnsureBufferSize(FlattenedSize()+numExtraBytes, true, true);}
  389 
  390    /** Sets our state from the given C-style string.
  391      * @param str The new string to copy from.  If maxLen is negative, this may be NULL.
  392      * @param maxLen If set, the maximum number of characters to copy (not including the NUL
  393      *               terminator byte).  By default, all characters up to the first encountered
  394      *               NUL terminator byte will be copied out of (str).
  395      */
  396    status_t SetCstr(const char * str, uint32 maxLen = MUSCLE_NO_LIMIT);
  397 
  398    /** Sets our state from the given String.  This is similar to the copy constructor, except
  399      * that it allows you to optionally specify a maximum length, and it allows you to detect
  400      * out-of-memory errors.
  401      * @param str The new string to copy from.
  402      * @param beginIndex Index of the first character in (str) to include.  
  403      *                   Defaults to zero, so that by default the entire string is included.
  404      * @param endIndex Index after the last character in (str) to include.  
  405      *                 Defaults to a very large number, so that by default the entire remainder of the string is included.
  406      * @returns B_NO_ERROR on success, or B_OUT_OF_MEMORY on failure.
  407      */
  408    status_t SetFromString(const String & str, uint32 beginIndex = 0, uint32 endIndex = MUSCLE_NO_LIMIT);
  409 
  410 #ifdef __APPLE__
  411    /** MACOS/X-only convenience method:  Sets our string equal to the string pointed to by (cfStringRef).
  412      * @param cfStringRef A CFStringRef that we will get our string value from.  May be NULL (in which case we'll be set to an empty string)
  413      * @returns B_NO_ERROR on success, or an error code on failure.
  414      */
  415    status_t SetFromCFStringRef(const CFStringRef & cfStringRef);
  416 
  417    /** MACOS/X-only convenience method:  Returns a CFStringRef containing the same string that we have. 
  418      * It becomes the caller's responsibility to CFRelease() the CFStringRef when he is done with it.
  419      * May return a NULL CFStringRef on failure (e.g. out of memory)
  420      */
  421    CFStringRef ToCFStringRef() const;
  422 #endif
  423 
  424    /** Returns true iff this string is a zero-length string. */
  425    bool IsEmpty() const {return (_length == 0);}
  426 
  427    /** Returns true iff this string starts with a number.
  428      * @param allowNegativeValues if true, negative values will be considered as numbers also.  Defaults to true.
  429      */
  430    bool StartsWithNumber(bool allowNegativeValues = true) const {const char * s = Cstr(); return ((isdigit(*s))||((allowNegativeValues)&&(s[0]=='-')&&(isdigit(s[1]))));}
  431 
  432    /** Returns true iff this string is not a zero-length string. */
  433    bool HasChars() const {return (_length > 0);}
  434 
  435    /** Returns true iff this string starts with (prefix) 
  436      * @param c a character to check for at the end of this String.
  437      */
  438    bool EndsWith(char c) const {return (_length > 0)&&(Cstr()[_length-1] == c);}
  439 
  440    /** Returns true iff this string ends with (suffix) 
  441      * @param suffix a String to check for at the end of this String.
  442      */
  443    bool EndsWith(const String & suffix) const {return ((Length() >= suffix.Length())&&(strcmp(Cstr()+(Length()-suffix.Length()), suffix.Cstr()) == 0));}
  444 
  445    /** Returns true iff this string ends with (suffix) 
  446      * @param suffix a String to check for at the end of this String.  NULL pointers are treated as a synonym for "".
  447      */
  448    bool EndsWith(const char * suffix) const
  449    { 
  450       if (suffix == NULL) suffix = "";
  451       const uint32 suffixLen = (uint32) strlen(suffix);
  452       return (Length() < suffixLen) ? false : (strcmp(Cstr()+(Length()-suffixLen), suffix) == 0); 
  453    }
  454 
  455    /** Returns true iff this string is equal to (string), as determined by strcmp(). 
  456      * @param str a String to compare this String with.
  457      */
  458    bool Equals(const String & str) const {return (*this == str);}
  459 
  460    /** Returns true iff this string is equal to (str), as determined by strcmp(). 
  461      * @param str Pointer to a C string to compare to.  NULL pointers are considered a synonym for "".
  462      */
  463    bool Equals(const char * str) const {return (*this == str);}
  464 
  465    /** Returns true iff this string contains a single character (c). 
  466      * @param c a character to compare this String with.
  467      */
  468    bool Equals(char c) const {return (_length == 1)&&(Cstr()[0] == c);}
  469 
  470    /** Returns the first index of (ch) in this string starting at or after (fromIndex), or -1 if not found. 
  471      * @param ch A character to look for in this string.
  472      * @param fromIndex Index of the first character to start searching at in this String.  Defaults to zero (i.e. start from the first character)
  473      */
  474    int IndexOf(char ch, uint32 fromIndex = 0) const
  475    {
  476       const char * temp = (fromIndex < Length()) ? strchr(Cstr()+fromIndex, ch) : NULL; 
  477       return temp ? (int)(temp - Cstr()) : -1; 
  478    }
  479 
  480    /** Returns true iff (ch) is contained in this string.
  481      * @param ch A character to look for in this string.
  482      * @param fromIndex Index of the first character to start searching at in this String.  Defaults to zero (i.e. start from the first character)
  483      */
  484    bool Contains(char ch, uint32 fromIndex = 0) const {return (IndexOf(ch, fromIndex) >= 0);}
  485 
  486    /** Returns true iff substring (str) is in this string starting at or after (fromIndex).
  487      * @param str A String to look for in this string.
  488      * @param fromIndex Index of the first character to start searching at in this String.  Defaults to zero (i.e. start from the first character)
  489      */
  490    bool Contains(const String & str, uint32 fromIndex = 0) const {return (IndexOf(str, fromIndex) >=0);}
  491 
  492    /** Returns true iff the substring (str) is in this string starting at or after (fromIndex).
  493      * @param str Pointer to a C string to compare to.  NULL pointers are considered a synonym for "".
  494      * @param fromIndex Index of the first character to start searching at in this String.  Defaults to zero (i.e. start from the first character)
  495      */
  496    bool Contains(const char * str, uint32 fromIndex = 0) const {return (IndexOf(str, fromIndex) >= 0);}
  497 
  498    /** Returns the first index of substring (str) in this string starting at or after (fromIndex), or -1 if not found. 
  499      * @param str A String to look for in this string.
  500      * @param fromIndex Index of the first character to start searching at in this String.  Defaults to zero (i.e. start from the first character)
  501      */
  502    int IndexOf(const String & str, uint32 fromIndex = 0) const
  503    {
  504       const char * temp = (fromIndex < Length()) ? strstr(Cstr()+fromIndex, str()) : NULL;
  505       return temp ? (int)(temp - Cstr()) : -1;
  506    }
  507 
  508    /** Returns the first index of substring (str) in this string starting at or after (fromIndex), or -1 if not found.
  509      * @param str Pointer to a C string to compare to.  NULL pointers are considered a synonym for "".
  510      * @param fromIndex Index of the first character to start searching at in this String.  Defaults to zero (i.e. start from the first character)
  511      */
  512    int IndexOf(const char * str, uint32 fromIndex = 0) const
  513    {
  514       const char * temp = (fromIndex < Length()) ? strstr(Cstr()+fromIndex, str?str:"") : NULL;
  515       return temp ? (int)(temp - Cstr()) : -1;
  516    }
  517 
  518    /** Returns the last index of (ch) in this string starting at or after (fromIndex), or -1 if not found. 
  519      * @param ch A character to look for in this string.
  520      * @param fromIndex Index of the first character to start searching at in this String.  Defaults to zero (i.e. start from the first character)
  521      */
  522    int LastIndexOf(char ch, uint32 fromIndex = 0) const
  523    {
  524       if (fromIndex < Length())
  525       {
  526          const char * s = Cstr()+fromIndex;
  527          const char * p = Cstr()+Length();
  528          while(--p >= s) if (*p == ch) return (int)(p-Cstr());
  529       }
  530       return -1;
  531    }
  532 
  533    /** Returns the last index of substring (str) in this string  
  534      * @param str A String to look for in this string.
  535      */
  536    int LastIndexOf(const String & str) const {return (str.Length() <= Length()) ? LastIndexOf(str, Length()-str.Length()) : -1;}
  537 
  538    /** Returns the last index of substring (str) in this string 
  539      * @param str Pointer to a C string to compare to.  NULL pointers are considered a synonym for "".
  540      */
  541    int LastIndexOf(const char * str) const
  542    {
  543       if (str == NULL) str = "";
  544       uint32 strLen = (uint32) strlen(str);
  545       return (strLen <= Length()) ? LastIndexOf(str, Length()-strLen) : -1;
  546    }
  547 
  548    /** Returns the last index of substring (str) in this string starting at or after (fromIndex), or -1 if not found.
  549      * @param str A String to look for in this string.
  550      * @param fromIndex Index of the first character to start searching at in this String.  Defaults to zero (i.e. start from the first character)
  551      */
  552    int LastIndexOf(const String & str, uint32 fromIndex) const;
  553 
  554    /** Returns the last index of substring (str) in this string starting at or after (fromIndex), or -1 if not found. 
  555      * @param str Pointer to a C string to compare to.  NULL pointers are considered a synonym for "".
  556      * @param fromIndex Index of the first character to start searching at in this String.  Defaults to zero (i.e. start from the first character)
  557      */
  558    int LastIndexOf(const char * str, uint32 fromIndex) const;
  559 
  560    /** Returns the number of characters in the string (not including the terminating NUL byte) */
  561    uint32 Length() const {return _length;}
  562 
  563    /** Returns the number of bytes of storage we have allocated.  Note that this value will often
  564      * be greater than the value returned by Length(), since we allocate extra bytes to minimize
  565      * the number of reallocations that must be done as data is being added to a String.
  566      */
  567    uint32 GetNumAllocatedBytes() const {return _bufferLen;}
  568 
  569    /** Returns the number of instances of (c) in this string. 
  570      * @param ch The character to count the number of instances of in this String.
  571      */
  572    uint32 GetNumInstancesOf(char ch) const;
  573 
  574    /** Returns the number of instances of (substring) in this string. 
  575      * @param substring String to count the number of instances of in this String.
  576      */
  577    uint32 GetNumInstancesOf(const String & substring) const;
  578 
  579    /** Returns the number of instances of (substring) in this string. 
  580      * @param substring C string to count the number of instances of in this String.
  581      */
  582    uint32 GetNumInstancesOf(const char * substring) const;
  583 
  584    /** Returns the Levenshtein distance between this string and (otherString).
  585      * @param otherString a String to calculate our Levenshtein distance to.
  586      * @param maxResult The maximum score to return.  (Setting a maximum score to return can
  587      *                  speed up execution time, as it allows this method to return early
  588      *                  as soon as the maximum score has been reached).  Defaults to MUSCLE_NO_LIMIT.
  589      * @returns The Levenshtein distance -- i.e. the number of single-character insertions, deletions,
  590      *          or character replacements it would take to convert one string into the other.
  591      */
  592    uint32 GetDistanceTo(const String & otherString, uint32 maxResult = MUSCLE_NO_LIMIT) const;
  593 
  594    /** Returns the Levenshtein distance between this string and (otherString).
  595      * @param otherString a C string to calculate our Levenshtein distance to.  NULL pointers are considered a synonym for "".
  596      * @param maxResult The maximum score to return.  (Setting a maximum score to return can
  597      *                  speed up execution time, as it allows this method to return early
  598      *                  as soon as the maximum score has been reached).  Defaults to MUSCLE_NO_LIMIT.
  599      * @returns The Levenshtein distance -- i.e. the number of single-character insertions, deletions,
  600      *          or character replacements it would take to convert one string into the other.
  601      */
  602    uint32 GetDistanceTo(const char * otherString, uint32 maxResult = MUSCLE_NO_LIMIT) const;
  603 
  604    /** Returns true iff this string starts with (c) 
  605      * @param c The character to see if this string starts with or not
  606      */
  607    bool StartsWith(char c) const {return (*Cstr() == c);}
  608 
  609    /** Returns true iff this string starts with (prefix) 
  610      * @param prefix The prefix to see whether this string starts with or not
  611      */
  612    bool StartsWith(const String & prefix) const {return ((Length() >= prefix.Length())&&(strncmp(Cstr(), prefix(), prefix.Length()) == 0));}
  613 
  614    /** Returns true iff this string starts with (prefix)
  615      * @param prefix Pointer to a C string to compare to.  NULL pointers are considered a synonym for "".
  616      */
  617    bool StartsWith(const char * prefix) const
  618    {
  619       if (prefix == NULL) prefix = "";
  620       uint32 prefixLen = (uint32) strlen(prefix);
  621       return (Length() < prefixLen) ? false : (strncmp(Cstr(), prefix, prefixLen) == 0);
  622    }
  623 
  624    /** Returns a string that consists of (count) copies of (str), followed by this string.
  625      * @param str The string to prepend
  626      * @param count How many instances of (str) to prepend.  Defaults to 1.
  627      */
  628    String Prepend(const String & str, uint32 count = 1) const;
  629 
  630    /** Returns a string that consists of (count) copies of (str), followed by this string. 
  631      * @param str Pointer to a C string to compare to.  NULL pointers are considered a synonym for "".
  632      * @param count How many instances of (str) should be prepended to this string.  Defaults to 1.
  633      */
  634    String Prepend(const char * str, uint32 count = 1) const;
  635 
  636    /** Returns a string that consists of (count) copies of (c), followed by this string.
  637      * @param c The character to prepend
  638      * @param count How many instances of (c) to prepend.  Defaults to 1.
  639      */
  640    String Prepend(char c, uint32 count = 1) const {const char cc[2] = {c, '\0'}; return Prepend(cc, count);}
  641 
  642    /** Similar to Prepend(), but this version will insert separator string between our current content and the prepended string, if necessary.
  643      * @param str A string to prepended to the end of this string.
  644      * @param sep Pointer to the string used to separate words.  Defaults to " "
  645      * @returns a reference to this object, which will have had the specified string prepended, with an inserted (sep) infix if necessary.
  646      */
  647    String PrependWord(const String & str, const char * sep = " ") const {return str.AppendWord(*this, sep);}
  648 
  649    /** Returns a string that consists of this string followed by (count) copies of (str). 
  650      * @param str A string to append to the end of this string.
  651      * @param count How many copies of (str) to append.  Defaults to 1.
  652      */
  653    String Append(const String & str, uint32 count = 1) const;
  654 
  655    /** Returns a string that consists of this string followed by (count) copies of (str). 
  656      * @param str Pointer to a C string to compare to.  NULL pointers are considered a synonym for "".
  657      * @param count How many instances of (str) should be appended to this string.  Defaults to 1.
  658      */
  659    String Append(const char * str, uint32 count = 1) const;
  660 
  661    /** Returns a string that consists of this string followed by (count) copies of (c). 
  662      * @param c The character to append
  663      * @param count How many instances of (c) to append.  Defaults to 1.
  664      */
  665    String Append(char c, uint32 count = 1) const {const char cc[2] = {c, '\0'}; return Append(cc, count);}
  666 
  667    /** Similar to the += operator, but this version will insert a separator between our current content and the appended string, if necessary.
  668      * @param str Pointer to a C string to return appended to this string.  NULL pointers are considered a synonym for "".
  669      * @param sep Pointer to the string used to separate words.  Defaults to " "
  670      * @returns a reference to this object, which will have had the specified string appended, with an inserted (sep) infix if necessary.
  671      */
  672    String AppendWord(const char * str, const char * sep = " ") const;
  673 
  674    /** Similar to the += operator, but this version will insert a separator between our current content and the appended string, if necessary.
  675      * @param str A string to append to the end of this string.
  676      * @param sep Pointer to the string used to separate words.  Defaults to " "
  677      * @returns a reference to this object, which will have had the specified string appended, with an inserted (sep) infix if necessary.
  678      */
  679    String AppendWord(const String & str, const char * sep = " ") const;
  680 
  681    /** Returns a string that is like this string, but padded out to the specified minimum length with (padChar).
  682     *  @param minLength Minimum length that the returned string should be.
  683     *  @param padOnRight If true, (padChar)s will be added to the right; if false (the default), they will be added on the left.
  684     *  @param padChar The character to pad out the string with.  Defaults to ' '.
  685     *  @returns the new, padded String.
  686     */
  687    String Pad(uint32 minLength, bool padOnRight = false, char padChar = ' ') const;
  688 
  689    /** Returns a string that is the same as this one, except that the beginning of each line in the string has (numIndentChars)
  690      * instances of (indentChar) prepended to it.
  691      * @param numIndentChars How many indent characters to prepend to each line
  692      * @param indentChar The character to use to make the indentations.  Defaults to ' '.
  693      * @returns the indented string.
  694      */
  695    String Indent(uint32 numIndentChars, char indentChar = ' ') const;
  696 
  697    /** Returns a string that consists of only the last part of this string, starting with index (beginIndex).  Does not modify the string it is called on.
  698      * @param beginIndex the index of the first character to include in the returned substring
  699      */
  700    String Substring(uint32 beginIndex) const {return String(*this, beginIndex);}
  701 
  702    /** Returns a string that consists of only the characters in this string from range (beginIndex) to (endIndex-1).  Does not modify the string it is called on. 
  703      * @param beginIndex the index of the first character to include in the returned substring
  704      * @param endIndex the index after the final character to include in the returned substring (if set to MUSCLE_NO_LIMIT, or any other too-large-value,
  705      *                 returned substring will include thi entire string starting with (beginIndex)
  706      */
  707    String Substring(uint32 beginIndex, uint32 endIndex) const {return String(*this, beginIndex, endIndex);}
  708 
  709    /** Returns a string that consists of only the last part of this string, starting with the first character after the last instance of (markerString).  
  710     *  If (markerString) is not found in the string, then this entire String is returned.
  711     *  For example, String("this is a test").Substring("is a") returns " test".
  712     *  Does not modify the string it is called on. 
  713     *  @param markerString the substring to return the suffix string that follows
  714     */
  715    String Substring(const String & markerString) const
  716    {
  717       int idx = LastIndexOf(markerString);
  718       return (idx >= 0) ? String(*this, idx+markerString.Length()) : *this;
  719    }
  720 
  721    /** @copydoc String::Substring(const String &) const */
  722    String Substring(const char * markerString) const
  723    {
  724       int idx = LastIndexOf(markerString);
  725       return (idx >= 0) ? String(*this, idx+(int)strlen(markerString)) : *this;  // if (idx >= 0), then we know markerString is non-NULL
  726    }
  727 
  728    /** Returns a string that consists of only the characters in the string from range (beginIndex) until the character just before
  729     *  the first character in (markerString).  If (markerString) is not found, then the entire substring starting at (beginIndex) is returned.
  730     *  For example, String("this is a test").Substring(1, "is a") returns "his ".
  731     *  Does not modify the string it is called on. 
  732     *  @param beginIndex the first character in our string to search at
  733     *  @param markerString the substring to return the suffix string that follows
  734     */
  735    String Substring(uint32 beginIndex, const String & markerString) const {return String(*this, beginIndex, (uint32) IndexOf(markerString, beginIndex));}
  736 
  737    /** @copydoc String::Substring(uint32, const String &) const */
  738    String Substring(uint32 beginIndex, const char * markerString) const {return String(*this, beginIndex, (uint32) IndexOf(markerString, beginIndex));}
  739 
  740    /** Returns an all lower-case version of this string.  Does not modify the string it is called on. */
  741    String ToLowerCase() const; 
  742 
  743    /** Returns an all upper-case version of this string.  Does not modify the string it is called on. */
  744    String ToUpperCase() const; 
  745 
  746    /** Returns a version of this string where All Words Are In Lower Case Except For The First Letter. */
  747    String ToMixedCase() const; 
  748 
  749    /** Returns an version of this string that has all leading and trailing whitespace removed.  Does not modify the string it is called on. */
  750    String Trim() const;  
  751 
  752    /** Swaps the state of this string with (swapWithMe).  Very efficient since little or no data copying is required.
  753      * @param swapWithMe the String to swap contents with
  754      */
  755    inline void SwapContents(String & swapWithMe)
  756    {
  757       muscleSwap(_strData,   swapWithMe._strData);
  758       muscleSwap(_bufferLen, swapWithMe._bufferLen);
  759       muscleSwap(_length,    swapWithMe._length);   // always do this
  760    }
  761 
  762 #ifndef MUSCLE_AVOID_CPLUSPLUS11
  763    /** @copydoc DoxyTemplate::DoxyTemplate(DoxyTemplate &&) */
  764    String(String && rhs) : _bufferLen(0), _length(0)
  765    {
  766       MUSCLE_INCREMENT_STRING_OP_COUNT(STRING_OP_MOVE_CTOR);
  767       ClearSmallBuffer(); 
  768       SwapContents(rhs);
  769    }
  770 
  771    /** @copydoc DoxyTemplate::DoxyTemplate(DoxyTemplate &&) */
  772    String & operator =(String && rhs) 
  773    {
  774       MUSCLE_INCREMENT_STRING_OP_COUNT(STRING_OP_MOVE_FROM_STRING);
  775       SwapContents(rhs); 
  776       return *this;
  777    }
  778 #endif
  779 
  780    /** Like CompareTo(), but case insensitive. 
  781      * @param s the String to compare this string to
  782      * @returns 0 if the two strings are equal, a negative value if this string is "first", or a positive value of (rhs) is "first"
  783      */
  784    int CompareToIgnoreCase(const String & s) const {return Strcasecmp(Cstr(), s());}
  785 
  786    /** Like CompareTo(), but case insensitive.
  787      * @param s the String to compare this string to
  788      * @returns 0 if the two strings are equal, a negative value if this string is "first", or a positive value of (rhs) is "first"
  789      */
  790    int CompareToIgnoreCase(const char * s) const {return Strcasecmp(Cstr(), s?s:"");}
  791 
  792    /** Like NumericAwareCompareTo(), but case insensitive.
  793      * @param s the String to compare this string to
  794      * @returns 0 if the two strings are equal, a negative value if this string is "first", or a positive value of (rhs) is "first"
  795      */
  796    int NumericAwareCompareToIgnoreCase(const String & s) const {return NumericAwareStrcasecmp(Cstr(), s());}
  797 
  798    /** Like NumericAwareCompareTo(), but case insensitive.
  799      * @param s the String to compare this string to
  800      * @returns 0 if the two strings are equal, a negative value if this string is "first", or a positive value of (rhs) is "first"
  801      */
  802    int NumericAwareCompareToIgnoreCase(const char * s) const {return NumericAwareStrcasecmp(Cstr(), s?s:"");}
  803 
  804    /** Like EndsWith(), but case insensitive.
  805      * @param c a character to check for at the end of this String.
  806      */
  807    bool EndsWithIgnoreCase(char c) const {return (HasChars())&&(tolower(Cstr()[_length-1]) == tolower(c));}
  808 
  809    /** Like EndsWith(), but case insensitive.
  810      * @param s a suffix to check for at the end of this String.
  811      */
  812    bool EndsWithIgnoreCase(const String & s) const {return ((Length() >= s.Length())&&(Strcasecmp(Cstr()+(Length()-s.Length()), s()) == 0));}
  813 
  814    /** Like EndsWith(), but case insensitive.
  815      * @param s a suffix to check for at the end of this String.
  816      */
  817    bool EndsWithIgnoreCase(const char * s) const;
  818 
  819    /** Like Equals(), but case insensitive.
  820      * @param s a string to check for (case-insensitive) equality with this String
  821      */
  822    bool EqualsIgnoreCase(const String & s) const {return ((this==&s)||((Length()==s.Length())&&(Strcasecmp(Cstr(), s()) == 0)));}
  823 
  824    /** Like Equals(), but case insensitive.
  825      * @param s a string to check for (case-insensitive) equality with this String
  826      */
  827    bool EqualsIgnoreCase(const char * s) const {if (s==NULL) s=""; return ((Cstr()==s)||(Strcasecmp(Cstr(), s) == 0));}
  828 
  829    /** Like Equals(), but case insensitive.
  830      * @param c a character to check for (case-insensitive) equality with this String.
  831      */
  832    bool EqualsIgnoreCase(char c) const {return (_length==1)&&(tolower(Cstr()[0])==tolower(c));}
  833 
  834    /** Like Contains(), but case insensitive. 
  835      * @param s A String to look for in this string.
  836      * @param f Index of the first character to start searching at in this String.  Defaults to zero.
  837      */
  838    bool ContainsIgnoreCase(const String & s, uint32 f = 0) const {return (IndexOfIgnoreCase(s, f) >= 0);}
  839 
  840    /** Like Contains(), but case insensitive. 
  841      * @param s A String to look for in this string.
  842      * @param f Index of the first character to start searching at in this String.  Defaults to zero.
  843      */
  844    bool ContainsIgnoreCase(const char * s, uint32 f = 0) const {return (IndexOfIgnoreCase(s, f) >= 0);}
  845 
  846    /** Like Contains(), but case insensitive.
  847      * @param ch A character to look for in this string.
  848      * @param f Index of the first character to start searching at in this String.  Defaults to zero.
  849      */
  850    bool ContainsIgnoreCase(char ch, uint32 f = 0) const {return (IndexOfIgnoreCase(ch, f) >= 0);}
  851 
  852    /** Like IndexOf(), but case insensitive.
  853      * @param s A String to look for in this string.
  854      * @param f Index of the first character to start searching at in this String.
  855      */
  856    int IndexOfIgnoreCase(const String & s, uint32 f = 0) const;
  857 
  858    /** Like IndexOf(), but case insensitive.
  859      * @param s A string to look for in this string.
  860      * @param f Index of the first character to start searching at in this String.
  861      */
  862    int IndexOfIgnoreCase(const char * s, uint32 f = 0) const;
  863 
  864    /** Like IndexOf(), but case insensitive. 
  865      * @param ch A character to look for in this string.
  866      * @param f Index of the first character to start searching at in this String.  Defaults to zero.
  867      */
  868    int IndexOfIgnoreCase(char ch, uint32 f = 0) const;
  869 
  870    /** Like LastIndexOf(), but case insensitive. 
  871      * @param s A String to look for in this string.
  872      * @param f Index of the first character to start searching at in this String.  Defaults to zero.
  873      */
  874    int LastIndexOfIgnoreCase(const String & s, uint32 f = 0) const;
  875 
  876    /** Like LastIndexOf(), but case insensitive. 
  877      * @param s A string to look for in this string.
  878      * @param f Index of the first character to start searching at in this String.  Defaults to zero.
  879      */
  880    int LastIndexOfIgnoreCase(const char * s, uint32 f = 0) const;
  881 
  882    /** Like LastIndexOf(), but case insensitive. 
  883      * @param ch A character to look for in this string.
  884      * @param f Index of the first character to start searching at in this String.  Defaults to zero.
  885      */
  886    int LastIndexOfIgnoreCase(char ch, uint32 f = 0) const;
  887 
  888    /** Like StartsWith(), but case insensitive. 
  889      * @param c The character to see if this string starts with or not
  890      */
  891    bool StartsWithIgnoreCase(char c) const {return (_length > 0)&&(tolower(Cstr()[0]) == tolower(c));}
  892 
  893    /** Like StartsWith(), but case insensitive. 
  894      * @param s The prefix to see whether this string starts with or not
  895      */
  896    bool StartsWithIgnoreCase(const String & s) const {return ((Length() >= s.Length())&&(Strncasecmp(Cstr(), s(), s.Length()) == 0));}
  897 
  898    /** Like StartsWith(), but case insensitive. 
  899      * @param s The prefix to see whether this string starts with or not
  900      */
  901    bool StartsWithIgnoreCase(const char * s) const {if (s==NULL) s=""; return (Strncasecmp(Cstr(), s, strlen(s)) == 0);}
  902 
  903    /** @copydoc DoxyTemplate::HashCode() const */
  904    inline uint32 HashCode() const {return CalculateHashCode(Cstr(), Length());}
  905 
  906    /** @copydoc DoxyTemplate::HashCode64() const */
  907    inline uint64 HashCode64() const {return CalculateHashCode64(Cstr(), Length());}
  908 
  909    /** Replaces all instances of (oldChar) in this string with (newChar).
  910      * @param replaceMe The character to search for.
  911      * @param withMe The character to replace all occurrences of (replaceMe) with.
  912      * @param maxReplaceCount The maximum number of characters that should be replaced.  Defaults to MUSCLE_NO_LIMIT.
  913      * @returns The number of characters that were successfully replaced.
  914      */
  915    uint32 Replace(char replaceMe, char withMe, uint32 maxReplaceCount = MUSCLE_NO_LIMIT); 
  916 
  917    /** Same as Replace(), but instead of modifying this object, it returns a modified copy, and the called object remains unchanged.
  918      * @param replaceMe The character to search for.
  919      * @param withMe The character to replace all occurrences of (replaceMe) with.
  920      * @param maxReplaceCount The maximum number of characters that should be replaced.  Defaults to MUSCLE_NO_LIMIT.
  921      * @returns The modified string.
  922      */
  923    String WithReplacements(char replaceMe, char withMe, uint32 maxReplaceCount = MUSCLE_NO_LIMIT) const; 
  924 
  925    /** Replaces all instances of (replaceMe) in this string with (withMe).
  926      * @param replaceMe The substring to search for.
  927      * @param withMe The substring to replace all occurrences of (replaceMe) with.
  928      * @param maxReplaceCount The maximum number of substrings that should be replaced.  Defaults to MUSCLE_NO_LIMIT.
  929      * @returns The number of substrings that were successfully replaced, or -1 if the operation failed (out of memory)
  930      */
  931    int32 Replace(const String & replaceMe, const String & withMe, uint32 maxReplaceCount = MUSCLE_NO_LIMIT); 
  932  
  933    /** Same as Replace(), but instead of modifying this object, it returns a modified copy, and the called object remains unchanged.
  934      * @param replaceMe The substring to search for.
  935      * @param withMe The substring to replace all occurrences of (replaceMe) with.
  936      * @param maxReplaceCount The maximum number of substrings that should be replaced.  Defaults to MUSCLE_NO_LIMIT.
  937      * @returns The modified string.
  938      */
  939    String WithReplacements(const String & replaceMe, const String & withMe, uint32 maxReplaceCount = MUSCLE_NO_LIMIT) const;
  940  
  941    /** Returns a String equal to this one, except with a set of search-and-replace operations performed.
  942      * @param beforeToAfter the search-and-replace operations to perform.  Keys in this table are the strings
  943      *                      to be searched for, and each key's associated value is the string to replace it with.
  944      * @param maxReplaceCount The maximum number of substrings that should be replaced.  Defaults to MUSCLE_NO_LIMIT.
  945      * @note By performing multiple search-and-replace operations simultaneously, we can give correct results in
  946      *       certain cases where a series of single-string search-and-replace operations would not.  For example, 
  947      *       String("1,2,3,4").WithReplacements("1","2").WithReplacements("2","3") returns "3,3,3,4"
  948      *       instead of the hoped-for "2,3,3,4".
  949      * @note Search-and-replace operations will be done in the iteration-order of the beforeToAfter Hashtable
  950      *       argument, so in any cases of conflicts, key->value pairs found earlier in the iteration will
  951      *       take precedence over those found later in the iteration.
  952      */
  953    String WithReplacements(const Hashtable<String, String> & beforeToAfter, uint32 maxReplaceCount = MUSCLE_NO_LIMIT) const;
  954 
  955    /** Reverses the order of all characters in the string, so that e.g. "string" becomes "gnirts" */
  956    void Reverse();
  957 
  958    /** Part of the Flattenable pseudo-interface.
  959     *  @return false
  960     */
  961    bool IsFixedSize() const {return false;}
  962 
  963    /** Part of the Flattenable pseudo-interface.
  964     *  @return B_STRING_TYPE
  965     */
  966    uint32 TypeCode() const {return B_STRING_TYPE;}
  967 
  968    /** Returns true iff (tc) equals B_STRING_TYPE.
  969      * @param tc the type code to check
  970      */
  971    bool AllowsTypeCode(uint32 tc) const {return (TypeCode()==tc);}
  972 
  973    /** Part of the Flattenable pseudo-interface.
  974     *  @return Length()+1  (the +1 is for the terminating NUL byte)
  975     */
  976    uint32 FlattenedSize() const {return Length()+1;}
  977 
  978    /** Part of the Flattenable pseudo-interface.  Flattens our string into (buffer).
  979     *  @param buffer A byte array to receive the flattened version of this string.
  980     *                There must be at least FlattenedSize() bytes available in this array.
  981     *  @note The clever secret here is that a flattened String is just a C-style
  982     *        zero-terminated char array, and can be used interchangably as such.
  983     */
  984    void Flatten(uint8 *buffer) const {memcpy((char *)buffer, Cstr(), FlattenedSize());}
  985 
  986    /** Unflattens a String from (buf).
  987     *  @param buf an array of (size) bytes.
  988     *  @param size the number of bytes in (buf).
  989     *  @note The clever secret here is that (buf) is treated as just a C-style
  990     *        zero-terminated char array, and can be used interchangably as such.
  991     *  @return B_NO_ERROR (never fails!)
  992     */
  993    status_t Unflatten(const uint8 *buf, uint32 size) {return SetCstr((const char *)buf, size);}
  994 
  995    /** Makes sure that we have pre-allocated enough space for a NUL-terminated string 
  996     *  at least (numChars) bytes long (not including the NUL byte).
  997     *  If not, this method will try to allocate the space.  
  998     *  @param numChars How much space to pre-allocate, in ASCII characters.
  999     *  @returns B_NO_ERROR on success, or B_OUT_OF_MEMORY on failure.
 1000     */ 
 1001    status_t Prealloc(uint32 numChars) {return EnsureBufferSize(numChars+1, true, false);}
 1002 
 1003    /** Removes (numCharsToTruncate) characters from the end of this string.
 1004      * @param numCharsToTruncate How many characters to truncate.  If greater than the
 1005      *                           length of this String, this String will become empty.
 1006      */
 1007    void TruncateChars(uint32 numCharsToTruncate) {_length -= muscleMin(_length, numCharsToTruncate); WriteNULTerminatorByte();}
 1008 
 1009    /** Makes sure this string is no longer than (maxLength) characters long by truncating
 1010      * any extra characters, if necessary
 1011      * @param maxLength Maximum length that this string should be allowed to be.
 1012      */
 1013    void TruncateToLength(uint32 maxLength) {_length = muscleMin(_length, maxLength); WriteNULTerminatorByte();}
 1014 
 1015    /** Returns a string like this string, but with the appropriate %# tokens
 1016      * replaced with a textual representation of the values passed in as (value).
 1017      * For example, String("%1 is a %2").Arg(13).Arg("bakers dozen") would return
 1018      * the string "13 is a bakers dozen".
 1019      * @param value The value to replace in the string.
 1020      * @param fmt The format parameter to pass to muscleSprintf().  Note that if you supply your
 1021      *            own format string, you'll need to be careful since a badly chosen format
 1022      *            string could lead to a crash or out-of-bounds memory overwrite.  In particular,
 1023      *            the format string should match the type specified, and should not lead to
 1024      *            more than 256 bytes being written.
 1025      * @returns a new String with the appropriate tokens replaced.
 1026      */
 1027    String Arg(bool value, const char * fmt = "%s") const;
 1028 
 1029    /** As above, but for char values.
 1030      * @copydoc Arg(bool, const char *) const
 1031      */
 1032    String Arg(char value, const char * fmt = "%i") const;
 1033 
 1034    /** As above, but for unsigned char values.
 1035      * @copydoc Arg(bool, const char *) const
 1036      */
 1037    String Arg(unsigned char value, const char * fmt = "%u") const;
 1038 
 1039    /** As above, but for short values.
 1040      * @copydoc Arg(bool, const char *) const
 1041      */
 1042    String Arg(short value, const char * fmt = "%i") const;
 1043 
 1044    /** As above, but for unsigned shot values.
 1045      * @copydoc Arg(bool, const char *) const
 1046      */
 1047    String Arg(unsigned short value, const char * fmt = "%u") const;
 1048 
 1049    /** As above, but for int values.
 1050      * @copydoc Arg(bool, const char *) const
 1051      */
 1052    String Arg(int value, const char * fmt = "%i") const;
 1053 
 1054    /** As above, but for unsigned int values.
 1055      * @copydoc Arg(bool, const char *) const
 1056      */
 1057    String Arg(unsigned int value, const char * fmt = "%u") const;
 1058 
 1059    /** As above, but for long values.
 1060      * @copydoc Arg(bool, const char *) const
 1061      */
 1062    String Arg(long value, const char * fmt = "%li") const;
 1063 
 1064    /** As above, but for unsigned long values.
 1065      * @copydoc Arg(bool, const char *) const
 1066      */
 1067    String Arg(unsigned long value, const char * fmt = "%lu") const;
 1068 
 1069    /** As above, but for long long values.
 1070      * @copydoc Arg(bool, const char *) const
 1071      */
 1072    String Arg(long long value, const char * fmt = INT64_FORMAT_SPEC) const;
 1073 
 1074    /** As above, but for unsigned long long values.
 1075      * @copydoc Arg(bool, const char *) const
 1076      */
 1077    String Arg(unsigned long long value, const char * fmt = UINT64_FORMAT_SPEC) const;
 1078 
 1079    /** As above, but for double values.
 1080      * @copydoc Arg(bool, const char *) const
 1081      */
 1082    String Arg(double value, const char * fmt) const;
 1083 
 1084    /** As above, but for double values.
 1085      * Returns a String representation of the given floating point value,
 1086      * with up to (maxDigitsAfterDecimal) digits appearing after the decimal point.
 1087      * @param f the floating-point value to return a String representation of.
 1088      * @param minDigitsAfterDecimal the minimum number of digits to display after the decimal
 1089      *                              point.  Defaults to 0 (meaning try to use as few as possible)
 1090      * @param maxDigitsAfterDecimal the maximum number of digits to display after the decimal
 1091      *                              point.  Defaults to MUSCLE_NO_LIMIT (meaning that no particular
 1092      *                              maximum value should be enforced)
 1093      * @note Trailing zeroes will be omitted from the string, as will the decimal point itself, if it
 1094      *       would otherwise be the last character in the String.
 1095      */
 1096    String Arg(double f, uint32 minDigitsAfterDecimal = 0, uint32 maxDigitsAfterDecimal = MUSCLE_NO_LIMIT) const;
 1097 
 1098    /** As above, but for string values.
 1099      * @param value the string to replace any instances of %1 with (or %2 if %1 isn't present, or etc)
 1100      */
 1101    String Arg(const String & value) const;
 1102 
 1103    /** As above, but for Point values.
 1104      * @copydoc Arg(bool, const char *) const
 1105      */
 1106    String Arg(const Point & value, const char * fmt = "%f,%f") const;
 1107 
 1108    /** As above, but for Rect values.
 1109      * @copydoc Arg(bool, const char *) const
 1110      */
 1111    String Arg(const Rect & value, const char * fmt = "%f,%f,%f,%f") const;
 1112 
 1113    /** As above, but for C string values.
 1114      * @param value the string to replace any instances of "%1" with (or "%2" if "%1" isn't present, or etc)
 1115      */
 1116    String Arg(const char * value) const;
 1117 
 1118    /** As above, but for printing pointer values.
 1119      * @param value the pointer-value whose string representation we should replace any instances of %1 with (or %2 if %1 isn't present, or etc)
 1120      */
 1121    String Arg(const void * value) const;
 1122 
 1123    /** If this string already ends with the specified character, returns this string verbatim.
 1124      * Otherwise, returns a String equivalent to this one but with the specified character appended.
 1125      * @param c The char we want to be sure is at the end of the returned String.
 1126      */
 1127    String WithSuffix(char c) const {return EndsWith(c) ? *this : Append(c);}
 1128 
 1129    /** If this string already ends with the specified string, returns this string verbatim.
 1130      * Otherwise, returns a String equivalent to this one but with the specified string appended.
 1131      * @param str The string we want to be sure is at the end of the returned String.
 1132      */
 1133    String WithSuffix(const String & str) const {return EndsWith(str) ? *this : Append(str);}
 1134 
 1135    /** If this string already begins with the specified character, returns this string verbatim.
 1136      * Otherwise, returns a String equivalent to this one but with the specified character prepended.
 1137      * @param c The character we want to be sure is at the beginning of the returned String.
 1138      */
 1139    String WithPrefix(char c) const {return StartsWith(c) ? *this : Prepend(c);}
 1140 
 1141    /** If this string already begins with the specified string, returns this string verbatim.
 1142      * Otherwise, returns a String equivalent to this one but with the specified string prepended.
 1143      * @param str The string we want to be sure is at the beginning of the returned String.
 1144      */
 1145    String WithPrefix(const String & str) const {return StartsWith(str) ? *this : Prepend(str);}
 1146 
 1147    /** Returns a String like this one, but with any characters (c) removed from the end.
 1148      * @param c The char we want to be sure is not at the end of the returned String.
 1149      * @param maxToRemove Maximum number of instances of (c) to remove from the returned String.
 1150      *                    Defaults to MUSCLE_NO_LIMIT, i.e. remove all trailing (c) chars.
 1151      */
 1152    String WithoutSuffix(char c, uint32 maxToRemove = MUSCLE_NO_LIMIT) const;
 1153 
 1154    /** Returns a String like this one, but with any instances of (str) removed from the end.
 1155      * @param str The substring we want to be sure is not at the end of the returned String.
 1156      * @param maxToRemove Maximum number of instances of (c) to remove from the returned String.
 1157      *                    Defaults to MUSCLE_NO_LIMIT, i.e. remove all trailing (str) substrings.
 1158      * @note if (str) is empty, this method will return (*this).
 1159      */
 1160    String WithoutSuffix(const String & str, uint32 maxToRemove = MUSCLE_NO_LIMIT) const;
 1161 
 1162    /** Returns a String like this one, but with any characters (c) removed from the beginning.
 1163      * @param c The char we want to be sure is not at the beginning of the returned String.
 1164      * @param maxToRemove Maximum number of instances of (c) to remove from the returned String.
 1165      *                    Defaults to MUSCLE_NO_LIMIT, i.e. remove all starting (c) chars.
 1166      */
 1167    String WithoutPrefix(char c, uint32 maxToRemove = MUSCLE_NO_LIMIT) const;
 1168 
 1169    /** Returns a String like this one, but with any instances of (str) removed from the beginning.
 1170      * @param str The substring we want to be sure is not at the beginning of the returned String.
 1171      * @param maxToRemove Maximum number of instances of (c) to remove from the returned String.
 1172      *                    Defaults to MUSCLE_NO_LIMIT, i.e. remove all starting (str) substrings.
 1173      * @note if (str) is empty, this method will return (*this).
 1174      */
 1175    String WithoutPrefix(const String & str, uint32 maxToRemove = MUSCLE_NO_LIMIT) const;
 1176 
 1177    /** Returns a String like this one, but with any characters (c) removed from the end.
 1178      * @param c The char we want to be sure is not at the end of the returned String (case-insensitive).
 1179      * @param maxToRemove Maximum number of instances of (c) to remove from the returned String.
 1180      *                    Defaults to MUSCLE_NO_LIMIT, i.e. remove all trailing (c) chars.
 1181      */
 1182    String WithoutSuffixIgnoreCase(char c, uint32 maxToRemove = MUSCLE_NO_LIMIT) const;
 1183 
 1184    /** Returns a String like this one, but with any instances of (str) removed from the end.
 1185      * @param str The substring we want to be sure is not at the end of the returned String (case-insensitive).
 1186      * @param maxToRemove Maximum number of instances of (c) to remove from the returned String.
 1187      *                    Defaults to MUSCLE_NO_LIMIT, i.e. remove all trailing (str) substrings.
 1188      * @note if (str) is empty, this method will return (*this).
 1189      */
 1190    String WithoutSuffixIgnoreCase(const String & str, uint32 maxToRemove = MUSCLE_NO_LIMIT) const;
 1191 
 1192    /** Returns a String like this one, but with any characters (c) removed from the beginning.
 1193      * @param c The char we want to be sure is not at the beginning of the returned String (case-insensitive).
 1194      * @param maxToRemove Maximum number of instances of (c) to remove from the returned String.
 1195      *                    Defaults to MUSCLE_NO_LIMIT, i.e. remove all starting (c) chars.
 1196      */
 1197    String WithoutPrefixIgnoreCase(char c, uint32 maxToRemove = MUSCLE_NO_LIMIT) const;
 1198 
 1199    /** Returns a String like this one, but with any instances of (str) removed from the beginning.
 1200      * @param str The substring we want to be sure is not at the beginning of the returned String (case-insensitive).
 1201      * @param maxToRemove Maximum number of instances of (c) to remove from the returned String.
 1202      *                    Defaults to MUSCLE_NO_LIMIT, i.e. remove all starting (str) substrings.
 1203      * @note if (str) is empty, this method will return (*this).
 1204      */
 1205    String WithoutPrefixIgnoreCase(const String & str, uint32 maxToRemove = MUSCLE_NO_LIMIT) const;
 1206 
 1207    /** Returns a String equal to this one, but with any integer/numeric suffix removed.
 1208      * For example, if you called this method on the String "Joe-54", this method would return "Joe".
 1209      * @param optRetRemovedSuffixValue If non-NULL, the numeric suffix that was removed will be returned here.
 1210      *                                 If there was no numeric suffix, zero will be written here.
 1211      * @note that negative numeric suffixes aren't supported -- i.e. plus or minus is not considered to be part of the numeric-suffix.
 1212      */
 1213    String WithoutNumericSuffix(uint32 * optRetRemovedSuffixValue = NULL) const;
 1214 
 1215    /** If this string ends in a numeric value, returns that value; otherwise returns (defaultValue).
 1216      *  For example, ParseNumericSuffix("Joe-54") would return 54.
 1217      *  @param defaultValue the value to return if no numeric suffix is found.  Defaults to zero.
 1218      *  @note that negative numeric suffixes aren't supported -- i.e. plus or minus is not considered to be part of the numeric-suffix.
 1219      */
 1220    uint32 ParseNumericSuffix(uint32 defaultValue = 0) const;
 1221 
 1222    /** Returns a 32-bit checksum corresponding to this String's contents.
 1223      * Note that this method method is O(N).
 1224      */
 1225    uint32 CalculateChecksum() const {return muscle::CalculateChecksum((const uint8 *) Cstr(), Length());}
 1226 
 1227    /** Returns true iff the given pointer points into our held character array.
 1228      * @param s A character pointer.  It will not be dereferenced by this call.
 1229      */
 1230    bool IsCharInLocalArray(const char * s) const {const char * b = Cstr(); return muscleInRange(s, b, b+_length);}
 1231 
 1232 private:
 1233    bool IsSpaceChar(char c) const {return ((c==' ')||(c=='\t')||(c=='\r')||(c=='\n'));}
 1234    status_t EnsureBufferSize(uint32 newBufLen, bool retainValue, bool allowShrink);
 1235    String ArgAux(const char * buf) const;
 1236    bool IsArrayDynamicallyAllocated() const {return (_bufferLen>sizeof(_strData._smallBuffer));}
 1237    char * GetBuffer() {return IsArrayDynamicallyAllocated() ? _strData._bigBuffer : _strData._smallBuffer;}
 1238    void ClearSmallBuffer() {memset(_strData._smallBuffer, 0, sizeof(_strData._smallBuffer));}
 1239    void WriteNULTerminatorByte() {GetBuffer()[_length] = '\0';}
 1240 
 1241 #ifdef __clang_analyzer__
 1242    struct ShortStringOptimizationData {  // ClangSA gets confused by unions, so we'll avoid SSO during Clang analysis
 1243 #else
 1244    union ShortStringOptimizationData {
 1245 #endif
 1246       char * _bigBuffer;                                // Pointer to allocated array.  Valid iff (_bufferLen >  sizeof(_smallBuffer))
 1247       char _smallBuffer[SMALL_MUSCLE_STRING_LENGTH+1];  // inline character array.      Valid iff (_bufferLen <= sizeof(_smallBuffer))
 1248    } _strData;
 1249 
 1250    uint32 _bufferLen;         // Number of bytes pointed to by (GetBuffer())
 1251    uint32 _length;            // cached strlen(GetBuffer())
 1252 
 1253    void VerifyIndex(uint32 index) const 
 1254    {
 1255 #ifdef MUSCLE_AVOID_ASSERTIONS
 1256       (void) index;  // avoid compiler warnings
 1257 #else
 1258       MASSERT(index < _length, "Index Out Of Bounds Exception");
 1259 #endif
 1260    }
 1261 };
 1262 
 1263 /** A custom compare functor for case-insensitive comparisons of Strings. */
 1264 class CaseInsensitiveStringCompareFunctor
 1265 {
 1266 public:
 1267    /** Compares the two String's strcmp() style, returning zero if they are equal, a negative value if (item1) comes first, or a positive value if (item2) comes first.
 1268      * @param s1 the first String to compare
 1269      * @param s2 the second String to compare
 1270      */
 1271    int Compare(const String & s1, const String & s2, void *) const {return s1.CompareToIgnoreCase(s2);}
 1272 };
 1273 
 1274 /** A custom compare functor for numeric-aware comparisons of Strings. */
 1275 class NumericAwareStringCompareFunctor
 1276 {
 1277 public:
 1278    /** Compares the two String's strcmp() style, returning zero if they are equal, a negative value if (item1) comes first, or a positive value if (item2) comes first.
 1279      * @param s1 the first String to compare
 1280      * @param s2 the second String to compare
 1281      */
 1282    int Compare(const String & s1, const String & s2, void *) const {return s1.NumericAwareCompareTo(s2);}
 1283 };
 1284 
 1285 /** A custom compare functor for case-insensitive numeric-aware comparisons of Strings. */
 1286 class CaseInsensitiveNumericAwareStringCompareFunctor
 1287 {
 1288 public:
 1289    /** Compares the two String's strcmp() style, returning zero if they are equal, a negative value if (item1) comes first, or a positive value if (item2) comes first.
 1290      * @param s1 the first String to compare
 1291      * @param s2 the second String to compare
 1292      */
 1293    int Compare(const String & s1, const String & s2, void *) const {return s1.NumericAwareCompareToIgnoreCase(s2);}
 1294 };
 1295 
 1296 /** Convenience method:  returns a string with no characters in it (a.k.a. "") */
 1297 inline const String & GetEmptyString() {return GetDefaultObjectForType<String>();}
 1298 
 1299 inline String operator+(const String & lhs, const String & rhs)  {String ret; (void) ret.Prealloc(lhs.Length()+rhs.Length());        ret = lhs; ret += rhs; return ret;}
 1300 inline String operator+(const String & lhs, const char *rhs)     {String ret; (void) ret.Prealloc(lhs.Length()+(rhs?(uint32)strlen(rhs):0)); ret = lhs; ret += rhs; return ret;}
 1301 inline String operator+(const char * lhs,   const String & rhs)  {String ret; (void) ret.Prealloc((lhs?(uint32)strlen(lhs):0)+rhs.Length()); ret = lhs; ret += rhs; return ret;}
 1302 inline String operator+(const String & lhs, char rhs)            {String ret; (void) ret.Prealloc(lhs.Length()+1);                   ret = lhs; ret += rhs; return ret;}
 1303 inline String operator+(char lhs,           const String & rhs)  {String ret; (void) ret.Prealloc(1+rhs.Length());                   ret.SetCstr(&lhs, 1); ret += rhs; return ret;}
 1304 inline String operator-(const String & lhs, const String & rhs)  {String ret = lhs; ret -= rhs; return ret;}
 1305 inline String operator-(const String & lhs, const char *rhs)     {String ret = lhs; ret -= rhs; return ret;}
 1306 inline String operator-(const char *lhs,    const String & rhs)  {String ret = lhs; ret -= rhs; return ret;}
 1307 inline String operator-(const String & lhs, char rhs)            {String ret = lhs; ret -= rhs; return ret;}
 1308 inline String operator-(char lhs,           const String & rhs)  {String ret; ret.SetCstr(&lhs, 1); ret -= rhs; return ret;}
 1309 
 1310 } // end namespace muscle
 1311 
 1312 #endif