NptStrings.h

00001 /*****************************************************************
00002 |
00003 |   Neptune - String Objects
00004 |
00005 |   (c) 2001-2003 Gilles Boccon-Gibod
00006 |   Author: Gilles Boccon-Gibod (bok@bok.net)
00007 |
00008  ****************************************************************/
00009 
00010 #ifndef _NPT_STRINGS_H_
00011 #define _NPT_STRINGS_H_
00012 
00013 /*----------------------------------------------------------------------
00014 |   includes
00015 +---------------------------------------------------------------------*/
00016 #include "NptConfig.h"
00017 #if defined(NPT_CONFIG_HAVE_NEW_H)
00018 #include <new>
00019 #endif
00020 #include "NptTypes.h"
00021 #include "NptConstants.h"
00022 #include "NptDebug.h"
00023 
00024 /*----------------------------------------------------------------------
00025 |   constants
00026 +---------------------------------------------------------------------*/
00027 const int NPT_STRING_SEARCH_FAILED = -1;
00028 
00029 /*----------------------------------------------------------------------
00030 |   NPT_String
00031 +---------------------------------------------------------------------*/
00032 class NPT_String
00033 {
00034 public:
00035     // factories
00036     static NPT_String FromInteger(long value);
00037     static NPT_String FromIntegerU(unsigned long value);
00038 
00039     // constructors
00040     NPT_String(const NPT_String& str);
00041     NPT_String(const char* str);
00042     NPT_String(const char* str, NPT_Size length);
00043     NPT_String(const char* str, NPT_Ordinal first, NPT_Size length);
00044     NPT_String(char c, NPT_Cardinal repeat = 1);
00045     NPT_String() : m_Chars(NULL) {}
00046    ~NPT_String() { if (m_Chars) delete GetBuffer(); }
00047 
00048     // string info and manipulations
00049     bool       IsEmpty() const { return m_Chars == NULL || GetBuffer()->GetLength() == 0; }
00050     NPT_Size   GetLength()   const { return m_Chars ? GetBuffer()->GetLength() : 0;    }
00051     NPT_Size   GetCapacity() const { return m_Chars ? GetBuffer()->GetAllocated() : 0; }
00052     NPT_Result SetLength(NPT_Size length);
00053     void       Assign(const char* chars, NPT_Size size);
00054     void       Append(const char* chars, NPT_Size size);
00055     void       Append(const char* s) { Append(s, StringLength(s)); }
00056     int        Compare(const char* s, bool ignore_case = false) const;
00057     static int Compare(const char* s1, const char* s2, bool ignore_case = false);
00058     int        CompareN(const char* s, NPT_Size count, bool ignore_case = false) const;
00059     static int CompareN(const char* s1, const char* s2, NPT_Size count, bool ignore_case = false);
00060 
00061     // substrings
00062     NPT_String SubString(NPT_Ordinal first, NPT_Size length) const;
00063     NPT_String SubString(NPT_Ordinal first) const {
00064         return SubString(first, GetLength());
00065     }
00066     NPT_String Left(NPT_Size length) const {
00067         return SubString(0, length);
00068     }
00069     NPT_String Right(NPT_Size length) const {
00070         return length >= GetLength() ? 
00071                *this : 
00072                SubString(GetLength()-length, length);
00073     }
00074 
00075     // buffer management
00076     void       Reserve(NPT_Size length);
00077 
00078     // conversions
00079     NPT_String ToLowercase() const;
00080     NPT_String ToUppercase() const;
00081     NPT_Result ToInteger(long& value, bool relaxed = true) const;
00082     NPT_Result ToInteger(unsigned long& value, bool relaxed = true) const;
00083     NPT_Result ToFloat(float& value, bool relaxed = true) const;
00084     
00085     // processing
00086     void MakeLowercase();
00087     void MakeUppercase();
00088     void Replace(char a, char b);
00089 
00090     // search
00091     int  Find(char c, NPT_Ordinal start = 0, bool ignore_case = false) const;
00092     int  Find(const char* s, NPT_Ordinal start = 0, bool ignore_case = false) const;
00093     int  ReverseFind(char c, NPT_Ordinal start = 0, bool ignore_case = false) const;
00094     int  ReverseFind(const char* s, NPT_Ordinal start = 0, bool ignore_case = false) const;
00095     bool StartsWith(const char* s, bool ignore_case = false) const;
00096     bool EndsWith(const char* s, bool ignore_case = false) const;
00097 
00098     // editing
00099     void Insert(const char* s, NPT_Ordinal where = 0);
00100     void Erase(NPT_Ordinal start, NPT_Cardinal count = 1);
00101     void Replace(NPT_Ordinal start, NPT_Cardinal count, const char* s);
00102     void TrimLeft();
00103     void TrimLeft(char c);
00104     void TrimLeft(const char* chars);
00105     void TrimRight();
00106     void TrimRight(char c);
00107     void TrimRight(const char* chars);
00108     void Trim();
00109     void Trim(char c);
00110     void Trim(const char* chars);
00111 
00112     // type casting
00113     operator char*() const        { return m_Chars ? m_Chars: &EmptyString; }
00114     operator const char* () const { return m_Chars ? m_Chars: &EmptyString; }
00115     const char* GetChars() const  { return m_Chars ? m_Chars: &EmptyString; }
00116     char*       UseChars()        { return m_Chars ? m_Chars: &EmptyString; }
00117 
00118     // operator overloading
00119     NPT_String& operator=(const char* str);
00120     NPT_String& operator=(const NPT_String& str);
00121     NPT_String& operator=(char c);
00122     const NPT_String& operator+=(const NPT_String& s) {
00123         Append(s.GetChars(), s.GetLength());
00124         return *this;
00125     }
00126     const NPT_String& operator+=(const char* s) {
00127         Append(s);
00128         return *this;
00129     }
00130     const NPT_String& operator+=(char c) {
00131         Append(&c, 1);
00132         return *this;
00133     }
00134     char operator[](int index) const {
00135         NPT_ASSERT((unsigned int)index < GetLength());
00136         return GetChars()[index];
00137     }
00138     char& operator[](int index) {
00139         NPT_ASSERT((unsigned int)index < GetLength());
00140         return UseChars()[index];
00141     }
00142 
00143     // friend operators
00144     friend NPT_String operator+(const NPT_String& s1, const NPT_String& s2) {
00145         return s1+s2.GetChars();
00146     }
00147     friend NPT_String operator+(const NPT_String& s1, const char* s2);
00148     friend NPT_String operator+(const char* s1, const NPT_String& s2);
00149     friend NPT_String operator+(const NPT_String& s, char c);
00150     friend NPT_String operator+(char c, const NPT_String& s);
00151 
00152 protected:
00153     // inner classes
00154     class Buffer {
00155     public:
00156         // class methods
00157         static Buffer* Allocate(NPT_Size allocated, NPT_Size length) {
00158             void* mem = ::operator new(sizeof(Buffer)+allocated+1);
00159             return new(mem) Buffer(allocated, length);
00160         }
00161         static char* Create(NPT_Size allocated, NPT_Size length=0) {
00162             Buffer* shared = Allocate(allocated, length);
00163             return shared->GetChars();
00164         }
00165         static char* Create(const char* copy) {
00166             NPT_Size length = StringLength(copy);
00167             Buffer* shared = Allocate(length, length);
00168             CopyString(shared->GetChars(), copy);
00169             return shared->GetChars();
00170         }
00171         static char* Create(const char* copy, NPT_Size length) {
00172             Buffer* shared = Allocate(length, length);
00173             CopyBuffer(shared->GetChars(), copy, length);
00174             shared->GetChars()[length] = '\0';
00175             return shared->GetChars();
00176         }
00177         static char* Create(char c, NPT_Cardinal repeat) {
00178             Buffer* shared = Allocate(repeat, repeat);
00179             char* s = shared->GetChars();
00180             while (repeat--) {
00181                 *s++ = c;
00182             }
00183             *s = '\0';
00184             return shared->GetChars();
00185         }
00186 
00187         // methods
00188         char* GetChars() { 
00189             // return a pointer to the first char
00190             return reinterpret_cast<char*>(this+1); 
00191         }
00192         NPT_Size GetLength() const      { return m_Length; }
00193         void SetLength(NPT_Size length) { m_Length = length; }
00194         NPT_Size GetAllocated() const   { return m_Allocated; }
00195 
00196     private:
00197         // methods
00198         Buffer(NPT_Size allocated, NPT_Size length = 0) : 
00199             m_Length(length),
00200             m_Allocated(allocated) {}
00201 
00202         // members
00203         NPT_Cardinal m_Length;
00204         NPT_Cardinal m_Allocated;
00205         // the actual string data follows
00206 
00207     };
00208     
00209     // members
00210     char* m_Chars;
00211 
00212 private:
00213     // friends
00214     friend class Buffer;
00215 
00216     // static members
00217     static char EmptyString;
00218 
00219     // methods
00220     Buffer* GetBuffer() const { 
00221         return reinterpret_cast<Buffer*>(m_Chars)-1;
00222     }
00223     void Reset() { 
00224         if (m_Chars != NULL) {
00225             delete GetBuffer(); 
00226             m_Chars = NULL;
00227         }
00228     }
00229     char* PrepareToWrite(NPT_Size length);
00230     void PrepareToAppend(NPT_Size length, NPT_Size allocate);
00231 
00232     // static methods
00233     static void CopyString(char* dst, const char* src) {
00234         while ((*dst++ = *src++)){}
00235     }
00236     
00237     static void CopyBuffer(char* dst, const char* src, NPT_Size size) {
00238         while (size--) *dst++ = *src++;
00239     }
00240     
00241     static NPT_Size StringLength(const char* str) {
00242         NPT_Size length = 0;
00243         while (*str++) length++;
00244         return length;
00245     }
00246 };
00247 
00248 /*----------------------------------------------------------------------
00249 |   external operators
00250 +---------------------------------------------------------------------*/
00251 inline bool operator==(const NPT_String& s1, const NPT_String& s2) { 
00252     return s1.Compare(s2) == 0; 
00253 }
00254 inline bool operator==(const NPT_String& s1, const char* s2) {
00255     return s1.Compare(s2) == 0; 
00256 }
00257 inline bool operator==(const char* s1, const NPT_String& s2) {
00258     return s2.Compare(s1) == 0; 
00259 }
00260 inline bool operator!=(const NPT_String& s1, const NPT_String& s2) {
00261     return s1.Compare(s2) != 0; 
00262 }
00263 inline bool operator!=(const NPT_String& s1, const char* s2) {
00264     return s1.Compare(s2) != 0; 
00265 }
00266 inline bool operator!=(const char* s1, const NPT_String& s2) {
00267     return s2.Compare(s1) != 0; 
00268 }
00269 inline bool operator<(const NPT_String& s1, const NPT_String& s2) {
00270     return s1.Compare(s2) < 0; 
00271 }
00272 inline bool operator<(const NPT_String& s1, const char* s2) {
00273     return s1.Compare(s2) < 0; 
00274 }
00275 inline bool operator<(const char* s1, const NPT_String& s2) {
00276     return s2.Compare(s1) > 0; 
00277 }
00278 inline bool operator>(const NPT_String& s1, const NPT_String& s2) {
00279     return s1.Compare(s2) > 0; 
00280 }
00281 inline bool operator>(const NPT_String& s1, const char* s2) {
00282     return s1.Compare(s2) > 0; 
00283 }
00284 inline bool operator>(const char* s1, const NPT_String& s2) {
00285     return s2.Compare(s1) < 0; 
00286 }
00287 inline bool operator<=(const NPT_String& s1, const NPT_String& s2) {
00288     return s1.Compare(s2) <= 0; 
00289 }
00290 inline bool operator<=(const NPT_String& s1, const char* s2) {
00291     return s1.Compare(s2) <= 0; 
00292 }
00293 inline bool operator<=(const char* s1, const NPT_String& s2) {
00294     return s2.Compare(s1) >= 0; 
00295 }
00296 inline bool operator>=(const NPT_String& s1, const NPT_String& s2) {
00297     return s1.Compare(s2) >= 0; 
00298 }
00299 inline bool operator>=(const NPT_String& s1, const char* s2) {
00300     return s1.Compare(s2) >= 0; 
00301 }
00302 inline bool operator>=(const char* s1, const NPT_String& s2) {
00303     return s2.Compare(s1) <= 0; 
00304 }
00305 
00306 #endif // _NPT_STRINGS_H_