Advertisement
thenuke321

Sstring.hpp

Nov 28th, 2014
77
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C++ 12.01 KB | None | 0 0
  1. /*****************************************************************************
  2. *
  3. *  PROJECT:     Multi Theft Auto v1.0
  4. *  LICENSE:     See LICENSE in the top level directory
  5. *  FILE:        SString.hpp
  6. *  PURPOSE:     SString implementation
  7. *  DEVELOPERS:  ccw <chris@codewave.co.uk>
  8. *               Alberto Alonso <rydencillo@gmail.com>
  9. *
  10. *  Multi Theft Auto is available from http://www.multitheftauto.com/
  11. *
  12. *****************************************************************************/
  13.  
  14.  
  15. //
  16. // Format a string
  17. //
  18. SString& SString::vFormat ( const char* szFormat, va_list vl )
  19. {
  20. #ifdef WIN32
  21.  
  22.     va_list vlLocal;
  23.  
  24.     // Calc size
  25.     va_copy ( vlLocal, vl );
  26.     int iRequiredCapacity;
  27.     __try
  28.     {
  29.         iRequiredCapacity = _vscprintf ( szFormat, vlLocal );
  30.     }
  31.     __except ( EXCEPTION_EXECUTE_HANDLER )
  32.     {
  33.         // Clean up and indicate problem
  34.         OnFormatException( szFormat );
  35.         return *this;
  36.     }
  37.  
  38.     if ( iRequiredCapacity < 1 )
  39.     {
  40.         // Error or empty string
  41.         clear ();
  42.         return *this;
  43.     }
  44.  
  45.     // Allocate buffer
  46.     char* szDest = static_cast < char* > ( malloc ( iRequiredCapacity + 1 ) );
  47.  
  48.     // Try to format the string into the buffer.
  49.     va_copy ( vlLocal, vl );
  50.     int iSize;
  51.     __try
  52.     {
  53.         iSize = vsnprintf ( szDest, iRequiredCapacity, szFormat, vlLocal );
  54.     }
  55.     __except ( EXCEPTION_EXECUTE_HANDLER )
  56.     {
  57.         // Clean up and indicate problem
  58.         free ( szDest );
  59.         OnFormatException( szFormat );
  60.         return *this;
  61.     }
  62.  
  63.     if ( iSize < 1 )
  64.     {
  65.         // Error
  66.         clear ();
  67.     }
  68.     else
  69.     {
  70.         // Copy from buffer
  71.         szDest [ iSize ] = '\0';
  72.         std::string::assign ( szDest );
  73.     }
  74.  
  75.     // Delete buffer
  76.     free ( szDest );
  77.  
  78.     // Done
  79.     return *this;
  80.  
  81. #else
  82.  
  83.     va_list vlLocal;
  84.  
  85.     // Guess size
  86.     int iRequiredCapacity = 220;
  87.  
  88.     // Allocate buffer
  89.     char* szDest = static_cast < char* > ( malloc ( iRequiredCapacity + 1 ) );
  90.  
  91.     // Try to format the string into the buffer. If we will need
  92.     // more capacity it will return -1 in glibc 2.0 and a greater capacity than
  93.     // current in glibc 2.1, so we will resize. Else we've finished.
  94.     va_copy ( vlLocal, vl );
  95.     int iSize = vsnprintf ( szDest, iRequiredCapacity, szFormat, vlLocal );
  96.     if ( iSize == -1 )
  97.     {
  98.         // glibc 2.0 - Returns -1 when it hasn't got enough capacity.
  99.         // Duplicate the buffer size until we get enough capacity
  100.         do
  101.         {
  102.             iRequiredCapacity *= 2;
  103.             szDest = static_cast < char* > ( realloc ( szDest, iRequiredCapacity + 1 ) );
  104.             va_copy ( vlLocal, vl );
  105.             iSize = vsnprintf ( szDest, iRequiredCapacity, szFormat, vlLocal );
  106.         } while ( iSize == -1 );
  107.     }
  108.     else if ( iSize > iRequiredCapacity )
  109.     {
  110.         // glibc 2.1 - Returns the required capacity.
  111.         iRequiredCapacity = iSize + 1;
  112.         szDest = static_cast < char* > ( realloc ( szDest, iRequiredCapacity + 1 ) );
  113.  
  114.         va_copy ( vlLocal, vl );
  115.         iSize = vsnprintf ( szDest, iRequiredCapacity, szFormat, vlLocal );
  116.     }
  117.  
  118.     if ( iSize < 1 )
  119.     {
  120.         // Error or empty string
  121.         clear ();
  122.     }
  123.     else
  124.     {
  125.         // Copy from buffer
  126.         szDest [ iSize ] = '\0';
  127.         std::string::assign ( szDest );
  128.     }
  129.  
  130.     // Delete buffer
  131.     free ( szDest );
  132.  
  133.     // Done
  134.     return *this;
  135. #endif
  136. }
  137.  
  138.  
  139. //
  140. // Handle format exception
  141. //
  142. void SString::OnFormatException ( const char* szFormat )
  143. {
  144.     dassert( 0 );
  145.     // Replace format characters because it seems like a good idea
  146.     *this = ( SStringX( "[Format exception] " ) + szFormat ).Replace( "%", "#" );
  147. }
  148.  
  149.  
  150. //
  151. // Split into parts
  152. //
  153. void SString::Split ( const SString& strDelim, std::vector < SString >& outResult, unsigned int uiMaxAmount, unsigned int uiMinAmount ) const
  154. {
  155.     outResult.clear ();
  156.     size_t ulStartPoint = 0;
  157.  
  158.     while ( true )
  159.     {
  160.         size_t ulPos = find ( strDelim, ulStartPoint );
  161.  
  162.         if ( ulPos == npos || ( uiMaxAmount > 0 && uiMaxAmount <= outResult.size () + 1 ) )
  163.         {
  164.             if ( ulStartPoint <= length () )
  165.                 outResult.push_back ( substr ( ulStartPoint ) );
  166.             break;
  167.         }
  168.  
  169.         outResult.push_back ( substr ( ulStartPoint, ulPos - ulStartPoint ) );
  170.  
  171.         ulStartPoint = ulPos + strDelim.length ();
  172.     }
  173.  
  174.     while ( outResult.size () < uiMinAmount )
  175.         outResult.push_back ( "" );        
  176. }
  177.  
  178. //
  179. // Split in two
  180. //
  181. // eg  "a.b.c.d.e" with strDelim == "." and iIndex == 1  gives "a" and "b.c.d.e"
  182. //     "a.b.c.d.e" with strDelim == "." and iIndex == -2 gives "a.b.c" and "d.e"
  183. //
  184. bool SString::Split ( const SString& strDelim, SString* pstrLeft, SString* pstrRight, int iIndex ) const
  185. {
  186.     // Check for self-overwrite
  187.     if ( this == pstrLeft || this == pstrRight )
  188.         return SString ( *this ).Split ( strDelim, pstrLeft, pstrRight, iIndex );
  189.  
  190.     assert ( iIndex );
  191.     bool bFromEnd = iIndex < 0;
  192.     size_t ulPos;
  193.     if ( !bFromEnd )
  194.     {
  195.         ulPos = 0;
  196.         for ( int i = 0 ; i < iIndex && ulPos != npos ; i++ )
  197.         {
  198.             if ( i )
  199.                 ulPos += strDelim.length ();
  200.             if ( ulPos < length () )
  201.             {
  202.                 ulPos = find ( strDelim, ulPos );
  203.             }
  204.             else
  205.             {
  206.                 ulPos = npos;
  207.                 break;
  208.             }
  209.         }
  210.     }
  211.     else
  212.     {
  213.         ulPos = length ();
  214.         for ( int i = 0 ; i < -iIndex && ulPos != npos ; i++ )
  215.         {
  216.             if ( ulPos >= strDelim.length () )
  217.             {
  218.                 ulPos -= strDelim.length ();
  219.                 ulPos = rfind ( strDelim, ulPos );
  220.             }
  221.             else
  222.             {
  223.                 ulPos = npos;
  224.                 break;
  225.             }
  226.         }
  227.     }
  228.  
  229.     if ( ulPos == npos )
  230.     {
  231.         if ( pstrLeft )
  232.             *pstrLeft = bFromEnd ? "" : c_str ();
  233.         if ( pstrRight )
  234.             *pstrRight = bFromEnd ? c_str () : "";
  235.         return false;
  236.     }
  237.  
  238.     if ( pstrLeft )
  239.         *pstrLeft = substr ( 0, ulPos );
  240.  
  241.     if ( pstrRight )
  242.         *pstrRight = substr ( ulPos + strDelim.length (), length () - ( ulPos + strDelim.length () ) );
  243.  
  244.     return true;
  245. }
  246.  
  247.  
  248. //
  249. // Specialization of Split that returns the left side of the split
  250. //
  251. SString SString::SplitLeft ( const SString& strDelim, SString* pstrRight, int iIndex ) const
  252. {
  253.     SString strLeft;
  254.     Split ( strDelim, &strLeft, pstrRight, iIndex );
  255.     return strLeft;
  256. }
  257.  
  258.  
  259. //
  260. // Specialization of Split that returns the right side of the split
  261. //
  262. SString SString::SplitRight ( const SString& strDelim, SString* pstrLeft, int iIndex ) const
  263. {
  264.     SString strRight;
  265.     Split ( strDelim, pstrLeft, &strRight, iIndex );
  266.     return strRight;
  267. }
  268.  
  269.  
  270. //
  271. // Replace all occurrences of the string szOld with szNew
  272. //
  273. SString SString::Replace ( const char* szOld, const char* szNew, bool bSearchJustReplaced ) const
  274. {
  275.     // Check if anything to replace first
  276.     size_t idx = 0;
  277.     if( ( idx = this->find ( szOld, idx ) ) == npos )
  278.         return *this;
  279.  
  280.     size_t iOldLength = strlen ( szOld );
  281.     size_t iNewLength = strlen ( szNew );
  282.     SString strResult = *this;
  283.     do
  284.     {
  285.         strResult.replace ( idx, iOldLength, szNew );
  286.         if ( !bSearchJustReplaced )
  287.             idx += iNewLength;
  288.     }
  289.     while( ( idx = strResult.find ( szOld, idx ) ) != npos );
  290.     return strResult;
  291. }
  292.  
  293. //
  294. // Case insensitive version of Replace()
  295. //
  296. SString SString::ReplaceI ( const char* szOld, const char* szNew, bool bSearchJustReplaced ) const
  297. {
  298.     SString strOldUpper = SStringX ( szOld ).ToUpper ();
  299.  
  300.     // Check if anything to replace first
  301.     size_t idx = 0;
  302.     if( ( idx = this->ToUpper ().find ( strOldUpper, idx ) ) == npos )
  303.         return *this;
  304.  
  305.     size_t iOldLength = strlen ( szOld );
  306.     size_t iNewLength = strlen ( szNew );
  307.     SString strResult = *this;
  308.     do
  309.     {
  310.         strResult.replace ( idx, iOldLength, szNew );
  311.         if ( !bSearchJustReplaced )
  312.             idx += iNewLength;
  313.     }
  314.     while( ( idx = strResult.ToUpper ().find ( strOldUpper, idx ) ) != npos );
  315.     return strResult;
  316. }
  317.  
  318.  
  319. //
  320. // Remove szOlds from the start of the string.
  321. //
  322. SString SString::TrimStart ( const char* szOld ) const
  323. {
  324.     const size_t uiOldLength = strlen ( szOld );
  325.     SString strResult = *this;
  326.     while ( strResult.substr ( 0, uiOldLength ) == szOld )
  327.         strResult = strResult.substr ( uiOldLength );
  328.     return strResult;
  329. }
  330.  
  331. //
  332. // Remove szOlds from the end of the string.
  333. //
  334. SString SString::TrimEnd ( const char* szOld ) const
  335. {
  336.     const size_t uiOldLength = strlen ( szOld );
  337.     SString strResult = *this;
  338.     while ( strResult.length () >= uiOldLength && strResult.substr ( strResult.length () - uiOldLength ) == szOld )
  339.         strResult = strResult.substr ( 0, strResult.length () - uiOldLength );
  340.     return strResult;
  341. }
  342.  
  343. //
  344. // Change to all lower case characters.
  345. //
  346. SString SString::ToLower ( void ) const
  347. {
  348.     SString strResult = *this;
  349.     std::transform ( strResult.begin(), strResult.end(), strResult.begin(), SharedUtil::tolower < uchar > );
  350.     return strResult;
  351. }
  352.  
  353. //
  354. // Change to all upper case characters.
  355. //
  356. SString SString::ToUpper ( void ) const
  357. {
  358.     SString strResult = *this;
  359.     std::transform ( strResult.begin(), strResult.end(), strResult.begin(), SharedUtil::toupper < uchar > );
  360.     return strResult;
  361. }
  362.  
  363. //
  364. // Change '0x0a' or '0x0d' or '0x0d 0x0a' to '\n'.
  365. //
  366. SString SString::ConformLineEndings ( void ) const
  367. {
  368.     assert ( '\n' == '\x0A' );
  369.     if ( std::count( begin(), end(), '\n' ) )
  370.         return Replace ( "\x0D", "" );
  371.     else
  372.         return Replace ( "\x0D", "\n" );
  373. }
  374.  
  375. //
  376. // Test if string contains strOther
  377. //
  378. bool SString::Contains ( const SString& strOther ) const
  379. {
  380.     return find ( strOther ) != std::string::npos;
  381. }
  382.  
  383. //
  384. // Test if string contains strOther. Case insensitive.
  385. //
  386. bool SString::ContainsI ( const SString& strOther ) const
  387. {
  388.     return ToUpper ().find ( strOther.ToUpper () ) != std::string::npos;
  389. }
  390.  
  391. //
  392. // Case insensitive compate.
  393. //
  394. bool SString::CompareI ( const SString& strOther ) const
  395. {
  396.     return stricmp ( *this, strOther ) == 0;
  397. }
  398.  
  399. // Fault tolerant version of substr
  400. SString SString::SubStr ( int iPos, int iCount ) const
  401. {
  402.     if ( iPos < 0 )
  403.     {
  404.         iCount += iPos;
  405.         iPos = 0;
  406.     }
  407.     iCount = Max ( 0, iCount );
  408.     if ( iPos + iCount > (int)length () )
  409.     {
  410.         iCount = length () - iPos;
  411.     }
  412.     if ( iCount < 1 )
  413.         return "";
  414.     return substr ( iPos, iCount );
  415. }
  416.  
  417. // Left most number of characters
  418. SString SString::Left ( int iCount ) const
  419. {
  420.     return SubStr ( 0, iCount );
  421. }
  422.  
  423. // Right most number of characters
  424. SString SString::Right ( int iCount ) const
  425. {
  426.     return SubStr ( (int)length () - iCount, iCount );
  427. }
  428.  
  429.  
  430. bool SString::EndsWith ( const SString& strOther ) const
  431. {
  432.     return Right ( (int)strOther.length () ) == strOther;
  433. }
  434.  
  435. bool SString::EndsWithI ( const SString& strOther ) const
  436. {
  437.     return stricmp ( Right ( (int)strOther.length () ), strOther ) == 0;
  438. }
  439.  
  440. bool SString::BeginsWith ( const SString& strOther ) const
  441. {
  442.     return Left ( (int)strOther.length () ) == strOther;
  443. }
  444.  
  445. bool SString::BeginsWithI ( const SString& strOther ) const
  446. {
  447.     return stricmp ( Left ( (int)strOther.length () ), strOther ) == 0;
  448. }
  449.  
  450. // Static function
  451. SString SString::Join ( const SString& strDelim, const std::vector < SString >& parts, int iFirst, int iCount )
  452. {
  453.     SString strResult;
  454.     int iLast = Min < int > ( iFirst + iCount, parts.size () ) - 1;
  455.     iFirst = Max < int > ( iFirst, 0 );
  456.     for ( int i = iFirst ; i <= iLast ; i++ )
  457.     {
  458.         if ( i != iFirst )
  459.             strResult += strDelim;
  460.         strResult += parts[i];
  461.     }
  462.     return strResult;
  463. }
  464.  
  465. void SString::AssignLeft ( const char* szOther, uint uiMaxLength )
  466. {
  467.     assign ( SStringX ( szOther ).Left ( uiMaxLength ) );
  468. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement