String.h

00001 /* This file is Copyright 2000-2008 Meyer Sound Laboratories Inc.  See the included LICENSE.txt file for details. */
00002 /* This class was derived from the String class written by Michael Olivero (mike95@mike95.com) */
00003  
00004 /* NOTE TO MACOS/X X-CODE USERS:  If you are trying to #include <string.h>
00005  * and X-Code is "helpfully" pulling in this file instead (because the
00006  * OS/X filesystem is case-insensitive), you can get around that problem
00007  * by adding "USE_HEADERMAP = NO" to your X-Code target settings.
00008  * ref:  http://lists.apple.com/archives/xcode-users/2004/Aug/msg00934.html
00009  *  --Jeremy
00010  */
00011 
00012 #ifndef MuscleString_h
00013 #define MuscleString_h
00014 
00015 #include <ctype.h> 
00016 #include "support/Flattenable.h"
00017 #include "system/GlobalMemoryAllocator.h"  // for muscleFree()
00018 
00019 BEGIN_NAMESPACE(muscle);
00020 
00021 #ifndef SMALL_MUSCLE_STRING_LENGTH
00022 # define SMALL_MUSCLE_STRING_LENGTH 7  // strings shorter than this length can be stored inline, without requiring an extra new[].
00023 #endif
00024 
00026 uint32 CStringHashFunc(const char * str); 
00027 
00029 class String : public Flattenable
00030 {
00031 public:
00038    String(const char * str = NULL, uint32 maxLen = MUSCLE_NO_LIMIT) : Flattenable(), _buffer(NULL), _bufferLen(0), _length(0) {if (str) (void) SetCstr(str, maxLen); else _smallBuffer[0] = '\0';}
00039 
00043    String(const String & str) : Flattenable(), _buffer(NULL), _bufferLen(0), _length(0) {(void) SetFromString(str);}
00044 
00051    String(const String & str, uint32 beginIndex, uint32 endIndex=MUSCLE_NO_LIMIT) : Flattenable(), _buffer(NULL), _bufferLen(0), _length(0) {(void) SetFromString(str, beginIndex, endIndex);}
00052 
00054    virtual ~String() {if (_buffer != _smallBuffer) muscleFree(_buffer);}
00055 
00059    String & operator = (char val) {(void) SetCstr(&val, 1); return *this;}
00060 
00064    String & operator = (const char * val) {(void) SetCstr(val); return *this;}
00065 
00069    String & operator = (const String &rhs) {(void) SetFromString(rhs); return *this;}
00070 
00074    String & operator += (const String &rhs);
00075 
00079    String & operator += (const char * rhs);
00080 
00084    String & operator += (char ch)
00085    {
00086       if (EnsureBufferSize(Length()+2, true) == B_NO_ERROR)
00087       {
00088          _buffer[_length++] = ch;
00089          _buffer[_length]   = '\0';
00090       }
00091       return *this;
00092    }
00093    
00099    String & operator -= (const String &rhs);
00100 
00106    String & operator -= (const char ch);
00107    
00112    String & operator << (const String& rhs) {return (*this += rhs);}
00113 
00118    String & operator << (const char* rhs) {return (*this += rhs);}
00119    
00124    String & operator << (int rhs);   
00125 
00130    String & operator << (float rhs);   
00131 
00136    String & operator << (bool rhs);
00137 
00141    bool operator == (const String &rhs) const {return ((this == &rhs)||((Length() == rhs.Length())&&(strcmp(Cstr(), rhs.Cstr()) == 0)));}
00142 
00146    bool operator == (const char * rhs) const {return (strcmp(Cstr(), rhs?rhs:"") == 0);}
00147 
00151    bool operator != (const String &rhs) const {return !(*this == rhs);}
00152 
00156    bool operator != (const char * rhs) const {return (strcmp(Cstr(), rhs?rhs:"") != 0);}
00157 
00161    bool operator < (const String &rhs) const {return (this == &rhs) ? false : (strcmp(Cstr(), rhs.Cstr()) < 0);}
00162 
00166    bool operator < (const char * rhs) const {return (strcmp(Cstr(), rhs?rhs:"") < 0);}
00167 
00171    bool operator > (const String &rhs) const {return (this == &rhs) ? false : (strcmp(Cstr(), rhs.Cstr()) > 0);}
00172 
00176    bool operator > (const char * rhs) const {return (strcmp(Cstr(), rhs?rhs:"") > 0);}
00177 
00181    bool operator <= (const String &rhs) const {return (this == &rhs) ? true : (strcmp(Cstr(), rhs.Cstr()) <= 0);}
00182 
00186    bool operator <= (const char * rhs) const {return (strcmp(Cstr(), rhs?rhs:"") <= 0);}
00187 
00191    bool operator >= (const String &rhs) const {return (this == &rhs) ? true : (strcmp(Cstr(), rhs.Cstr()) >= 0);}
00192 
00196    bool operator >= (const char * rhs) const {return (strcmp(Cstr(), rhs?rhs:"") >= 0);}
00197 
00201    char operator [] (uint32 index) const {VerifyIndex(index); return _buffer[index];}
00202 
00206    char & operator [] (uint32 index) {VerifyIndex(index); return _buffer[index];}
00207 
00212    char CharAt(uint32 index) const {return operator[](index);}
00213  
00217    int CompareTo(const String & rhs) const {return strcmp(Cstr(), rhs.Cstr());}
00218 
00222    int CompareTo(const char * rhs) const {return strcmp(Cstr(), rhs?rhs:"");}
00223 
00225    const char * Cstr() const {return _buffer ? _buffer : "";}
00226 
00228    const char * operator()() const {return Cstr();}  
00229 
00231    void Clear() {if (_buffer) _buffer[0] = '\0'; _length = 0;}
00232 
00239    status_t SetCstr(const char * str, uint32 maxLen = MUSCLE_NO_LIMIT);
00240 
00251    status_t SetFromString(const String & str, uint32 beginIndex = 0, uint32 endIndex = MUSCLE_NO_LIMIT);
00252 
00254    bool IsEmpty() const {return (_length == 0);}
00255 
00257    bool HasChars() const {return (_length > 0);}
00258 
00262    bool EndsWith(char c) const {return (_length > 0)&&(_buffer[_length-1] == c);}
00263 
00267    bool EndsWith(const String &suffix) const {return (Length() < suffix.Length()) ? false : (strcmp(Cstr()+(Length()-suffix.Length()), suffix.Cstr()) == 0);}
00268 
00272    bool EndsWith(const char * suffix) const
00273    { 
00274       if (suffix == NULL) suffix = "";
00275       uint32 suffixLen = strlen(suffix);
00276       return (Length() < suffixLen) ? false : (strcmp(Cstr()+(Length()-suffixLen), suffix) == 0); 
00277    }
00278 
00282    bool Equals(const String & str) const {return (*this == str);}
00283 
00287    bool Equals(const char * str) const {return (*this == str);}
00288 
00292    bool Equals(char c) const {return (_length == 1)&&(_buffer[0] == c);}
00293 
00298    int IndexOf(char ch, uint32 fromIndex = 0) const
00299    {
00300       const char * temp = (fromIndex < Length()) ? strchr(Cstr()+fromIndex, ch) : NULL; 
00301       return temp ? (temp - Cstr()) : -1; 
00302    }
00303 
00308    int IndexOf(const String &str, uint32 fromIndex = 0) const
00309    {
00310       const char * temp = (fromIndex < Length()) ? strstr(Cstr()+fromIndex, str()) : NULL;
00311       return temp ? (temp - Cstr()) : -1;
00312    }
00313 
00318    int IndexOf(const char * str, uint32 fromIndex = 0) const
00319    {
00320       const char * temp = (fromIndex < Length()) ? strstr(Cstr()+fromIndex, str?str:"") : NULL;
00321       return temp ? (temp - Cstr()) : -1;
00322    }
00323 
00328    int LastIndexOf(char ch, uint32 fromIndex = 0) const
00329    {
00330       const char * lio = (fromIndex < Length()) ? strrchr(Cstr()+fromIndex, ch) : NULL;
00331       return lio ? (lio - Cstr()) : -1;
00332    }
00333 
00337    int LastIndexOf(const String &str) const {return (str.Length() <= Length()) ? LastIndexOf(str, Length()-str.Length()) : -1;}
00338 
00342    int LastIndexOf(const char * str) const
00343    {
00344       if (str == NULL) str = "";
00345       uint32 strLen = strlen(str);
00346       return (strLen <= Length()) ? LastIndexOf(str, Length()-strLen) : -1;
00347    }
00348 
00353    int LastIndexOf(const String &str, uint32 fromIndex) const;
00354 
00359    int LastIndexOf(const char * str, uint32 fromIndex) const;
00360 
00362    uint32 Length() const {return _length;}
00363 
00367    uint32 GetNumInstancesOf(char ch) const;
00368 
00372    uint32 GetNumInstancesOf(const String & substring) const;
00373 
00377    uint32 GetNumInstancesOf(const char * substring) const;
00378 
00382    bool StartsWith(char c) const {return (_length > 0)&&(_buffer[0] == c);}
00383 
00387    bool StartsWith(const String &prefix) const {return ((Length() >= prefix.Length())&&(strncmp(Cstr(), prefix(), prefix.Length()) == 0));}
00388 
00392    bool StartsWith(const char * prefix) const
00393    {
00394       if (prefix == NULL) prefix = "";
00395       uint32 prefixLen = strlen(prefix);
00396       return (Length() < prefixLen) ? false : (strncmp(Cstr(), prefix, prefixLen) == 0);
00397    }
00398 
00400    bool StartsWith(const String &prefix, uint32 offset) const {return ((offset+prefix.Length()<=Length())&&(strncmp(Cstr()+offset, prefix.Cstr(), prefix.Length()) == 0));}
00401 
00406    bool StartsWith(const char * prefix, uint32 offset) const
00407    {
00408       if (prefix == NULL) prefix = "";
00409       uint32 prefixLen = strlen(prefix);
00410       return ((offset+prefixLen<=Length())&&(strncmp(Cstr()+offset, prefix, prefixLen) == 0));
00411    }
00412 
00414    String Prepend(const String & str, uint32 count = 1) const;
00415 
00420    String Prepend(const char * str, uint32 count = 1) const;
00421 
00423    String Append(const String & str, uint32 count = 1) const;
00424 
00429    String Append(const char * str, uint32 count = 1) const;
00430 
00437    String Pad(uint32 minLength, bool padOnRight = false, char padChar = ' ') const;
00438 
00440    String Substring(uint32 beginIndex) const {return String(*this, beginIndex);}
00441 
00443    String Substring(uint32 beginIndex, uint32 endIndex) const {return String(*this, beginIndex, endIndex);}
00444 
00450    String Substring(const String & markerString) const
00451    {
00452       int idx = LastIndexOf(markerString);
00453       return (idx >= 0) ? String(*this, idx+markerString.Length()) : *this;
00454    }
00455 
00457    String Substring(const char * markerString) const
00458    {
00459       int idx = LastIndexOf(markerString);
00460       return (idx >= 0) ? String(*this, idx+strlen(markerString)) : *this;  // if (idx >= 0), then we know markerString is non-NULL
00461    }
00462 
00468    String Substring(uint32 beginIndex, const String & markerString) const {return String(*this, beginIndex, (uint32) IndexOf(markerString, beginIndex));}
00469 
00471    String Substring(uint32 beginIndex, const char * markerString) const {return String(*this, beginIndex, (uint32) IndexOf(markerString, beginIndex));}
00472 
00474    String ToLowerCase() const; 
00475 
00477    String ToUpperCase() const; 
00478 
00480    String Trim() const;  
00481 
00483    void SwapContents(String & swapWithMe);
00484 
00486    int CompareToIgnoreCase(const String &s) const             {return ToLowerCase().CompareTo(s.ToLowerCase());}
00487 
00489    bool EndsWithIgnoreCase(char c) const                      {return (_length > 0)&&(tolower(_buffer[_length-1]) == tolower(c));}
00490 
00492    bool EndsWithIgnoreCase(const String &s) const             {return ToLowerCase().EndsWith(s.ToLowerCase());}
00493 
00495    bool EqualsIgnoreCase(const String &s) const               {return ToLowerCase().Equals(s.ToLowerCase());}
00496 
00498    bool EqualsIgnoreCase(char c) const                        {return (_length==1)&&(tolower(_buffer[0])==tolower(c));}
00499 
00501    int IndexOfIgnoreCase(const String &s) const               {return ToLowerCase().IndexOf(s.ToLowerCase());}
00502 
00504    int IndexOfIgnoreCase(const String &s, uint32 f) const     {return ToLowerCase().IndexOf(s.ToLowerCase(),f);}
00505 
00507    int IndexOfIgnoreCase(char ch) const                       {return ToLowerCase().IndexOf((char)tolower(ch));}
00508 
00510    int IndexOfIgnoreCase(char ch, uint32 f) const             {return ToLowerCase().IndexOf((char)tolower(ch),f);}
00511 
00513    int LastIndexOfIgnoreCase(const String &s) const           {return ToLowerCase().LastIndexOf(s.ToLowerCase());}
00514 
00516    int LastIndexOfIgnoreCase(const String &s, uint32 f) const {return ToLowerCase().LastIndexOf(s.ToLowerCase(),f);}
00517 
00519    int LastIndexOfIgnoreCase(char ch) const                   {return ToLowerCase().LastIndexOf((char)tolower(ch));}
00520 
00522    int LastIndexOfIgnoreCase(char ch, uint32 f) const         {return ToLowerCase().LastIndexOf((char)tolower(ch),f);}
00523 
00525    bool StartsWithIgnoreCase(char c) const                    {return (_length > 0)&&(tolower(_buffer[0]) == tolower(c));}
00526 
00528    bool StartsWithIgnoreCase(const String &s) const           {return ToLowerCase().StartsWith(s.ToLowerCase());}
00529 
00531    bool StartsWithIgnoreCase(const String &s, uint32 o) const {return ToLowerCase().StartsWith(s.ToLowerCase(),o);}
00532 
00534    inline uint32 HashCode() const {return CStringHashFunc(Cstr());}
00535 
00541    uint32 Replace(char replaceMe, char withMe); 
00542 
00549    int32 Replace(const String & replaceMe, const String & withMe); 
00550  
00552    void Reverse();
00553 
00557    virtual bool IsFixedSize() const {return false;}
00558 
00562    virtual uint32 TypeCode() const {return B_STRING_TYPE;}
00563 
00567    virtual uint32 FlattenedSize() const;
00568 
00575    virtual void Flatten(uint8 *buffer) const;
00576 
00582    virtual status_t Unflatten(const uint8 *buf, uint32 size);
00583 
00590    status_t Prealloc(uint32 numChars) {return EnsureBufferSize(numChars+1, true);}
00591 
00604    String Arg(int8 value,   const char * fmt = "%i")   const;
00605 
00607    String Arg(uint8 value,  const char * fmt = "%u")   const;
00608 
00610    String Arg(int16 value,  const char * fmt = "%i")   const;
00611 
00613    String Arg(uint16 value, const char * fmt = "%u")   const;
00614 
00616    String Arg(int32 value,  const char * fmt = INT32_FORMAT_SPEC)  const;
00617 
00619    String Arg(uint32 value, const char * fmt = UINT32_FORMAT_SPEC) const;
00620 
00622    String Arg(int64 value,  const char * fmt = INT64_FORMAT_SPEC)  const;
00623 
00625    String Arg(uint64 value, const char * fmt = UINT64_FORMAT_SPEC) const;
00626 
00628    String Arg(double value, const char * fmt = "%f")   const;
00629 
00631    String Arg(const String & value) const;
00632 
00634    String Arg(const char * value) const;
00635 
00639 #ifdef MUSCLE_AVOID_NAMESPACES
00640    uint32 CalculateChecksum() const {return ::CalculateChecksum((const uint8 *) Cstr(), Length());}
00641 #else
00642    uint32 CalculateChecksum() const {return muscle::CalculateChecksum((const uint8 *) Cstr(), Length());}
00643 #endif
00644 
00645 private:
00646    bool IsSpaceChar(char c) const {return ((c==' ')||(c=='\t')||(c=='\r')||(c=='\n'));}
00647    status_t EnsureBufferSize(uint32 newBufLen, bool retainValue);
00648    String ArgAux(const char * buf) const;
00649 
00650    char _smallBuffer[SMALL_MUSCLE_STRING_LENGTH+1];  // store very small strings in-line, to avoid dynamic allocation
00651    char * _buffer;            // Stores the chars.  May point at (_smallBuffer), or a dynamically allocated buffer
00652    uint32 _bufferLen;         // Number of bytes pointed to by (_buffer)
00653    uint32 _length;            // cached strlen(_buffer)
00654 
00655    void VerifyIndex(uint32 index) const 
00656    {
00657 #ifdef MUSCLE_AVOID_ASSERTIONS
00658       (void) index;  // avoid compiler warnings
00659 #else
00660       MASSERT(index < _length, "Index Out Of Bounds Exception");
00661 #endif
00662    }
00663 };
00664 DECLARE_HASHTABLE_KEY_CLASS(String);
00665 
00666 // Also we want to allow C Strings to be used as keys in a Hashtable too
00667 template <> class HashFunctor<const char *>
00668 {
00669 public:
00673    uint32 operator () (const char * str) const {return CStringHashFunc(str);}
00674 };
00675 
00677 const String & GetEmptyString();
00678 
00680 int StringCompareFunc(const String &, const String &, void *);
00681 
00683 int StringCompareFunc(const String * const &, const String * const &, void *);
00684 
00686 int CStringCompareFunc(const char * const &, const char * const &, void *);
00687 
00688 inline String operator+(const String & lhs, const String &rhs)  {String ret(lhs); ret += rhs; return ret;}
00689 inline String operator+(const String & lhs, const char *rhs)    {String ret(lhs); ret += rhs; return ret;}
00690 inline String operator+(const char * lhs,   const String & rhs) {String ret(lhs); ret += rhs; return ret;}
00691 inline String operator+(const String & lhs, char rhs)           {String ret(lhs); ret += rhs; return ret;}
00692 inline String operator-(const String & lhs, const String &rhs)  {String ret(lhs); ret -= rhs; return ret;}
00693 inline String operator-(const String & lhs, const char *rhs)    {String ret(lhs); ret -= rhs; return ret;}
00694 inline String operator-(const char *lhs,    const String &rhs)  {String ret(lhs); ret -= rhs; return ret;}
00695 inline String operator-(const String & lhs, char rhs)           {String ret(lhs); ret -= rhs; return ret;}
00696 
00697 END_NAMESPACE(muscle);
00698 
00699 #endif

Generated on Thu Jun 5 17:47:54 2008 for MUSCLE by  doxygen 1.5.1