00001
00002
00003
00004
00005
00006
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
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;
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;
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;
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 ∅
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;
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)
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;
00435 }
00436
00444 void resize(size_t count, const CH& value)
00445 {
00446 Parent::resize(size + 1, value);
00447 Parent::back() = 0;
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 :
00568 (sz1 == NULL || sz2 == NULL) ?
00569 false : fstrcmp(sz1, sz2) == 0;
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
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_