- Main Page
- Modules
- Namespaces
- Classes
- Files
- Related Pages

- File List
- File Members

# 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_