1 /***************************************************************** 2 | 3 | Neptune - String Objects 4 | 5 | Copyright (c) 2002-2008, Axiomatic Systems, LLC. 6 | All rights reserved. 7 | 8 | Redistribution and use in source and binary forms, with or without 9 | modification, are permitted provided that the following conditions are met: 10 | * Redistributions of source code must retain the above copyright 11 | notice, this list of conditions and the following disclaimer. 12 | * Redistributions in binary form must reproduce the above copyright 13 | notice, this list of conditions and the following disclaimer in the 14 | documentation and/or other materials provided with the distribution. 15 | * Neither the name of Axiomatic Systems nor the 16 | names of its contributors may be used to endorse or promote products 17 | derived from this software without specific prior written permission. 18 | 19 | THIS SOFTWARE IS PROVIDED BY AXIOMATIC SYSTEMS ''AS IS'' AND ANY 20 | EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 21 | WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 22 | DISCLAIMED. IN NO EVENT SHALL AXIOMATIC SYSTEMS BE LIABLE FOR ANY 23 | DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 24 | (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 25 | LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND 26 | ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 27 | (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 28 | SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 29 | 30 ****************************************************************/ 31 32 #ifndef _NPT_STRINGS_H_ 33 #define _NPT_STRINGS_H_ 34 35 /*---------------------------------------------------------------------- 36 | includes 37 +---------------------------------------------------------------------*/ 38 #include "NptConfig.h" 39 #if defined(NPT_CONFIG_HAVE_NEW_H) 40 #include <new> 41 #endif 42 #include "NptTypes.h" 43 #include "NptConstants.h" 44 #include "NptList.h" 45 #include "NptArray.h" 46 #include "NptDebug.h" 47 #include "NptHash.h" 48 49 /*---------------------------------------------------------------------- 50 | constants 51 +---------------------------------------------------------------------*/ 52 const int NPT_STRING_SEARCH_FAILED = -1; 53 54 /*---------------------------------------------------------------------- 55 | NPT_String 56 +---------------------------------------------------------------------*/ 57 class NPT_String 58 { 59 public: 60 // factories 61 static NPT_String FromInteger(NPT_Int64 value); 62 static NPT_String FromIntegerU(NPT_UInt64 value); 63 static NPT_String Format(const char* format, ...); 64 65 // constructors 66 NPT_String(const NPT_String& str); 67 NPT_String(const char* str); 68 NPT_String(const char* str, NPT_Size length); 69 NPT_String(char c, NPT_Cardinal repeat = 1); NPT_String()70 NPT_String() : m_Chars(NULL) {} ~NPT_String()71 ~NPT_String() { if (m_Chars) GetBuffer()->Destroy(); } 72 73 // string info and manipulations IsEmpty()74 bool IsEmpty() const { return m_Chars == NULL || GetBuffer()->GetLength() == 0; } GetLength()75 NPT_Size GetLength() const { return m_Chars ? GetBuffer()->GetLength() : 0; } GetCapacity()76 NPT_Size GetCapacity() const { return m_Chars ? GetBuffer()->GetAllocated() : 0; } 77 NPT_Result SetLength(NPT_Size length, bool pad = false); 78 void Assign(const char* chars, NPT_Size size); 79 void Append(const char* chars, NPT_Size size); Append(const char * s)80 void Append(const char* s) { Append(s, StringLength(s)); } 81 int Compare(const char* s, bool ignore_case = false) const; 82 static int Compare(const char* s1, const char* s2, bool ignore_case = false); 83 int CompareN(const char* s, NPT_Size count, bool ignore_case = false) const; 84 static int CompareN(const char* s1, const char* s2, NPT_Size count, bool ignore_case = false); 85 86 // substrings 87 NPT_String SubString(NPT_Ordinal first, NPT_Size length) const; SubString(NPT_Ordinal first)88 NPT_String SubString(NPT_Ordinal first) const { 89 return SubString(first, GetLength()); 90 } Left(NPT_Size length)91 NPT_String Left(NPT_Size length) const { 92 return SubString(0, length); 93 } Right(NPT_Size length)94 NPT_String Right(NPT_Size length) const { 95 return length >= GetLength() ? 96 *this : 97 SubString(GetLength()-length, length); 98 } 99 NPT_List<NPT_String> Split(const char* separator) const; 100 NPT_Array<NPT_String> SplitAny(const char* separator) const; 101 static NPT_String Join(NPT_List<NPT_String>& args, const char* separator); 102 103 // buffer management 104 void Reserve(NPT_Size length); 105 106 // hashing 107 NPT_UInt32 GetHash32() const; 108 NPT_UInt64 GetHash64() const; 109 110 // conversions 111 NPT_String ToLowercase() const; 112 NPT_String ToUppercase() const; 113 NPT_Result ToInteger(int& value, bool relaxed = true) const; 114 NPT_Result ToInteger(unsigned int& value, bool relaxed = true) const; 115 NPT_Result ToInteger(long& value, bool relaxed = true) const; 116 NPT_Result ToInteger(unsigned long& value, bool relaxed = true) const; 117 NPT_Result ToInteger32(NPT_Int32& value, bool relaxed = true) const; 118 NPT_Result ToInteger32(NPT_UInt32& value, bool relaxed = true) const; 119 NPT_Result ToInteger64(NPT_Int64& value, bool relaxed = true) const; 120 NPT_Result ToInteger64(NPT_UInt64& value, bool relaxed = true) const; 121 NPT_Result ToFloat(float& value, bool relaxed = true) const; 122 123 // processing 124 void MakeLowercase(); 125 void MakeUppercase(); 126 const NPT_String& Replace(char a, char b); 127 const NPT_String& Replace(char a, const char* b); 128 129 // search 130 int Find(char c, NPT_Ordinal start = 0, bool ignore_case = false) const; 131 int Find(const char* s, NPT_Ordinal start = 0, bool ignore_case = false) const; 132 int FindAny(const char* s, NPT_Ordinal start, bool ignore_case = false) const; 133 int ReverseFind(char c, NPT_Ordinal start = 0, bool ignore_case = false) const; 134 int ReverseFind(const char* s, NPT_Ordinal start = 0, bool ignore_case = false) const; 135 bool StartsWith(const char* s, bool ignore_case = false) const; 136 bool EndsWith(const char* s, bool ignore_case = false) const; 137 138 // editing 139 const NPT_String& Insert(const char* s, NPT_Ordinal where = 0); 140 const NPT_String& Erase(NPT_Ordinal start, NPT_Cardinal count = 1); 141 const NPT_String& Replace(const char* before, const char* after); 142 // void Replace(NPT_Ordinal start, NPT_Cardinal count, const char* s); 143 const NPT_String& TrimLeft(); 144 const NPT_String& TrimLeft(char c); 145 const NPT_String& TrimLeft(const char* chars); 146 const NPT_String& TrimRight(); 147 const NPT_String& TrimRight(char c); 148 const NPT_String& TrimRight(const char* chars); 149 const NPT_String& Trim(); 150 const NPT_String& Trim(char c); 151 const NPT_String& Trim(const char* chars); 152 153 // type casting 154 operator char*() const { return m_Chars ? m_Chars: &EmptyString; } 155 operator const char* () const { return m_Chars ? m_Chars: &EmptyString; } GetChars()156 const char* GetChars() const { return m_Chars ? m_Chars: &EmptyString; } UseChars()157 char* UseChars() { return m_Chars ? m_Chars: &EmptyString; } 158 159 // operator overloading 160 NPT_String& operator=(const char* str); 161 NPT_String& operator=(const NPT_String& str); 162 NPT_String& operator=(char c); 163 const NPT_String& operator+=(const NPT_String& s) { 164 Append(s.GetChars(), s.GetLength()); 165 return *this; 166 } 167 const NPT_String& operator+=(const char* s) { 168 Append(s); 169 return *this; 170 } 171 const NPT_String& operator+=(char c) { 172 Append(&c, 1); 173 return *this; 174 } 175 char operator[](int index) const { 176 NPT_ASSERT((unsigned int)index < GetLength()); 177 return GetChars()[index]; 178 } 179 char& operator[](int index) { 180 NPT_ASSERT((unsigned int)index < GetLength()); 181 return UseChars()[index]; 182 } 183 184 // friend operators 185 friend NPT_String operator+(const NPT_String& s1, const NPT_String& s2) { 186 return s1+s2.GetChars(); 187 } 188 friend NPT_String operator+(const NPT_String& s1, const char* s2); 189 friend NPT_String operator+(const char* s1, const NPT_String& s2); 190 friend NPT_String operator+(const NPT_String& s, char c); 191 friend NPT_String operator+(char c, const NPT_String& s); 192 193 protected: 194 // inner classes 195 class Buffer { 196 public: 197 // class methods Allocate(NPT_Size allocated,NPT_Size length)198 static Buffer* Allocate(NPT_Size allocated, NPT_Size length) { 199 void* mem = ::operator new(sizeof(Buffer)+allocated+1); 200 return new(mem) Buffer(allocated, length); 201 } 202 static char* Create(NPT_Size allocated, NPT_Size length=0) { 203 Buffer* shared = Allocate(allocated, length); 204 return shared->GetChars(); 205 } Create(const char * copy)206 static char* Create(const char* copy) { 207 NPT_Size length = StringLength(copy); 208 Buffer* shared = Allocate(length, length); 209 CopyString(shared->GetChars(), copy); 210 return shared->GetChars(); 211 } Create(const char * copy,NPT_Size length)212 static char* Create(const char* copy, NPT_Size length) { 213 Buffer* shared = Allocate(length, length); 214 CopyBuffer(shared->GetChars(), copy, length); 215 shared->GetChars()[length] = '\0'; 216 return shared->GetChars(); 217 } Create(char c,NPT_Cardinal repeat)218 static char* Create(char c, NPT_Cardinal repeat) { 219 Buffer* shared = Allocate(repeat, repeat); 220 char* s = shared->GetChars(); 221 while (repeat--) { 222 *s++ = c; 223 } 224 *s = '\0'; 225 return shared->GetChars(); 226 } 227 228 // methods GetChars()229 char* GetChars() { 230 // return a pointer to the first char 231 return reinterpret_cast<char*>(this+1); 232 } GetLength()233 NPT_Size GetLength() const { return m_Length; } SetLength(NPT_Size length)234 void SetLength(NPT_Size length) { m_Length = length; } GetAllocated()235 NPT_Size GetAllocated() const { return m_Allocated; } Destroy()236 void Destroy() { ::operator delete((void*)this); } 237 238 private: 239 // methods 240 Buffer(NPT_Size allocated, NPT_Size length = 0) : m_Length(length)241 m_Length(length), 242 m_Allocated(allocated) {} 243 244 // members 245 NPT_Cardinal m_Length; 246 NPT_Cardinal m_Allocated; 247 // the actual string data follows 248 249 }; 250 251 // members 252 char* m_Chars; 253 254 private: 255 // friends 256 friend class Buffer; 257 258 // static members 259 static char EmptyString; 260 261 // methods GetBuffer()262 Buffer* GetBuffer() const { 263 return reinterpret_cast<Buffer*>(m_Chars)-1; 264 } Reset()265 void Reset() { 266 if (m_Chars != NULL) { 267 delete GetBuffer(); 268 m_Chars = NULL; 269 } 270 } 271 char* PrepareToWrite(NPT_Size length); 272 void PrepareToAppend(NPT_Size length, NPT_Size allocate); 273 274 // static methods CopyString(char * dst,const char * src)275 static void CopyString(char* dst, const char* src) { 276 while ((*dst++ = *src++)){} 277 } 278 CopyBuffer(char * dst,const char * src,NPT_Size size)279 static void CopyBuffer(char* dst, const char* src, NPT_Size size) { 280 while (size--) *dst++ = *src++; 281 } 282 StringLength(const char * str)283 static NPT_Size StringLength(const char* str) { 284 NPT_Size length = 0; 285 while (*str++) length++; 286 return length; 287 } 288 }; 289 290 /*---------------------------------------------------------------------- 291 | external operators 292 +---------------------------------------------------------------------*/ 293 inline bool operator==(const NPT_String& s1, const NPT_String& s2) { 294 return s1.Compare(s2) == 0; 295 } 296 inline bool operator==(const NPT_String& s1, const char* s2) { 297 return s1.Compare(s2) == 0; 298 } 299 inline bool operator==(const char* s1, const NPT_String& s2) { 300 return s2.Compare(s1) == 0; 301 } 302 inline bool operator!=(const NPT_String& s1, const NPT_String& s2) { 303 return s1.Compare(s2) != 0; 304 } 305 inline bool operator!=(const NPT_String& s1, const char* s2) { 306 return s1.Compare(s2) != 0; 307 } 308 inline bool operator!=(const char* s1, const NPT_String& s2) { 309 return s2.Compare(s1) != 0; 310 } 311 inline bool operator<(const NPT_String& s1, const NPT_String& s2) { 312 return s1.Compare(s2) < 0; 313 } 314 inline bool operator<(const NPT_String& s1, const char* s2) { 315 return s1.Compare(s2) < 0; 316 } 317 inline bool operator<(const char* s1, const NPT_String& s2) { 318 return s2.Compare(s1) > 0; 319 } 320 inline bool operator>(const NPT_String& s1, const NPT_String& s2) { 321 return s1.Compare(s2) > 0; 322 } 323 inline bool operator>(const NPT_String& s1, const char* s2) { 324 return s1.Compare(s2) > 0; 325 } 326 inline bool operator>(const char* s1, const NPT_String& s2) { 327 return s2.Compare(s1) < 0; 328 } 329 inline bool operator<=(const NPT_String& s1, const NPT_String& s2) { 330 return s1.Compare(s2) <= 0; 331 } 332 inline bool operator<=(const NPT_String& s1, const char* s2) { 333 return s1.Compare(s2) <= 0; 334 } 335 inline bool operator<=(const char* s1, const NPT_String& s2) { 336 return s2.Compare(s1) >= 0; 337 } 338 inline bool operator>=(const NPT_String& s1, const NPT_String& s2) { 339 return s1.Compare(s2) >= 0; 340 } 341 inline bool operator>=(const NPT_String& s1, const char* s2) { 342 return s1.Compare(s2) >= 0; 343 } 344 inline bool operator>=(const char* s1, const NPT_String& s2) { 345 return s2.Compare(s1) <= 0; 346 } 347 348 /*---------------------------------------------------------------------- 349 | hashing 350 +---------------------------------------------------------------------*/ 351 template <> 352 struct NPT_Hash<NPT_String> 353 { 354 NPT_UInt32 operator()(const NPT_String& s) const { return s.GetHash32(); } 355 }; 356 357 358 #endif // _NPT_STRINGS_H_ 359