FUtils/FUString.h

Go to the documentation of this file.
00001 /*
00002     Copyright (C) 2005-2007 Feeling Software Inc.
00003     Portions of the code are:
00004     Copyright (C) 2005-2007 Sony Computer Entertainment America
00005     
00006     MIT License: http://www.opensource.org/licenses/mit-license.php
00007 */
00008 
00015 #ifndef _FU_STRING_H_
00016 #define _FU_STRING_H_
00017 
00018 #ifndef _FM_ARRAY_H_
00019 #include "FMath/FMArray.h"
00020 #endif // _FM_ARRAY_H_
00021 
00023 extern FCOLLADA_EXPORT const char* emptyCharString;
00025 extern FCOLLADA_EXPORT const fchar* emptyFCharString;
00026 
00027 // Already documented elsewhere.
00028 namespace fm
00029 {
00035     template <class CH>
00036     class FCOLLADA_EXPORT stringT : public fm::vector<CH, true>
00037     {
00038     public:
00039         typedef fm::vector<CH, true> Parent; 
00041     public:
00045         static const size_t npos = ~(size_t)0;
00046 
00048         stringT() : Parent() {}
00049 
00052         stringT(const stringT& c) : Parent(c) {}
00053         
00056         stringT(const CH* c) : Parent()
00057         {
00058             append(c);
00059             if (c == NULL || (*c) == 0) push_back((CH) 0);
00060         }
00061 
00066         stringT(const CH* c, size_t length) : Parent()
00067         {
00068             if (c == NULL || length == 0) return;
00069             
00070             if (length != npos)
00071             {
00072                 Parent::resize(length + 1);
00073                 memcpy(Parent::begin(), c, sizeof(CH) * length);
00074                 Parent::back() = 0; // NULL-terminate.
00075             }
00076             else
00077             {
00078                 append(c);
00079                 if (c == NULL || (*c) == 0) push_back((CH) 0);
00080             }
00081         }
00082 
00086         stringT(size_t length, const CH& c) : Parent()
00087         {
00088             Parent::reserve(length + 1);
00089             Parent::insert(Parent::begin(), length, c);
00090             Parent::push_back((CH) 0);
00091         }
00092 
00096         inline size_t length() const { return Parent::size() > 1 ? Parent::size() - 1 : 0; }
00097         inline size_t size() const { return Parent::size() > 1 ? Parent::size() - 1 : 0; } 
00102         inline CH& back() { return *(Parent::end() - 2); }
00103         inline const CH& back() const { return *(Parent::end() - 2); } 
00107         inline void pop_back() { if (Parent::size() > 0) { Parent::pop_back(); Parent::back() = 0; } }
00108 
00112         inline bool empty() const { return Parent::size() <= 1; }
00113 
00119         stringT substr(size_t start, size_t count = npos) const
00120         {
00121             if (start >= length()) return stringT();
00122             if (count == npos || count + start > length()) count = length() - start;
00123             return stringT(c_str() + start, count);
00124         }
00125 
00128         inline void append(const stringT& str)
00129         {
00130             insert(npos, str);
00131         }
00132 
00137         inline void append(const CH* str, size_t count=npos)
00138         {
00139             insert(npos, str, count);
00140         }
00141 
00144         void append(const CH& c)
00145         {
00146             if (c != 0)
00147             {
00148                 size_t originalSize = length();
00149                 Parent::resize(originalSize + 2);
00150                 *(Parent::end() - 2) = c;
00151                 Parent::back() = 0; // NULL-terminate
00152             }
00153         }
00154 
00160         void insert(size_t offset, const CH* str, size_t count=npos)
00161         {
00162             if (str != NULL && (*str != 0))
00163             {
00164                 size_t originalSize = length();
00165                 offset = min(offset, originalSize);
00166 
00167                 size_t str_length = 0;
00168                 const CH* s = str;
00169                 while(*s != 0 && str_length < count) { ++s; ++str_length; }
00170                 resize(originalSize + str_length);
00171                 if (offset < originalSize)
00172                 {
00173                     memmove(Parent::begin() + offset + str_length, Parent::begin() + offset, (originalSize - offset) * sizeof(CH));
00174                 }
00175                 memcpy(Parent::begin() + offset, str, sizeof(CH) * str_length);
00176                 Parent::back() = 0; // NULL-terminate
00177             }
00178         }
00179 
00183         void insert(size_t offset, const stringT& str)
00184         {
00185             size_t str_length = str.length();
00186             if (str_length > 0)
00187             {
00188                 size_t originalSize = length();
00189                 offset = min(offset, originalSize);
00190                 resize(originalSize + str_length);
00191                 if (offset < originalSize)
00192                 {
00193                     memmove(Parent::begin() + offset + str_length, Parent::begin() + offset, (originalSize - offset) * sizeof(CH));
00194                 }
00195                 memcpy(Parent::begin() + offset, str.c_str(), sizeof(CH) * str_length);
00196             }
00197         }
00198 
00201         const CH* c_str() const
00202         {
00203             static CH empty = 0;
00204             if (Parent::size() == 0) return &empty;
00205             return Parent::begin();
00206         }
00207         inline operator const CH*() const { return c_str(); } 
00214         size_t find(const CH& character, size_t offset=0) const
00215         {
00216             if (character > 0)
00217             {
00218                 for (const CH* it = Parent::begin() + offset; it < Parent::end(); ++it)
00219                 {
00220                     if ((*it) == character) return it - Parent::begin();
00221                 }
00222             }
00223             return npos;
00224         }
00225 
00232         size_t find(const stringT& str, size_t offset=0) const
00233         {
00234             if (str.length() > 0 && length() >= str.length())
00235             {
00236                 CH firstMatch = str.front();
00237                 const CH* end_fence = Parent::end() - str.size() + 1;
00238                 for (const CH* it = Parent::begin() + offset; it < end_fence; ++it)
00239                 {
00240                     if ((*it) == firstMatch)
00241                     {
00242                         const CH* it2 = it;
00243                         const CH* sit = str.begin();
00244                         const CH* endIt = (*(str.end() - 1) == 0) ? str.end() - 1 : str.end();
00245                         for (; it2 != Parent::end() && sit != endIt; ++sit, ++it2)
00246                         {
00247                             if ((*sit) != (*it2)) break;
00248                         }
00249                         if (sit == endIt) return it - Parent::begin();
00250                     }
00251                 }
00252             }
00253             return npos;
00254         }
00255 
00261         size_t find(const CH* c, size_t offset=0) const
00262         {
00263             size_t length = 0; const CH* d = c; while (*d != 0) { ++length; ++d; }
00264             if (length > 0 && Parent::size() >= length)
00265             {
00266                 const CH* end_fence = Parent::end() - length + 1;
00267                 for (const CH* it = Parent::begin() + offset; it < end_fence; ++it)
00268                 {
00269                     if ((*it) == (*c))
00270                     {
00271                         const CH* it2 = it;
00272                         for (d = c; it2 != Parent::end() && (*d) != 0; ++it2, ++d)
00273                         {
00274                             if ((*it2) != (*d)) break;
00275                         }
00276                         if (*d == 0) return it - Parent::begin();
00277                     }
00278                 }
00279             }
00280             return npos;
00281         }
00282 
00288         size_t rfind(const CH& character, size_t offset=0) const
00289         {
00290             size_t ret = npos;
00291             if (character > 0)
00292             {
00293                 for (const CH* it = Parent::begin() + offset; it < Parent::end(); ++it)
00294                 {
00295                     if ((*it) == character) ret = it - Parent::begin();
00296                 }
00297             }
00298             return ret;
00299         }
00300 
00307         size_t rfind(const stringT& str, size_t offset=0) const
00308         {
00309             size_t ret = npos;
00310             if (str.length() > 0 && length() >= str.length())
00311             {
00312                 CH firstMatch = str.front();
00313                 const CH* end_fence = Parent::end() - str.size() + 1;
00314                 for (const CH* it = Parent::begin() + offset; it < end_fence; ++it)
00315                 {
00316                     if ((*it) == firstMatch)
00317                     {
00318                         const CH* it2 = it;
00319                         const CH* sit = str.begin();
00320                         const CH* endIt = (*(str.end() - 1) == 0) ? str.end() - 1 : str.end();
00321                         for (; it2 != Parent::end() && sit != endIt; ++sit, ++it2)
00322                         {
00323                             if ((*sit) != (*it2)) break;
00324                         }
00325                         if (sit == endIt) ret = it - Parent::begin();
00326                     }
00327                 }
00328             }
00329             return ret;
00330         }
00331 
00337         size_t rfind(const CH* c, size_t offset=0) const
00338         {
00339             size_t ret = npos;
00340             size_t length = 0; const CH* d = c; while (*d != 0) { ++length; ++d; }
00341             if (length > 0 && Parent::size() >= length)
00342             {
00343                 const CH* end_fence = Parent::end() - length + 1;
00344                 for (const CH* it = Parent::begin() + offset; it < end_fence; ++it)
00345                 {
00346                     if ((*it) == (*c))
00347                     {
00348                         const CH* it2 = it;
00349                         for (d = c; it2 != Parent::end() && (*d) != 0; ++it2, ++d)
00350                         {
00351                             if ((*it2) != (*d)) break;
00352                         }
00353                         if (*d == 0) ret = it - Parent::begin();
00354                     }
00355                 }
00356             }
00357             return ret;
00358         }
00359 
00365         size_t find_first_of(const CH* c, size_t offset=0) const
00366         {
00367             size_t length = 0; const CH* d = c; while (*d != 0) { ++length; ++d; }
00368             if (length > 0 && Parent::size() >= length)
00369             {
00370                 for (const CH* it = Parent::begin() + offset; it < Parent::end(); ++it)
00371                 {
00372                     d = c;
00373                     while (*d != 0 && *d != *it) { ++d; }
00374                     if (*d != 0) return it - Parent::begin();
00375                 }
00376             }
00377             return npos;
00378         }
00379 
00385         size_t find_last_of(const CH* c, size_t offset=0) const
00386         {
00387             size_t ret = length() - offset; // UNOPTIMIZE. Didn't feel like this is an important-enough function.
00388             size_t length = 0; const CH* d = c; while (*d != 0) { ++length; ++d; }
00389             if (length > 0 && Parent::size() >= length)
00390             {
00391                 const CH* end = Parent::end() - (length + offset);
00392                 const CH* begin = Parent::begin();
00393                 for (const CH* it = end; it >= begin; --it)
00394                 {
00395                     d = c;
00396                     while (*d != 0) 
00397                     {
00398                         if (*d == *it) return ret;
00399                         ++d;
00400                     }
00401                     --ret;
00402                 }
00403             }
00404             return npos;
00405         }
00406         
00415         void erase(size_t start=0, size_t end=npos)
00416         {
00417             if (start < length() && start < end) // covers size() == 0.
00418             {
00419                 if (end > length()) end = length();
00420                 Parent::erase(Parent::begin() + start, Parent::begin() + end);
00421             }
00422         }
00423 
00431         void resize(size_t size)
00432         {
00433             Parent::resize(size + 1);
00434             Parent::back() = 0; // NULL-terminate
00435         }
00436 
00444         void resize(size_t count, const CH& value)
00445         {
00446             Parent::resize(size + 1, value);
00447             Parent::back() = 0; // NULL-terminate
00448         }
00449     };
00450 
00452     typedef stringT<char> string;
00453 
00458     template <class CharT> stringT<CharT> operator+(const stringT<CharT>& A, const stringT<CharT>& B) { stringT<CharT> C = A; C.append(B); return C; }
00459     template <class CharT> stringT<CharT> operator+(const CharT* A, const stringT<CharT>& B) { stringT<CharT> C = A; C.append(B); return C; } 
00460     template <class CharT> stringT<CharT> operator+(const stringT<CharT>& A, const CharT* B) { stringT<CharT> C = A; C.append(B); return C; } 
00461     template <class CharT> stringT<CharT>& operator+=(stringT<CharT>& A, const stringT<CharT>& B) { A.append(B); return A; } 
00462     template <class CharT> stringT<CharT>& operator+=(stringT<CharT>& A, const CharT* B) { A.append(B); return A; } 
00468     template <class CharT> stringT<CharT>& operator+=(stringT<CharT>& A, const CharT& B) { A.append(B); return A; }
00469 
00475     template <class CharT> bool operator<(const stringT<CharT>& A, const stringT<CharT>& B)
00476     {
00477         const CharT* a = A.c_str(); const CharT* b = B.c_str();
00478         while ((*a) != 0 && (*b) != 0 && (*a) == (*b)) { ++a; ++b; }
00479         return (*a) < (*b);
00480     }
00481 
00486     template <class CharT> bool operator==(const stringT<CharT>& A, const stringT<CharT>& B)
00487     {
00488         if (A.length() != B.length()) return false;
00489         const CharT* a = A.c_str(); const CharT* b = B.c_str();
00490         while ((*a) != 0 && (*a) == (*b)) { ++a; ++b; }
00491         return (*a) == (*b);
00492     }
00493 
00498     template <class CharT> bool operator!=(const stringT<CharT>& A, const stringT<CharT>& B)
00499     {
00500         if (A.length() != B.length()) return true;
00501         const CharT* a = A.c_str(); const CharT* b = B.c_str();
00502         while ((*a) != 0 && (*a) == (*b)) { ++a; ++b; }
00503         return (*a) != (*b);
00504     }
00505 
00510     template <class CharT> bool operator!=(const stringT<CharT>& A, const CharT* B)
00511     {
00512         if (B == NULL) return true;
00513         size_t B_length = 0; { const CharT* b = B; while (*b != 0) { ++b; ++B_length; } }
00514         if (A.length() != B_length) return true;
00515         const CharT* a = A.c_str(); const CharT* b = B;
00516         while ((*a) != 0 && (*a) == (*b)) { ++a; ++b; }
00517         return (*a) != (*b);
00518     }
00519 };
00520 
00522 typedef fm::stringT<fchar> fstring;
00523 
00525 typedef fm::vector<fstring> FStringList;
00526 
00528 typedef fm::vector<fm::string> StringList;
00529 
00534 inline bool IsEquivalent(const char* sz1, const char* sz2) { return strcmp(sz1, sz2) == 0; }
00535 inline bool IsEquivalent(const fm::string& sz1, const char* sz2) { return strcmp(sz1.c_str(), sz2) == 0; } 
00536 inline bool IsEquivalent(const char* sz1, const fm::string& sz2) { return strcmp(sz1, sz2.c_str()) == 0; } 
00537 inline bool IsEquivalent(const fm::string& sz1, const fm::string& sz2) { return strcmp(sz1.c_str(), sz2.c_str()) == 0; } 
00543 inline bool IsEquivalentI(const char* sz1, const char* sz2) { return _stricmp(sz1, sz2) == 0; }
00544 inline bool IsEquivalentI(const fm::string& sz1, const char* sz2) { return _stricmp(sz1.c_str(), sz2) == 0; } 
00545 inline bool IsEquivalentI(const char* sz1, const fm::string& sz2) { return _stricmp(sz1, sz2.c_str()) == 0; } 
00546 inline bool IsEquivalentI(const fm::string& sz1, const fm::string& sz2) { return _stricmp(sz1.c_str(), sz2.c_str()) == 0; } 
00547 #ifdef UNICODE
00548 inline bool IsEquivalentI(const fchar* sz1, const fchar* sz2) { return fstricmp(sz1, sz2) == 0; } 
00549 inline bool IsEquivalentI(const fstring& sz1, const fchar* sz2) { return fstricmp(sz1.c_str(), sz2) == 0; } 
00550 inline bool IsEquivalentI(const fchar* sz1, const fstring& sz2) { return fstricmp(sz1, sz2.c_str()) == 0; } 
00551 inline bool IsEquivalentI(const fstring& sz1, const fstring& sz2) { return fstricmp(sz1.c_str(), sz2.c_str()) == 0; } 
00552 #endif // UNICODE
00553 
00558 inline bool operator==(const fm::string& sz1, const char* sz2) { return strcmp(sz1.c_str(), sz2) == 0; }
00559 
00560 #ifdef UNICODE
00561 
00565 inline bool IsEquivalent(const fchar* sz1, const fchar* sz2) 
00566 { 
00567     return (sz1 == sz2) ? true : // ptrs same, are equivalent
00568         (sz1 == NULL || sz2 == NULL) ? // either ptr null, not equivalent
00569             false : fstrcmp(sz1, sz2) == 0; // do actual test
00570 }
00571 inline bool IsEquivalent(const fstring& sz1, const fchar* sz2) { return IsEquivalent(sz1.c_str(), sz2); } 
00572 inline bool IsEquivalent(const fchar* sz1, const fstring& sz2) { return IsEquivalent(sz1, sz2.c_str()); } 
00573 inline bool IsEquivalent(const fstring& sz1, const fstring& sz2) { return IsEquivalent(sz1.c_str(), sz2.c_str()); } 
00579 inline bool operator==(const fstring& sz1, const fchar* sz2) { return IsEquivalent(sz1.c_str(), sz2); }
00580 #endif // UNICODE
00581 
00582 // Include the main string modification classes.
00583 #include "FUtils/FUStringBuilder.h"
00584 #include "FUtils/FUStringConversion.h"
00585 
00587 #define FS(a) fstring(FC(a))
00588 
00589 #define TO_FSTRING(a) FUStringConversion::ToFString(a)
00590 
00591 #define TO_STRING(a) FUStringConversion::ToString(a)
00592 
00594 extern FCOLLADA_EXPORT const fm::string emptyString;
00596 extern FCOLLADA_EXPORT const fstring emptyFString;
00597 
00602 inline bool IsEquivalent(FUSStringBuilder& builder, const char* sz) { return IsEquivalent(builder.ToCharPtr(), sz); }
00603 inline bool IsEquivalent(FUSStringBuilder& builder, const fm::string& sz) { return IsEquivalent(builder.ToCharPtr(), sz.c_str()); } 
00604 #ifdef UNICODE
00605 inline bool IsEquivalent(FUStringBuilder& builder, const fchar* sz) { return IsEquivalent(builder.ToCharPtr(), sz); } 
00606 inline bool IsEquivalent(FUStringBuilder& builder, const fstring& sz) { return IsEquivalent(builder.ToCharPtr(), sz.c_str()); } 
00607 #endif
00608 
00609 #endif // _FU_STRING_H_

Generated on Thu Feb 14 16:58:36 2008 for FCollada by  doxygen 1.4.6-NO