00001
00002
00003
00004
00005
00011 #ifndef HSTRING_H
00012 #define HSTRING_H
00013
00014 #include <cctype>
00024 class HString : public HObj
00025 {
00026 typedef HObj base_class;
00027 static StringPtr ClassName(void) { return "HString"; }
00028
00029
00030
00031 public:
00032 typedef enum {
00033 ALIGN_DEFAULT = 0,
00034 ALIGN_LEFT = 0x01,
00035 ALIGN_CENTER = 0x02,
00036 ALIGN_RIGHT = 0x03
00037 } Alignment;
00038 protected:
00039 std::string m_str;
00040
00041
00042
00043 public:
00044 HString(void)
00045 { m_str.clear(); }
00046
00047 HString(StringPtr pstr) : m_str(pstr)
00048 { }
00049
00050 HString(const HString & rhs) : m_str(rhs.m_str)
00051 { }
00052
00053 virtual ~HString()
00054 { }
00055
00056
00057
00058 public:
00067 static uint32
00068 Hash(StringPtr pstr)
00069 {
00070 uint32 uCRC = 0X811C9DC5L;
00071
00072 while (STR_VALID(pstr))
00073 {
00074 uCRC *= 0x01000193L;
00075 uCRC ^= uint32( *pstr++ );
00076 }
00077
00078 return uCRC;
00079 }
00087 HString &
00088 Align(HString::Alignment align, uint32 uWidth, Text chPad = ' ') throw()
00089 {
00090 (void) HError::NoError();
00091
00092 ASSERT(uWidth > 0);
00093
00094 (void) Trim();
00095
00096 switch (align)
00097 {
00098 case ALIGN_DEFAULT:
00099 case ALIGN_LEFT:
00100 if (uWidth > m_str.size())
00101 m_str.append( (uWidth - m_str.size()), chPad);
00102 break;
00103
00104 case ALIGN_RIGHT:
00105 if (uWidth > m_str.size())
00106 m_str.insert(m_str.begin(), (uWidth - m_str.size()), chPad);
00107 break;
00108
00109 case ALIGN_CENTER:
00110 if (uWidth > m_str.size())
00111 {
00112 uint32 uPadding = uWidth - m_str.size();
00113
00114 m_str.append( (uPadding / 2), chPad);
00115 m_str.insert( m_str.begin(), (uPadding - (uPadding / 2)), chPad);
00116 }
00117 break;
00118
00119 default:
00120 HError::Throw(ERR_BAD_PARAMETER, __FILE__, __LINE__);
00121 }
00122
00123 return *this;
00124 }
00131 ErrCode
00132 Append(StringPtr pstr)
00133 {
00134 if (STR_VALID(pstr))
00135 m_str += pstr;
00136 return HError::NoError();
00137 }
00145 int32
00146 Compare(const HString & rhs, bool bCase = true) const
00147 {
00148 if (&rhs == this) return 0;
00149
00150 return bCase ? Humble::safe_strcmp(m_str.c_str(), rhs.m_str.c_str()) :
00151 Humble::safe_strcmpi(m_str.c_str(), rhs.m_str.c_str());
00152 }
00160 int32
00161 Compare(StringPtr pstr, bool bCase = true) const
00162 {
00163 if (m_str.c_str() == pstr) return 0;
00164
00165 return bCase ? Humble::safe_strcmp(m_str.c_str(), pstr) :
00166 Humble::safe_strcmpi(m_str.c_str(), pstr);
00167 }
00178 int32
00179 Find(Text ch, uint32 uStart = 0) const
00180 {
00181 std::string::size_type sPos;
00182
00183 if (!isValidIndex(uStart)) return -1;
00184
00185 sPos = (uStart == 0) ? m_str.find(ch) : m_str.find(ch, uStart);
00186
00187 return (sPos == std::string::npos) ? -1 : int32(sPos);
00188 }
00199 int32
00200 Find(StringPtr pstr, uint32 uStart = 0) const
00201 {
00202 std::string::size_type sPos;
00203
00204 if (STR_EMPTY(pstr) || !isValidIndex(uStart))
00205 return -1;
00206
00207 sPos = (uStart == 0) ? m_str.find(pstr) : m_str.find(pstr, uStart);
00208
00209 return (sPos == std::string::npos) ? -1 : int32(sPos);
00210 }
00220 int32
00221 FindLast(Text ch) const
00222 {
00223 std::string::size_type sPos = m_str.rfind(ch);
00224
00225 return (sPos == std::string::npos) ? -1 : int32(sPos);
00226 }
00236 int32
00237 FindLast(StringPtr pstr) const
00238 {
00239 std::string::size_type sPos;
00240
00241 if (STR_EMPTY(pstr) ||
00242 (sPos = m_str.rfind(pstr)) == std::string::npos)
00243 {
00244 return -1;
00245 }
00246
00247 return int32(sPos);
00248 }
00258 #ifndef DOXYGEN_SHOULD_SKIP_THIS
00259 GCC_ONLY( __attribute__ ((format (printf,2,3))) )
00260 #endif
00261 int32
00262 Format(StringPtr pstrFormat, ...)
00263 {
00264 if (STR_VALID(pstrFormat))
00265 {
00266 va_list vaList;
00267
00268 va_start(vaList, pstrFormat);
00269 (void) FormatV(pstrFormat, vaList);
00270 va_end(vaList);
00271 }
00272 else
00273 SetEmpty();
00274
00275 return GetLength();
00276 }
00288 int32
00289 FormatV(StringPtr pstrFormat, va_list & vaList)
00290 {
00291 if (STR_EMPTY(pstrFormat))
00292 {
00293 DEBUG_LOG("Hstring::FormatV() => NULL format string.\n");
00294 SetEmpty();
00295 return 0;
00296 }
00297
00298
00299
00300
00301
00302
00303 const int32 kMaxIntLen = 40;
00304 const int32 kMaxFloatLen = 312 + 6;
00305
00306
00307
00308 va_list argList;
00309 int32 nLen,
00310 nItemLen,
00311 nMaxLen = 0;
00312 int nPrecision,
00313 nWidth;
00314
00315 argList = vaList;
00316 for (StringPtr pstr = pstrFormat; STR_VALID(pstr); ++pstr)
00317 {
00318
00319 if (*pstr != '%' || *(pstr + 1) == '%')
00320 {
00321 nMaxLen++;
00322 continue;
00323 }
00324
00325 nItemLen = nWidth = 0;
00326
00327 for (pstr++ ; STR_VALID(pstr); ++pstr)
00328 {
00329
00330 if (*pstr == '#')
00331 nMaxLen += 2;
00332 else if (*pstr == '*')
00333 nWidth = va_arg(argList, int);
00334 else if (*pstr == '-' || *pstr == '+' || *pstr == '0' || *pstr == ' ')
00335 ;
00336 else
00337 break;
00338 }
00339
00340
00341
00342 if (nWidth == 0)
00343 {
00344 nWidth = Humble::safe_strtoi(pstr);
00345 while (STR_VALID(pstr) && isdigit(*pstr))
00346 pstr++;
00347 }
00348
00349 ASSERT(nWidth >= 0);
00350
00351
00352
00353 nPrecision = 0;
00354 if (*pstr == '.')
00355 {
00356 pstr++;
00357 if (*pstr == '*')
00358 {
00359 nPrecision = va_arg(argList, int);
00360 pstr++;
00361 }
00362 else
00363 {
00364 nPrecision = Humble::safe_strtoi(pstr);
00365 while (STR_VALID(pstr) && isdigit(*pstr))
00366 pstr++;
00367 }
00368
00369 ASSERT(nPrecision >= 0);
00370 }
00371
00372
00373
00374 switch (*pstr)
00375 {
00376 case 'l':
00377 case 'h':
00378 pstr++;
00379 break;
00380 }
00381
00382
00383
00384 switch (*pstr)
00385 {
00386
00387 case 'c':
00388 nItemLen = 2;
00389 (void) va_arg(argList, Text);
00390 break;
00391
00392 case 's':
00393 {
00394 StringPtr pstrNextArg = va_arg(argList, StringPtr);
00395
00396 if (NULL_PTR(pstrNextArg))
00397 nItemLen = 6;
00398 else
00399 {
00400 nItemLen = STR_LEN(pstrNextArg);
00401 nItemLen = max(1, nItemLen);
00402 }
00403 }
00404 break;
00405 }
00406
00407
00408
00409 if (nItemLen != 0)
00410 {
00411 nItemLen = max(nItemLen, nWidth);
00412 if (nPrecision != 0)
00413 nItemLen = min(nItemLen, nPrecision);
00414 }
00415 else
00416 {
00417 switch (*pstr)
00418 {
00419
00420 case 'd':
00421 case 'i':
00422 case 'u':
00423 case 'x':
00424 case 'X':
00425 case 'o':
00426 (void) va_arg(argList, int);
00427 nItemLen = max(kMaxIntLen, nWidth + nPrecision);
00428 break;
00429
00430 case 'e':
00431 case 'E':
00432 case 'g':
00433 case 'G':
00434 (void) va_arg(argList, double);
00435 nItemLen = max(128, nWidth + nPrecision);
00436 break;
00437
00438 case 'f':
00439 {
00440 Text szTmp[kMaxFloatLen];
00441
00442 nItemLen = nWidth + nPrecision;
00443 if (nItemLen < kMaxFloatLen)
00444 {
00445 nItemLen = STR_SPRINTF( szTmp, kMaxFloatLen,
00446 "%*.*f",
00447 nWidth, nPrecision + 6, va_arg(argList, double));
00448 }
00449 }
00450 break;
00451
00452 case 'p':
00453 (void) va_arg(argList, void *);
00454 nItemLen = max(kMaxIntLen, nWidth + nPrecision);
00455 break;
00456
00457
00458 case 'n':
00459 (void) va_arg(argList, int*);
00460 break;
00461
00462 default:
00463 ASSERT(0);
00464 }
00465 }
00466
00467 nMaxLen += nItemLen;
00468 }
00469
00470
00471
00472
00473
00474
00475 if (nMaxLen < 512)
00476 {
00477 Text szBuffer[512] = { '\0' };
00478
00479 nLen = Humble::safe_vsprintf(szBuffer, nMaxLen, pstrFormat, vaList);
00480 m_str = szBuffer;
00481 }
00482 else
00483 {
00484 TextPtr pstr = new Text[ nMaxLen+1 ];
00485
00486 ASSERT_PTR(pstr);
00487 DEBUG_LOG( "HString::FormatV() => allocated %ld byte string.\n",
00488 (nMaxLen+1));
00489
00490 nLen = Humble::safe_vsprintf(pstr, nMaxLen, pstrFormat, vaList);
00491 m_str = pstr;
00492
00493 delete [] pstr;
00494 }
00495
00496 #if __DEBUG__
00497 if (nLen > nMaxLen)
00498 {
00499 DEBUG_LOG( "HString::FormatV() => actual length of \"%s\" is %ld (estimated as %ld).\n",
00500 m_str.c_str(), nLen, nMaxLen);
00501 }
00502 #endif
00503
00504 return nLen;
00505 }
00516 HString
00517 Left(uint32 uCount) const
00518 {
00519 std::string str;
00520 uint32 uLen = GetLength();
00521
00522 if (uCount >= uLen)
00523 str = m_str;
00524 else if (uCount > 0)
00525 str = m_str.substr(0, uCount);
00526
00527 return HString(str.c_str());
00528 }
00533 HString &
00534 MakeLower(void)
00535 {
00536 for (uint32 udx = 0; udx < m_str.length(); ++udx)
00537 m_str[udx] = tolower( m_str[udx] );
00538
00539
00540 return *this;
00541 }
00546 HString &
00547 MakeUpper(void)
00548 {
00549 for (uint32 udx = 0; udx < m_str.length(); ++udx)
00550 m_str[udx] = toupper( m_str[udx] );
00551
00552
00553
00554 return *this;
00555 }
00567 HString
00568 Mid(uint32 uStart, int32 nCount = -1) const
00569 {
00570 std::string str;
00571
00572 if (isValidIndex(uStart))
00573 {
00574 if (nCount < 0 || nCount > int32(GetLength() - uStart))
00575 nCount = int32(GetLength() - uStart);
00576
00577 if (nCount > 0)
00578 str = m_str.substr(uStart, nCount);
00579 }
00580
00581 return HString(str.c_str());
00582 }
00593 int32
00594 Replace(Text chOld, Text chNew)
00595 {
00596 std::string::iterator it;
00597 int32 nCount = 0;
00598
00599 for (it = m_str.begin(); it != m_str.end(); ++it)
00600 if (*it == chOld)
00601 {
00602 *it = chNew;
00603 nCount++;
00604 }
00605
00606 return nCount;
00607 }
00618 HString
00619 Right(int32 nCount) const
00620 {
00621 std::string str;
00622 int32 nLen = GetLength();
00623
00624 if (nCount >= nLen)
00625 str = m_str;
00626 else if (nCount > 0)
00627 str = m_str.substr(nLen - nCount);
00628
00629 return HString(str.c_str());
00630 }
00635 HString &
00636 Trim(void)
00637 {
00638 TrimRight();
00639 TrimLeft();
00640 return *this;
00641 }
00646 HString &
00647 TrimLeft(void)
00648 {
00649 while (!m_str.empty() && std::isspace( m_str[0] ))
00650 m_str.erase( m_str.begin() );
00651
00652 return *this;
00653 }
00658 HString &
00659 TrimRight(void)
00660 {
00661 while (!m_str.empty() && std::isspace( m_str[m_str.size() - 1] ))
00662 m_str.erase(m_str.end() - 1);
00663
00664 return *this;
00665 }
00666
00667
00668
00669 public:
00673 inline Text GetAt(uint32 udx) const
00674 { return isValidIndex(udx) ? m_str[udx] : '\0'; }
00681 inline void SetAt(uint32 udx, Text ch)
00682 {
00683 if (isValidIndex(udx))
00684 m_str[udx] = ch;
00685 }
00689 inline void SetEmpty(void)
00690 { m_str.clear(); }
00693 inline int32 GetLength(void) const
00694 { return m_str.length(); }
00697 inline StringPtr GetString(void) const
00698 { return IsEmpty() ? kStrEmpty : m_str.c_str(); }
00701 inline int32 GetValue(void) const
00702 { return IsEmpty() ? 0 : Humble::safe_strtoi( m_str.c_str() ); }
00703
00704
00705
00706 public:
00709 inline bool IsEmpty(void) const
00710 { return m_str.empty(); }
00713 inline bool IsNotEmpty(void) const
00714 { return !m_str.empty(); }
00715 protected:
00719 inline bool isValidIndex(const uint32 udx) const
00720 { return (std::string::size_type(udx) < m_str.length()); }
00721
00722
00723
00724 public:
00725 operator StringPtr (void) const
00726 { return GetString(); }
00727
00728 Text operator [] (int index) const
00729 { return GetAt(index); }
00730
00731 bool operator == (StringPtr pstr) const
00732 { return (m_str == pstr); }
00733 bool operator == (const HString & rhs) const
00734 { return (m_str == rhs.m_str); }
00735
00736 bool operator != (StringPtr pstr) const
00737 { return (m_str != pstr); }
00738 bool operator != (const HString & rhs) const
00739 { return (m_str != rhs.m_str); }
00740
00741 bool operator < (StringPtr pstr) const
00742 { return (m_str < pstr); }
00743 bool operator < (const HString & rhs) const
00744 { return (m_str < rhs.m_str); }
00745
00746 bool operator <= (StringPtr pstr) const
00747 { return (m_str <= pstr); }
00748 bool operator <= (const HString & rhs) const
00749 { return (m_str <= rhs.m_str); }
00750
00751 bool operator > (StringPtr pstr) const
00752 { return (m_str > pstr); }
00753 bool operator > (const HString & rhs) const
00754 { return (m_str > rhs.m_str); }
00755
00756 bool operator >= (StringPtr pstr) const
00757 { return (m_str >= pstr); }
00758 bool operator >= (const HString & rhs) const
00759 { return (m_str >= rhs.m_str); }
00760
00761 HString & operator = (StringPtr pstr)
00762 {
00763 m_str = STR_SAFE(pstr);
00764 return *this;
00765 }
00766
00767 HString & operator = (const HString & rhs)
00768 {
00769 if (&rhs != this)
00770 m_str.assign(rhs.m_str);
00771 return *this;
00772 }
00773
00774 HString & operator = (const std::string & rhs)
00775 {
00776 if (&rhs != &m_str)
00777 m_str = rhs;
00778 return *this;
00779 }
00780
00781 HString & operator += (StringPtr pstr)
00782 {
00783 if (STR_VALID(pstr))
00784 m_str += pstr;
00785 return *this;
00786 }
00787
00788 HString & operator += (const HString & rhs)
00789 {
00790 m_str.append(rhs.m_str);
00791 return *this;
00792 }
00793
00794 friend HString operator + (const HString & str1, const HString & str2)
00795 {
00796 HString str(str1);
00797 str += str2;
00798 return str;
00799 }
00800
00801 friend HString operator + (const HString & str1, StringPtr pstr2)
00802 {
00803 HString str(str1);
00804 str += pstr2;
00805 return str;
00806 }
00807
00808 friend HString operator + (StringPtr pstr1, const HString & str2)
00809 {
00810 HString str(pstr1);
00811 str += str2;
00812 return str;
00813 }
00814
00815 };
00816
00817
00818
00834 template <uint32 MAX_LEN>
00835 class HStr : public HObj
00836 {
00837 typedef HObj base_class;
00838 static StringPtr ClassName(void) { return "HStr"; }
00839
00840
00841
00842 protected:
00843 Text m_buffer[MAX_LEN+1];
00844
00845
00846
00847 public:
00848 HStr()
00849 { SetEmpty(); }
00850 HStr(HStr const & T)
00851 { assign(T.m_buffer); }
00852 HStr(StringPtr pstr)
00853 { assign(pstr); }
00854
00855 virtual
00856 ~HStr()
00857 { };
00858
00859
00860
00861 public:
00869 HStr &
00870 Align(HString::Alignment align, uint32 uWidth, Text chPad = ' ') throw()
00871 {
00872 (void) HError::NoError();
00873
00874 ASSERT(uWidth > 0);
00875
00876 (void) Trim();
00877
00878 switch (align)
00879 {
00880 case HString::ALIGN_DEFAULT:
00881 case HString::ALIGN_LEFT:
00882 for (uint32 udx = GetLength(); udx < uWidth; ++udx)
00883 SetAt(udx, chPad);
00884 break;
00885
00886 case HString::ALIGN_RIGHT:
00887 if (uWidth > uint32(GetLength()))
00888 {
00889 Text szTmp[MAX_LEN+1] = { '\0' };
00890
00891 uWidth -= GetLength();
00892 for (uint32 udx = 0; udx < uWidth; ++udx)
00893 szTmp[udx] = chPad;
00894
00895 STR_NCPY(&szTmp[uWidth], m_buffer, MAX_LEN);
00896 assign(szTmp);
00897 }
00898 break;
00899
00900 case HString::ALIGN_CENTER:
00901 if (uWidth > uint32(GetLength()))
00902 {
00903 Text szTmp[MAX_LEN+1] = { '\0' };
00904 uint32 uPadding = (uWidth - GetLength()) / 2;
00905
00906 for (uint32 udx = 0; udx < uWidth; udx++)
00907 szTmp[udx] = chPad;
00908
00909 MEM_COPY(&szTmp[uPadding], m_buffer, GetLength());
00910 assign(szTmp);
00911 }
00912 break;
00913
00914 default:
00915 HError::Throw(ERR_BAD_PARAMETER, __FILE__, __LINE__);
00916 }
00917
00918 return *this;
00919 }
00926 ErrCode
00927 Append(StringPtr pstr)
00928 {
00929 if (validPtr(pstr))
00930 STR_CAT(m_buffer, pstr, MAX_LEN);
00931 return HError::NoError();
00932 }
00939 int32
00940 Compare(const HStr & rhs, bool bCase = true) const
00941 {
00942 if (&rhs == this) return 0;
00943
00944 return bCase ? Humble::safe_strcmp(m_buffer, rhs.m_buffer) :
00945 Humble::safe_strcmpi(m_buffer, rhs.m_buffer);
00946 }
00953 int32
00954 Compare(StringPtr pstr, bool bCase = true) const
00955 {
00956 if (pstr == m_buffer) return 0;
00957
00958 return bCase ? Humble::safe_strcmp(m_buffer, pstr) :
00959 Humble::safe_strcmpi(m_buffer, pstr);
00960 }
00972 int32
00973 Find(Text ch, uint32 uStart = 0) const
00974 {
00975 StringPtr psz = NULL;
00976
00977 if (isValidIndex(uStart))
00978 psz = Humble::safe_strchr(&m_buffer[uStart], ch);
00979
00980 return GOOD_PTR(psz) ? int32(psz - m_buffer) : -1;
00981 }
00992 int32
00993 Find(StringPtr pstr, uint32 uStart = 0) const
00994 {
00995 int32 nOffset = -1;
00996
00997 if (STR_VALID(pstr) && isValidIndex(uStart))
00998 {
00999 StringPtr pstrHere = strstr(&m_buffer[uStart], pstr);
01000 nOffset = GOOD_PTR(pstrHere) ? int32(pstrHere - m_buffer) : -1;
01001 }
01002
01003 return nOffset;
01004 }
01015 int32
01016 FindLast(Text ch) const
01017 {
01018 StringPtr psz = Humble::safe_strrchr(m_buffer, ch);
01019
01020 return GOOD_PTR(psz) ? int32(psz - m_buffer) : -1;
01021 }
01027 #ifndef DOXYGEN_SHOULD_SKIP_THIS
01028 GCC_ONLY(__attribute__((format(printf,2,3))))
01029 #endif
01030 int32
01031 Format(StringPtr pstr, ...)
01032 {
01033 int32 nLen;
01034 va_list vaList;
01035
01036 va_start(vaList, pstr);
01037 nLen = Humble::safe_vsprintf(m_buffer, MAX_LEN, pstr, vaList);
01038 va_end(vaList);
01039
01040 return nLen;
01041 }
01052 HStr<MAX_LEN>
01053 Left(uint32 uCount) const
01054 {
01055 Text szTmp[MAX_LEN+1] = { '\0' };
01056 uint32 uLen = GetLength();
01057
01058 if (uCount >= uLen)
01059 Humble::safe_strncpy(szTmp, m_buffer, MAX_LEN);
01060 else if (uCount > 0)
01061 Humble::safe_strncpy(szTmp, m_buffer, uCount);
01062
01063 return HStr<MAX_LEN>(szTmp);
01064 }
01069 HStr &
01070 MakeLower(void)
01071 {
01072 (void) Humble::safe_strlwr(m_buffer);
01073 return *this;
01074 }
01079 HStr &
01080 MakeUpper(void)
01081 {
01082 (void) Humble::safe_strupr(m_buffer);
01083 return *this;
01084 }
01096 HStr<MAX_LEN>
01097 Mid(uint32 uStart, int32 nCount = -1) const
01098 {
01099 Text szTmp[MAX_LEN+1] = { '\0' };
01100 uint32 uCount = (nCount < 0) ? GetLength() : nCount;
01101
01102 if (isValidIndex(uStart) && uCount > 0)
01103 Humble::safe_strncpy(szTmp, &m_buffer[uStart], uCount);
01104
01105 return HStr<MAX_LEN>(szTmp);
01106 }
01117 int32
01118 Replace(Text chOld, Text chNew)
01119 {
01120 int32 nCount = 0;
01121
01122 for (uint32 udx = 0; udx < MAX_LEN; ++udx)
01123 if (m_buffer[udx] == chOld)
01124 {
01125 m_buffer[udx] = chNew;
01126 nCount++;
01127 }
01128
01129 return nCount;
01130 }
01141 HStr<MAX_LEN>
01142 Right(uint32 uCount) const
01143 {
01144 HStr<MAX_LEN> str;
01145 uint32 uLen = GetLength();
01146
01147 if (uCount >= uLen)
01148 str.assign(m_buffer);
01149 else if (uCount > 0)
01150 str.assign(&m_buffer[uLen - uCount]);
01151
01152 return str;
01153 }
01158 HStr &
01159 Trim(void)
01160 {
01161 TrimRight();
01162 TrimLeft();
01163 return *this;
01164 }
01169 HStr &
01170 TrimLeft(void)
01171 {
01172 uint32 uFirst;
01173
01174 for (uFirst = 0; uFirst < MAX_LEN; ++uFirst)
01175 if (!isspace(m_buffer[uFirst]))
01176 break;
01177
01178 if (uFirst > 0)
01179 {
01180 MEM_MOVE(m_buffer, &m_buffer[uFirst], MAX_LEN - uFirst);
01181 MEM_ZERO(&m_buffer[MAX_LEN - uFirst], uFirst);
01182 }
01183
01184 return *this;
01185 }
01190 HStr &
01191 TrimRight(void)
01192 {
01193 for (uint32 udx = GetLength() - 1; isspace(m_buffer[udx]); --udx)
01194 {
01195 m_buffer[udx] = '\0';
01196 if (udx == 0)
01197 break;
01198 }
01199
01200 return *this;
01201 }
01202 protected:
01207 void
01208 assign(StringPtr pstr)
01209 {
01210 if (validPtr(pstr))
01211 STR_NCPY(m_buffer, pstr, MAX_LEN);
01212 else
01213 SetEmpty();
01214 }
01215
01216
01217
01218 public:
01224 inline Text GetAt(int32 index) const
01225 { return isValidIndex(index) ? m_buffer[index] : '\0'; }
01229 inline void SetAt(int32 index, Text ch)
01230 {
01231 if (isValidIndex(index))
01232 m_buffer[index] = ch;
01233 }
01236 inline int32 GetLength(void) const
01237 { return STR_NLEN(m_buffer, MAX_LEN+1); }
01240 inline static int32 GetMaxLength(void)
01241 { return MAX_LEN; }
01244 inline StringPtr GetString(void) const
01245 { return m_buffer; }
01248 inline int32 GetValue(void) const
01249 { return IsEmpty() ? 0 : Humble::safe_strtoi(m_buffer); }
01251 inline void SetEmpty(void)
01252 { MEM_ZERO(m_buffer, MAX_LEN+1); }
01253
01254
01255
01256 public:
01263 inline int32 FormatV(StringPtr pstr, va_list & vaList)
01264 { return Humble::safe_vsprintf(m_buffer, MAX_LEN, pstr, vaList); }
01269 uint32 Hash(void) const
01270 { return HStr::Hash(m_buffer); }
01275 inline bool IsEmpty(void) const
01276 { return (m_buffer[0] == '\0'); }
01281 inline bool IsNotEmpty(void) const
01282 { return (m_buffer[0] != '\0'); }
01283 protected:
01294 inline bool isValidIndex(uint32 udx) const
01295 { return (udx < MAX_LEN); }
01305 inline bool validPtr(StringPtr pstr) const
01306 { return (GOOD_PTR(pstr) && pstr != m_buffer); }
01307
01308
01309
01310
01311 public:
01312 bool operator == (StringPtr pstr) const
01313 { return (Compare(pstr, true) == 0); }
01314 bool operator != (StringPtr pstr) const
01315 { return (Compare(pstr, true) != 0); }
01316
01317 bool operator <= (StringPtr pstr) const
01318 { return (Compare(pstr, true) <= 0); }
01319 bool operator < (StringPtr pstr) const
01320 { return (Compare(pstr, true) < 0); }
01321 bool operator >= (StringPtr pstr) const
01322 { return (Compare(pstr, true) >= 0); }
01323 bool operator > (StringPtr pstr) const
01324 { return (Compare(pstr, true) > 0); }
01325
01326 operator StringPtr() const
01327 { return GetString(); }
01328
01329 Text operator [] (int index) const
01330 { return GetAt(index); }
01331
01332 HStr & operator = (HStr const & rhs)
01333 { assign(rhs.m_buffer); return *this; }
01334 HStr & operator = (StringPtr pstr)
01335 { assign(pstr); return *this;}
01336 HStr & operator += (HStr const & rhs)
01337 { Append(rhs.m_buffer); return *this;}
01338 HStr & operator +=(StringPtr pstr)
01339 { Append(pstr); return *this;}
01340 HStr operator + (HStr const & rhs) const
01341 {
01342 HStr<MAX_LEN> str(m_buffer);
01343 str.Append(rhs.m_buffer);
01344 return str;
01345 }
01346 HStr operator + (StringPtr pstr) const
01347 {
01348 HStr<MAX_LEN> str(m_buffer);
01349 str.Append(pstr);
01350 return str;
01351 }
01352 };
01360 typedef HStr<255> HStrTmp;
01361
01362 #endif // HSTRING_H
01363
01364
01365
01366
01367
01368
01369
01370
01371
01372
01373
01374
01375
01376
01377
01378
01379
01380
01381
01382
01383
01384
01385
01386
01387
01388
01389
01390
01391
01392
01393
01394
01395
01396
01397
01398
01399
01400