Advertisement
amgineyoc

AString.cpp

Oct 13th, 2014
211
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C++ 25.16 KB | None | 0 0
  1. #include "AString.h"
  2. #include <cstring>
  3. #include <stdarg.h>
  4. #include <stdio.h>
  5.  
  6. //#define ASTRING_DEBUG_TRACE_ENABLE
  7. #ifdef ASTRING_DEBUG_TRACE_ENABLE
  8. #define ASTRING_DEBUG_TRACE(a,b) std::cout<<"ASTRING DEBUG :"<<a<<b<<std::endl
  9. #else
  10. #define ASTRING_DEBUG_TRACE(a,b)
  11. #endif
  12. #if ASTRING_IMPLEMENT_WITH_STD_STRING
  13. #define ASTRING_IMPLEMENT_WITH_STD_STRING_CODE(x) x
  14. #else
  15. #define ASTRING_IMPLEMENT_WITH_STD_STRING_CODE(x)
  16. #endif
  17.  
  18.  
  19. #if ! ASTRING_IMPLEMENT_WITH_STD_STRING
  20. const char AString::EmptyBuffer[4] = { 0, 0, 0, 0 };
  21. const size_t AString::npos = (size_t)-1;
  22. #endif
  23.  
  24. //-------------------------------------------------------------
  25. AString::AString()
  26. ASTRING_IMPLEMENT_WITH_STD_STRING_CODE(:std::string())
  27. {
  28.     ASTRING_DEBUG_TRACE("construct empty", "");
  29. #if ! ASTRING_IMPLEMENT_WITH_STD_STRING
  30.     StrBuffer = (char*)&EmptyBuffer;
  31. #endif
  32. }
  33. //-------------------------------------------------------------
  34. AString::~AString() ASTRING_NOEXCEPT
  35. {
  36.     ASTRING_DEBUG_TRACE("destroy ", c_str());
  37. #if ! ASTRING_IMPLEMENT_WITH_STD_STRING
  38.     if (StrBuffer != EmptyBuffer)
  39.         delete[] GetRawBuffer();
  40. #endif
  41. }
  42. //-------------------------------------------------------------
  43. AString::AString(const char *str, int count/*=-1*/)
  44. ASTRING_IMPLEMENT_WITH_STD_STRING_CODE(:std::string(str, (count)<0 ? strlen(str) : count))
  45. {
  46.     ASTRING_DEBUG_TRACE("construct char* ", str);
  47. #if ! ASTRING_IMPLEMENT_WITH_STD_STRING
  48.     size_t len;
  49.     if (count >= 0)
  50.         len = count;
  51.     else
  52.         len = strlen(str);
  53.     if (len>0)
  54.     {
  55.         AllocBuffer((unsigned)len);
  56.         memcpy(StrBuffer, str, len);
  57.         StrBuffer[len] = 0;
  58.         GetSize() = (unsigned)strlen(StrBuffer); // in case str contains a \0
  59.     }
  60.     else
  61.         StrBuffer = (char*)&EmptyBuffer;
  62. #endif
  63. }
  64. //-------------------------------------------------------------
  65. AString::AString(int value)
  66. ASTRING_IMPLEMENT_WITH_STD_STRING_CODE(:std::string())
  67. {
  68.     // Todo reimplement it without std::stringstream
  69.     // Todo support multiple base
  70.     ASTRING_DEBUG_TRACE("construct int ", value);
  71. #if ! ASTRING_IMPLEMENT_WITH_STD_STRING
  72.     StrBuffer = (char*)&EmptyBuffer;
  73. #endif
  74.     /*std::stringstream ss;
  75.     ss << value;
  76.     assign(ss.str().c_str());*/
  77.     Format("%d", value);
  78. }
  79. //-------------------------------------------------------------
  80. AString::AString(unsigned value)
  81. ASTRING_IMPLEMENT_WITH_STD_STRING_CODE(:std::string())
  82. {
  83.     // Todo reimplement it without std::stringstream
  84.     // Todo support multiple base
  85.     ASTRING_DEBUG_TRACE("construct unsigned ", value);
  86. #if ! ASTRING_IMPLEMENT_WITH_STD_STRING
  87.     StrBuffer = (char*)&EmptyBuffer;
  88. #endif
  89.     /*std::stringstream ss;
  90.     ss << value;
  91.     assign(ss.str().c_str());*/
  92.     Format("%u", value);
  93. }
  94. /*AString::AString(float value)
  95. {
  96. // Todo reimplement it without std::stringstream
  97. ASTRING_DEBUG_TRACE("construct float ",value);
  98. #if ! ASTRING_IMPLEMENT_WITH_STD_STRING
  99. StrBuffer=(char*)&EmptyBuffer;
  100. #endif
  101.  
  102. Format("%f",value);
  103. }*/
  104. AString::AString(double value)
  105. ASTRING_IMPLEMENT_WITH_STD_STRING_CODE(:std::string())
  106. {
  107.     ASTRING_DEBUG_TRACE("construct double ", value);
  108. #if ! ASTRING_IMPLEMENT_WITH_STD_STRING
  109.     StrBuffer = (char*)&EmptyBuffer;
  110. #endif
  111.     /*std::stringstream ss;
  112.     ss << value;
  113.     assign(ss.str().c_str());       */
  114. #if __MINGW32__ || _MSC_VER
  115.     Format("%f", value);
  116. #else
  117.     Format("%lf", value);
  118. #endif
  119.     // Trim right 0 and . but keep at least one char
  120.     for (unsigned i = (unsigned)size() - 1; i>0; i--)
  121.         if ((at(i) == '0') || (at(i) == '.'))
  122.             at(i) = 0;
  123.         else
  124.             break;
  125.     RecomputeSize();
  126.  
  127. }
  128. //-------------------------------------------------------------
  129. AString::AString(const AString &Src)
  130. ASTRING_IMPLEMENT_WITH_STD_STRING_CODE(:std::string(Src))
  131. {
  132.     ASTRING_DEBUG_TRACE("construct copy ", Src.c_str());
  133. #if ! ASTRING_IMPLEMENT_WITH_STD_STRING
  134.     unsigned len = (unsigned)Src.size();
  135.     if (len>0)
  136.     {
  137.         AllocBuffer(len);
  138.         GetSize() = len;
  139.         memcpy(StrBuffer, Src.StrBuffer, len);
  140.         StrBuffer[len] = 0;
  141.     }
  142.     else
  143.         StrBuffer = (char*)&EmptyBuffer;
  144. #endif
  145. }
  146.  
  147. #if ASTRING_INTEROP_BCB
  148. AString::AString(const AnsiString &Src)
  149. ASTRING_IMPLEMENT_WITH_STD_STRING_CODE(:std::string(Src.c_str()))
  150. {
  151.     ASTRING_DEBUG_TRACE("construct AnsiString ", Src.c_str());
  152. #if ! ASTRING_IMPLEMENT_WITH_STD_STRING
  153.     unsigned len = (unsigned)Src.Length();
  154.     if (len>0)
  155.     {
  156.         AllocBuffer(len);
  157.         GetSize() = len;
  158.         memcpy(StrBuffer, Src.c_str(), len);
  159.         StrBuffer[len] = 0;
  160.     }
  161.     else
  162.         StrBuffer = (char*)&EmptyBuffer;
  163. #endif
  164. }
  165. AString::AString(const UnicodeString &Src)
  166. ASTRING_IMPLEMENT_WITH_STD_STRING_CODE(:std::string(AnsiString(Src).c_str()))
  167. {
  168.     ASTRING_DEBUG_TRACE("construct AnsiString ", Src.c_str());
  169. #if ! ASTRING_IMPLEMENT_WITH_STD_STRING
  170.     AnsiString AS(Src); // Convert to Ansi
  171.     unsigned len = (unsigned)AS.Length();
  172.     if (len>0)
  173.     {
  174.         AllocBuffer(len);
  175.         GetSize() = len;
  176.         memcpy(StrBuffer, AS.c_str(), len);
  177.         StrBuffer[len] = 0;
  178.     }
  179.     else
  180.         StrBuffer = (char*)&EmptyBuffer;
  181. #endif
  182. }
  183. AString::operator AnsiString ()
  184. {
  185.     return AnsiString(c_str());
  186. }
  187. AString::operator UnicodeString ()
  188. {
  189.     return UnicodeString(c_str());
  190. }
  191.  
  192. #endif   //ASTRING_INTEROP_BCB
  193.  
  194. #if ASTRING_INTEROP_VSS
  195. AString::AString(CStringA &Src)
  196. ASTRING_IMPLEMENT_WITH_STD_STRING_CODE(:std::string(Src.GetBuffer(0)))
  197. {
  198.     //      ASTRING_DEBUG_TRACE("construct CStringA ",Src.c_str());
  199. #if ! ASTRING_IMPLEMENT_WITH_STD_STRING
  200.     unsigned len = (unsigned)Src.GetLength();
  201.     if (len>0)
  202.     {
  203.         AllocBuffer(len);
  204.         GetSize() = len;
  205.         memcpy(StrBuffer, Src.GetBuffer(0), len);
  206.         StrBuffer[len] = 0;
  207.     }
  208.     else
  209.         StrBuffer = (char*)&EmptyBuffer;
  210. #endif
  211. }
  212. AString::operator CStringA ()
  213. {
  214.     return CStringA(c_str());
  215. }
  216.  
  217. AString::AString(CStringW &Src)
  218. ASTRING_IMPLEMENT_WITH_STD_STRING_CODE(:std::string(CStringA(Src).GetBuffer(0)))
  219. {
  220.     //      ASTRING_DEBUG_TRACE("construct CStringW ",Src.c_str());
  221. #if ! ASTRING_IMPLEMENT_WITH_STD_STRING
  222.     CStringA Cs(Src);
  223.     unsigned len = (unsigned)Cs.GetLength();
  224.     if (len>0)
  225.     {
  226.         AllocBuffer(len);
  227.         GetSize() = len;
  228.         memcpy(StrBuffer, Cs.GetBuffer(0), len);
  229.         StrBuffer[len] = 0;
  230.     }
  231.     else
  232.         StrBuffer = (char*)&EmptyBuffer;
  233. #endif
  234. }
  235. AString::operator CStringW ()
  236. {
  237.     return CStringW(CStringA(c_str()));
  238. }
  239. #endif // ASTRING_INTEROP_VSS
  240.  
  241.  
  242. //-------------------------------------------------------------
  243. #if ASTRING_INTEROP_STD_STRING
  244. AString::AString(const std::string &Src)
  245. ASTRING_IMPLEMENT_WITH_STD_STRING_CODE(:std::string(Src))
  246. {
  247.     ASTRING_DEBUG_TRACE("construct string copy ", Src.c_str());
  248. #if ! ASTRING_IMPLEMENT_WITH_STD_STRING
  249.     unsigned len = (unsigned)Src.size();
  250.     if (len>0)
  251.     {
  252.         AllocBuffer(len);
  253.         GetSize() = len;
  254.         memcpy(StrBuffer, Src.c_str(), len);
  255.         StrBuffer[len] = 0;
  256.     }
  257.     else
  258.         StrBuffer = (char*)&EmptyBuffer;
  259. #endif
  260. }
  261. AString::operator std::string() const
  262. {
  263. #if  ASTRING_IMPLEMENT_WITH_STD_STRING
  264.     return *this;
  265. #else
  266.     std::string s(c_str());
  267.     return s;
  268. #endif
  269. }
  270.  
  271. #endif
  272. //-------------------------------------------------------------
  273. AString& AString::operator =(const AString& Src)
  274. {
  275.     ASTRING_DEBUG_TRACE("operator = AString ", Src.c_str());
  276. #if ! ASTRING_IMPLEMENT_WITH_STD_STRING
  277.     if (StrBuffer != ((char*)&EmptyBuffer))
  278.         delete[] GetRawBuffer();
  279.     unsigned len = (unsigned)Src.size();
  280.     if (len>0)
  281.     {
  282.         AllocBuffer(len);
  283.         GetSize() = len;
  284.         memcpy(StrBuffer, Src.StrBuffer, len);
  285.         StrBuffer[len] = 0;
  286.     }
  287.     else
  288.         StrBuffer = (char*)&EmptyBuffer;
  289. #else
  290.     assign(Src);
  291. #endif
  292.     return *this;
  293. }
  294. #if ! ASTRING_IMPLEMENT_WITH_STD_STRING
  295. //-------------------------------------------------------------
  296. AString& AString::assign(const char *str, int count/*=-1*/)
  297. {
  298.     ASTRING_DEBUG_TRACE("assign char* ", str);
  299.     unsigned len;
  300.     if (count >= 0)
  301.         len = count;
  302.     else
  303.         len = (unsigned)strlen(str);
  304.     clear();
  305.     if (len>0)
  306.     {
  307.         AllocBuffer(len);
  308.         GetSize() = len;
  309.         memcpy(StrBuffer, str, len);
  310.         StrBuffer[len] = 0;
  311.     }
  312.     else
  313.         StrBuffer = (char*)&EmptyBuffer;
  314.     return *this;
  315. }
  316. //-------------------------------------------------------------
  317. char* AString::c_str()
  318. {
  319.     return StrBuffer;
  320. }
  321. //-------------------------------------------------------------
  322. const char* AString::c_str() const
  323. {
  324.     return StrBuffer;
  325. }
  326. //-------------------------------------------------------------
  327. size_t AString::size() const
  328. {
  329.     if (StrBuffer == ((char*)&EmptyBuffer))
  330.         return 0;
  331.     else
  332.         return GetSize();
  333. }
  334. //-------------------------------------------------------------
  335. size_t AString::capacity() const
  336. {
  337.     if (StrBuffer == ((char*)&EmptyBuffer))
  338.         return 0;
  339.     else
  340.         return GetCapacity();
  341. }
  342. //-------------------------------------------------------------
  343. char* AString::GetRawBuffer()
  344. {
  345.     if (StrBuffer == ((char*)&EmptyBuffer))
  346.         return NULL;
  347.     else
  348.         return StrBuffer - 2 * sizeof(unsigned);
  349. }
  350. //-------------------------------------------------------------
  351. void AString::clear()
  352. {
  353.     ASTRING_DEBUG_TRACE("clear ", "");
  354.     if (StrBuffer != EmptyBuffer)
  355.     {
  356.         delete[] GetRawBuffer();
  357.         StrBuffer = (char*)EmptyBuffer;
  358.     }
  359. }
  360. //-------------------------------------------------------------
  361. void AString::reserve(size_t count)
  362. {
  363.     ASTRING_DEBUG_TRACE("reserve ", count);
  364.     char *PrevStr = c_str();
  365.     unsigned PrevLen = (unsigned)size();
  366.     char *PrevBuffer = GetRawBuffer();
  367.     if (PrevLen>(unsigned)count)
  368.         count = (size_t)PrevLen; // Reserve can't be smaller than current size
  369.     AllocBuffer((unsigned)count);
  370.     if (count)
  371.     {
  372.         GetSize() = (unsigned)count;
  373.         memcpy(StrBuffer, PrevStr, PrevLen);
  374.         StrBuffer[PrevLen] = 0;
  375.         GetSize() = PrevLen;
  376.     }
  377.     if ((PrevBuffer) && (PrevBuffer != EmptyBuffer))
  378.         delete[]PrevBuffer;
  379.  
  380.  
  381. }
  382. //-------------------------------------------------------------
  383. void AString::AllocBuffer(unsigned count)
  384. {
  385.     ASTRING_DEBUG_TRACE("Alloc buffer ", count);
  386.  
  387.     if (count>0)
  388.     {
  389.         count |= 7; // round up to 8 bytes (with the +1 of the next line)
  390.         StrBuffer = new char[count + 1 + 2 * sizeof(unsigned)];
  391.         StrBuffer += 2 * sizeof(unsigned);
  392.         GetSize() = 0;
  393.         GetCapacity() = count;
  394.         StrBuffer[0] = 0;
  395.     }
  396.     else
  397.         StrBuffer = (char*)&EmptyBuffer;
  398. }
  399. //-------------------------------------------------------------
  400. char& AString::operator[](size_t idx)
  401. {
  402.     if (idx>size())
  403.         throw AStringException("Invalid index");
  404.     return StrBuffer[idx];
  405. }
  406. //-------------------------------------------------------------
  407. char AString::operator[](size_t idx) const
  408. {
  409.     if (idx>size())
  410.         throw AStringException("Invalid index");
  411.     return StrBuffer[idx];
  412. }
  413. //-------------------------------------------------------------
  414. char& AString::at(size_t idx)
  415. {
  416.     if (idx>size())
  417.         throw AStringException("Invalid index");
  418.     return StrBuffer[idx];
  419. }
  420. //-------------------------------------------------------------
  421. char AString::at(size_t idx) const
  422. {
  423.     if (idx>size())
  424.         throw AStringException("Invalid index");
  425.     return StrBuffer[idx];
  426. }
  427.  
  428. //-------------------------------------------------------------
  429. unsigned& AString::GetSize()
  430. {
  431.     return *((unsigned*)(StrBuffer - 2 * sizeof(unsigned)));
  432. }
  433. //-------------------------------------------------------------
  434. unsigned& AString::GetCapacity()
  435. {
  436.     return *((unsigned*)(StrBuffer - sizeof(unsigned)));
  437. }
  438. //-------------------------------------------------------------
  439. unsigned AString::GetSize() const
  440. {
  441.     return *((unsigned*)(StrBuffer - 2 * sizeof(unsigned)));
  442. }
  443. //-------------------------------------------------------------
  444. unsigned AString::GetCapacity() const
  445. {
  446.     return *((unsigned*)(StrBuffer - sizeof(unsigned)));
  447. }
  448. //-------------------------------------------------------------
  449. AString AString::operator +(const AString &RightStr) const
  450. {
  451.     AString res;
  452.     unsigned LLen = (unsigned)size();
  453.     unsigned RLen = (unsigned)RightStr.size();
  454.     res.reserve(LLen + RLen);
  455.     res.GetSize() = LLen + RLen;
  456.     if (LLen)
  457.         memcpy(res.StrBuffer, StrBuffer, LLen);
  458.     if (RLen)
  459.         memcpy(&res.StrBuffer[LLen], RightStr.StrBuffer, RLen);
  460.     res.StrBuffer[res.GetSize()] = 0;
  461.     return res;
  462. }
  463. //-------------------------------------------------------------
  464. AString AString::operator +(const char* RightStr) const
  465. {
  466.     AString res;
  467.     unsigned LLen = (unsigned)size();
  468.     unsigned RLen = (unsigned)strlen(RightStr);
  469.     res.reserve(LLen + RLen);
  470.     res.GetSize() = LLen + RLen;
  471.     if (LLen)
  472.         memcpy(res.StrBuffer, StrBuffer, LLen);
  473.     if (RLen)
  474.         memcpy(&res.StrBuffer[LLen], RightStr, RLen);
  475.     res.StrBuffer[res.GetSize()] = 0;
  476.     return res;
  477. }
  478. //-------------------------------------------------------------
  479. AString operator +(const char *LeftStr, const AString &RightStr)
  480. {
  481.     AString res;
  482.     unsigned LLen = (unsigned)strlen(LeftStr);
  483.     unsigned RLen = (unsigned)RightStr.size();
  484.     res.reserve(LLen + RLen);
  485.     res.GetSize() = LLen + RLen;
  486.     if (LLen)
  487.         memcpy(res.StrBuffer, LeftStr, LLen);
  488.     if (RLen)
  489.         memcpy(&res.StrBuffer[LLen], RightStr.StrBuffer, RLen);
  490.     res.StrBuffer[res.GetSize()] = 0;
  491.     return res;
  492. }
  493. //-------------------------------------------------------------
  494. AString& AString::operator +=(const AString &RightStr)
  495. {
  496.     unsigned RLen = (unsigned)RightStr.size();
  497.     unsigned FinalLength = (unsigned)size() + RLen;
  498.     if (FinalLength>capacity())
  499.         reserve(FinalLength);
  500.     if (RLen)
  501.         memcpy(&StrBuffer[size()], RightStr.StrBuffer, RLen);
  502.     GetSize() = FinalLength;
  503.     StrBuffer[FinalLength] = 0;
  504.     return *this;
  505. }
  506. //-------------------------------------------------------------
  507. bool AString::operator ==(const AString &RightStr) const
  508. {
  509.     unsigned RLen = (unsigned)RightStr.size();
  510.     if (RLen != size())
  511.         return false;
  512.     char *sL = StrBuffer;
  513.     char *sR = RightStr.StrBuffer;
  514.     while (*sL)
  515.     {
  516.         if (*sL != *sR)
  517.             return false;
  518.         ++sL; // Go to next char
  519.         ++sR;
  520.     }
  521.     return true;
  522. }
  523. //-------------------------------------------------------------
  524. bool AString::operator ==(const char* RightStr) const
  525. {
  526.     char *sL = StrBuffer;
  527.     const char *sR = RightStr;
  528.     while (*sL)
  529.     {
  530.         if (*sL != *sR)
  531.             return false;
  532.         ++sL; // Go to next char
  533.         ++sR;
  534.     }
  535.     if (*sL != *sR)
  536.         return false;
  537.     return true;
  538. }
  539. //-------------------------------------------------------------
  540. bool operator ==(const char *LeftStr, const AString &RightStr)
  541. {
  542.     return RightStr == LeftStr;
  543. }
  544. //-------------------------------------------------------------
  545. bool AString::operator <(const AString &RightStr) const
  546. {
  547.     char *sL = StrBuffer;
  548.     char *sR = RightStr.StrBuffer;
  549.     while (*sL)
  550.     {
  551.         if (*sL<*sR)
  552.             return true;
  553.         if (*sL>*sR)
  554.             return false;
  555.         ++sL; // Go to next char
  556.         ++sR;
  557.     }
  558.     if (*sR) // Right string have more char, if begining equal it's longer
  559.         return true;
  560.     return false;
  561. }
  562. //-------------------------------------------------------------
  563. bool AString::operator >(const AString &RightStr) const
  564. {
  565.     char *sL = StrBuffer;
  566.     char *sR = RightStr.StrBuffer;
  567.     while (*sL)
  568.     {
  569.         if (*sL>*sR)
  570.             return true;
  571.         if (*sL<*sR)
  572.             return false;
  573.         ++sL; // Go to next char
  574.         ++sR;
  575.     }
  576.     return false;
  577. }
  578. //-------------------------------------------------------------
  579. bool AString::operator <(const char *RightStr) const
  580. {
  581.     char *sL = StrBuffer;
  582.     const char *sR = RightStr;
  583.     while (*sL)
  584.     {
  585.         if (*sL<*sR)
  586.             return true;
  587.         if (*sL>*sR)
  588.             return false;
  589.         ++sL; // Go to next char
  590.         ++sR;
  591.     }
  592.     if (*sR) // Right string have more char, if begining equal it's longer
  593.         return true;
  594.     return false;
  595. }
  596. //-------------------------------------------------------------
  597. bool AString::operator >(const char *RightStr) const
  598. {
  599.     char *sL = StrBuffer;
  600.     const char *sR = RightStr;
  601.     while (*sL)
  602.     {
  603.         if (*sL>*sR)
  604.             return true;
  605.         if (*sL<*sR)
  606.             return false;
  607.         ++sL; // Go to next char
  608.         ++sR;
  609.     }
  610.     return false;
  611. }
  612. //-------------------------------------------------------------
  613. bool operator <(const char *LeftStr, const AString &RightStr)
  614. {
  615.     const char *sL = LeftStr;
  616.     char *sR = RightStr.StrBuffer;
  617.     while (*sL)
  618.     {
  619.         if (*sL<*sR)
  620.             return true;
  621.         if (*sL>*sR)
  622.             return false;
  623.         ++sL; // Go to next char
  624.         ++sR;
  625.     }
  626.     if (*sR) // Right string have more char, if begining equal it's longer
  627.         return true;
  628.     return false;
  629. }
  630. //-------------------------------------------------------------
  631. bool operator >(const char *LeftStr, const AString &RightStr)
  632. {
  633.     const char *sL = LeftStr;
  634.     char *sR = RightStr.StrBuffer;
  635.     while (*sL)
  636.     {
  637.         if (*sL>*sR)
  638.             return true;
  639.         if (*sL<*sR)
  640.             return false;
  641.         ++sL; // Go to next char
  642.         ++sR;
  643.     }
  644.     return false;
  645. }
  646.  
  647. //-------------------------------------------------------------
  648. bool AString::operator !=(const AString &RightStr) const
  649. {
  650.     return !(*this == RightStr);
  651. }
  652. //-------------------------------------------------------------
  653. bool AString::operator !=(const char* RightStr) const
  654. {
  655.     return !(*this == RightStr);
  656. }
  657. bool operator !=(const char *LeftStr, const AString &RightStr)
  658. {
  659.     return !(RightStr == LeftStr);
  660. }
  661. //-------------------------------------------------------------
  662. AString AString::substr(size_t pos /*= 0*/, size_t count /*= npos*/) const
  663. {
  664.     if (pos>size())
  665.         throw AStringException("substr:Invalid position");
  666.     if ((count != npos) && ((count>size()) || ((pos + count)>size())))
  667.         count = size() - pos;
  668.     return  AString(&StrBuffer[pos], (int)count);
  669. }
  670. //-------------------------------------------------------------
  671. size_t AString::find(const char* Searched, size_t StartPos/*=0*/, size_t count/*=0*/) const
  672. {
  673.     if (count == 0)
  674.         count = (unsigned)strlen(Searched);
  675.     if (StartPos>size())
  676.         return npos;
  677.     if (count>size())
  678.         return npos;
  679.     char *Source = StrBuffer + StartPos;
  680.     while (*Source)
  681.     {
  682.         unsigned c = 0;
  683.         while (c<count)
  684.         {
  685.             if (Source[c] != Searched[c])
  686.                 break;
  687.             c++;
  688.         }
  689.         if (c == count)
  690.             return (unsigned)(Source - StrBuffer);
  691.         Source++;
  692.     }
  693.     return npos;
  694. }
  695. //-------------------------------------------------------------
  696. size_t AString::find(char Searched, size_t StartPos/*=0*/) const
  697. {
  698.     return find(&Searched, StartPos, 1);
  699. }
  700. //-------------------------------------------------------------
  701. AString::iterator AString::begin()
  702. {
  703.     return c_str();
  704. }
  705. //-------------------------------------------------------------
  706. AString::iterator AString::end()
  707. {
  708.     return c_str() + size();
  709. }
  710. #endif
  711. //-------------------------------------------------------------
  712. #if !ASTRING_NOSTL
  713. std::ostream& operator<<(std::ostream& os, const AString& str)
  714. {
  715.     os << str.c_str();
  716.     return os;
  717. }
  718. #endif
  719.  
  720. //-------------------------------------------------------------
  721. AString& AString::replace(size_t pos, size_t count, const AString& str)
  722. {
  723. #if ASTRING_IMPLEMENT_WITH_STD_STRING
  724.     std::string::replace(pos, count, str);
  725.     return *this;
  726. #else
  727.     if ((pos + count)>size())
  728.         throw AStringException("replace:pos+count > size");
  729.     size_t NewStringSize = str.size();
  730.     if (count == NewStringSize)
  731.     {// Replace by same size is simple and quick
  732.         for (size_t i = 0; i<count; i++)
  733.             at(pos + i) = str[i];
  734.     }
  735.     else if (count>NewStringSize)
  736.     {  // replace by smaller string
  737.         for (size_t i = 0; i<NewStringSize; i++)
  738.             at(pos + i) = str[i];
  739.         size_t Remaining = size() - (pos + count);
  740.         for (size_t i = 0; i <= Remaining; i++) // <= to copy also the zero
  741.             at(pos + NewStringSize + i) = at(pos + count + i);
  742.         GetSize() = static_cast<unsigned int>(pos + NewStringSize + Remaining);
  743.     }
  744.     else
  745.     {  // replace by bigger string
  746.         // Save the end of the string
  747.         AString EndOfString = substr(pos + count);
  748.         GetSize() = static_cast<unsigned int>(pos);
  749.         if (capacity()<(GetSize() + str.size() + EndOfString.size()))
  750.             reserve(GetSize() + str.size() + EndOfString.size());
  751.         (*this) += str;
  752.         (*this) += EndOfString;
  753.     }
  754.     return *this;
  755. #endif
  756. }
  757. //-------------------------------------------------------------
  758. AString& AString::replace(const AString& src, const AString& str)
  759. {
  760.     size_t startpos = 0;
  761.     while (1)
  762.     {
  763.         size_t  pos = find(src.c_str(), startpos, src.size());
  764.         if (pos == npos)
  765.             return *this;
  766.         replace(pos, src.size(), str);
  767.         startpos = pos + str.size();
  768.     }
  769. }
  770. //-------------------------------------------------------------
  771. AString& AString::rtrim(const char *CharsToRemove)
  772. {
  773.     unsigned CharToRemoveSize = static_cast<unsigned int>(strlen(CharsToRemove));
  774.     if (size() == 0)
  775.         return *this;
  776.     size_t pos = size();
  777.     size_t count = 0; // Count of char to remove
  778.     do{
  779.         pos--;
  780.         bool CharRemoved = false;
  781.         for (unsigned i = 0; i<CharToRemoveSize; i++)
  782.             if ((*this)[pos] == CharsToRemove[i])
  783.             {
  784.             CharRemoved = true;
  785.             count++;
  786.             break;
  787.             }
  788.         if (CharRemoved == false)
  789.             break;
  790.     } while (pos);
  791.     if (count>0)
  792.     {
  793. #if ASTRING_IMPLEMENT_WITH_STD_STRING
  794.         resize(size() - count);
  795. #else
  796.         (*this)[size() - count] = 0;
  797.         RecomputeSize();
  798. #endif
  799.     }
  800.     return *this;
  801. }
  802. //-------------------------------------------------------------
  803. AString& AString::ltrim(const char *CharsToRemove)
  804. {
  805.     unsigned CharToRemoveSize = static_cast<unsigned int>(strlen(CharsToRemove));
  806.     if (size() == 0)
  807.         return *this;
  808.     size_t pos = 0;
  809.     size_t count = 0; // Count of char to remove
  810.     do{
  811.         bool CharRemoved = false;
  812.         for (unsigned i = 0; i<CharToRemoveSize; i++)
  813.             if ((*this)[pos] == CharsToRemove[i])
  814.             {
  815.             CharRemoved = true;
  816.             count++;
  817.             break;
  818.             }
  819.         if (CharRemoved == false)
  820.             break;
  821.         pos++;
  822.     } while (pos<size());
  823.     if (count>0)
  824.     {
  825. #if ASTRING_IMPLEMENT_WITH_STD_STRING
  826.         assign(substr(count));
  827. #else
  828.         char* destptr = StrBuffer;
  829.         do{
  830.             *destptr = destptr[pos];
  831.             destptr++;
  832.         } while (*(destptr - 1));
  833.         RecomputeSize();
  834. #endif
  835.     }
  836.     return *this;
  837. }
  838. //-------------------------------------------------------------
  839. AString& AString::trim(const char *CharsToRemove)
  840. {
  841.     rtrim(CharsToRemove);
  842.     ltrim(CharsToRemove);
  843.     return *this;
  844. }
  845. //-------------------------------------------------------------
  846. void AString::strncpy(char* dest, size_t destsize, unsigned pos /*= 0*/) const
  847. {
  848.     if (pos>size())
  849.         throw AStringException("Invalid position");
  850.     if (destsize<1)
  851.         throw AStringException("Invalid destination size should be >0");
  852.     destsize--; // zero based and/or final 0
  853.     if ((destsize>size()) || ((pos + destsize)>size()))
  854.         destsize = size() - pos;
  855.     memcpy(dest, &c_str()[pos], destsize);
  856.     dest[destsize] = 0;
  857.  
  858. }
  859. //-------------------------------------------------------------
  860. void AString::RecomputeSize()
  861. {
  862.     unsigned NewSize = (unsigned)strlen(c_str());
  863.     if (NewSize == size())
  864.         return;
  865. #if ASTRING_IMPLEMENT_WITH_STD_STRING
  866.     resize(NewSize);
  867. #else
  868.     GetSize() = NewSize;
  869. #endif
  870. }
  871. //-------------------------------------------------------------
  872. int AString::ToInt()
  873. {
  874.     int x;
  875. #ifdef _MSC_VER
  876.     if (sscanf_s(c_str(), "%d", &x) <= 0)
  877. #else
  878.     if (sscanf(c_str(), "%d", &x) <= 0)
  879. #endif
  880.         throw AStringException(Asprintf("ToInt %s is not an integer ", c_str()));
  881.     return x;
  882. }
  883. //-------------------------------------------------------------
  884. int AString::ToIntDef(int defval)
  885. {
  886.     int x;
  887. #ifdef _MSC_VER
  888.     if (sscanf_s(c_str(), "%d", &x) <= 0)
  889. #else
  890.     if (sscanf(c_str(), "%d", &x) <= 0)
  891. #endif
  892.         return defval;
  893.     return x;
  894. }
  895. //-------------------------------------------------------------
  896. #if __cplusplus > 199711L // C++ 11
  897. //-------------------------------------------------------------
  898. AString::AString(AString &&Src) ASTRING_NOEXCEPT
  899. ASTRING_IMPLEMENT_WITH_STD_STRING_CODE(:std::string(Src))
  900. {
  901.     ASTRING_DEBUG_TRACE("Move constructor ", Src.c_str());
  902. #if ! ASTRING_IMPLEMENT_WITH_STD_STRING
  903.     StrBuffer = Src.StrBuffer;
  904.     Src.StrBuffer = (char*)&EmptyBuffer;
  905. #endif
  906. }
  907. //-------------------------------------------------------------
  908. AString& AString::operator =(AString&& Src) ASTRING_NOEXCEPT
  909. {
  910.     ASTRING_DEBUG_TRACE("Move operator = ", Src.c_str());
  911. #if ! ASTRING_IMPLEMENT_WITH_STD_STRING
  912.     if (StrBuffer != ((char*)&EmptyBuffer))
  913.         delete[] GetRawBuffer();
  914.     StrBuffer = Src.StrBuffer;
  915.     Src.StrBuffer = (char*)&EmptyBuffer;
  916.     return *this;
  917. #else
  918.     return this->operator =(Src);
  919. #endif
  920. }
  921. #endif // C++ 11
  922.  
  923. //-------------------------------------------------------------
  924. AString Asprintf(const char *Fmt, ...)
  925. {
  926.     int needed;
  927.     char* TempBuffer;
  928.     AString ret;
  929. #ifdef _MSC_VER
  930.     va_list argptr;
  931.     va_start(argptr, Fmt);
  932.     needed = _vscprintf(Fmt, argptr);
  933. #else
  934.     char Temp[4];
  935.     va_list argptr;
  936.     va_start(argptr, Fmt);
  937.     needed = vsnprintf(Temp, 0, Fmt, argptr);
  938. #endif
  939.     va_end(argptr);
  940.  
  941. #if ASTRING_IMPLEMENT_WITH_STD_STRING
  942.     TempBuffer = new char[needed + 1];
  943. #else
  944.     ret.reserve(needed);
  945.     TempBuffer = ret.c_str();
  946.     ret.GetSize() = needed;
  947. #endif
  948.     va_start(argptr, Fmt);
  949. #ifdef _MSC_VER
  950.     vsnprintf_s(TempBuffer, needed + 1, _TRUNCATE, Fmt, argptr);
  951. #else
  952.     vsnprintf(TempBuffer, needed + 1, Fmt, argptr);
  953.     TempBuffer[needed] = 0;
  954. #endif
  955.     va_end(argptr);
  956. #if ASTRING_IMPLEMENT_WITH_STD_STRING
  957.     ret = TempBuffer;
  958.     delete[] TempBuffer;
  959. #endif
  960.     return ret;
  961. }
  962. //-------------------------------------------------------------
  963. //AString& AString::Format(const AString &Fmt,...)
  964. AString& AString::Format(const char *Fmt, ...)
  965. {
  966.     char* TempBuffer;
  967.     int needed;
  968.     va_list argptr;
  969.     va_start(argptr, Fmt);
  970. #ifdef _MSC_VER
  971.     needed = _vscprintf(Fmt, argptr);
  972. #else
  973.     char Temp[4];
  974.     needed = vsnprintf(Temp, 0, Fmt, argptr);
  975. #endif
  976.     va_end(argptr);
  977. #if ASTRING_IMPLEMENT_WITH_STD_STRING
  978.     TempBuffer = new char[needed + 1];
  979. #else
  980.     reserve(needed);
  981.     TempBuffer = c_str();
  982.     GetSize() = needed;
  983. #endif
  984.     va_start(argptr, Fmt);
  985. #ifdef _MSC_VER
  986.     vsnprintf_s(TempBuffer, needed + 1, _TRUNCATE, Fmt, argptr);
  987. #else
  988.     vsnprintf(TempBuffer, needed + 1, Fmt, argptr);
  989.     TempBuffer[needed] = 0;
  990. #endif
  991.     va_end(argptr);
  992. #if ASTRING_IMPLEMENT_WITH_STD_STRING
  993.     assign(TempBuffer);
  994.     delete[] TempBuffer;
  995. #endif
  996.     return *this;
  997.  
  998. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement