LCOV - code coverage report
Current view: top level - usr/include/irrlicht - irrString.h (source / functions) Hit Total Coverage
Test: report Lines: 91 176 51.7 %
Date: 2015-07-11 18:23:49 Functions: 23 36 63.9 %

          Line data    Source code
       1             : // Copyright (C) 2002-2012 Nikolaus Gebhardt
       2             : // This file is part of the "Irrlicht Engine" and the "irrXML" project.
       3             : // For conditions of distribution and use, see copyright notice in irrlicht.h and irrXML.h
       4             : 
       5             : #ifndef __IRR_STRING_H_INCLUDED__
       6             : #define __IRR_STRING_H_INCLUDED__
       7             : 
       8             : #include "irrTypes.h"
       9             : #include "irrAllocator.h"
      10             : #include "irrMath.h"
      11             : #include <stdio.h>
      12             : #include <string.h>
      13             : #include <stdlib.h>
      14             : 
      15             : namespace irr
      16             : {
      17             : namespace core
      18             : {
      19             : 
      20             : //! Very simple string class with some useful features.
      21             : /** string<c8> and string<wchar_t> both accept Unicode AND ASCII/Latin-1,
      22             : so you can assign Unicode to string<c8> and ASCII/Latin-1 to string<wchar_t>
      23             : (and the other way round) if you want to.
      24             : 
      25             : However, note that the conversation between both is not done using any encoding.
      26             : This means that c8 strings are treated as ASCII/Latin-1, not UTF-8, and
      27             : are simply expanded to the equivalent wchar_t, while Unicode/wchar_t
      28             : characters are truncated to 8-bit ASCII/Latin-1 characters, discarding all
      29             : other information in the wchar_t.
      30             : */
      31             : 
      32             : enum eLocaleID
      33             : {
      34             :         IRR_LOCALE_ANSI = 0,
      35             :         IRR_LOCALE_GERMAN = 1
      36             : };
      37             : 
      38             : static eLocaleID locale_current = IRR_LOCALE_ANSI;
      39             : static inline void locale_set ( eLocaleID id )
      40             : {
      41             :         locale_current = id;
      42             : }
      43             : 
      44             : //! Returns a character converted to lower case
      45           0 : static inline u32 locale_lower ( u32 x )
      46             : {
      47           0 :         switch ( locale_current )
      48             :         {
      49             :                 case IRR_LOCALE_GERMAN:
      50             :                 case IRR_LOCALE_ANSI:
      51           0 :                         break;
      52             :         }
      53             :         // ansi
      54           0 :         return x >= 'A' && x <= 'Z' ? x + 0x20 : x;
      55             : }
      56             : 
      57             : //! Returns a character converted to upper case
      58             : static inline u32 locale_upper ( u32 x )
      59             : {
      60             :         switch ( locale_current )
      61             :         {
      62             :                 case IRR_LOCALE_GERMAN:
      63             :                 case IRR_LOCALE_ANSI:
      64             :                         break;
      65             :         }
      66             : 
      67             :         // ansi
      68             :         return x >= 'a' && x <= 'z' ? x + ( 'A' - 'a' ) : x;
      69             : }
      70             : 
      71             : 
      72             : template <typename T, typename TAlloc = irrAllocator<T> >
      73             : class string
      74             : {
      75             : public:
      76             : 
      77             :         typedef T char_type;
      78             : 
      79             :         //! Default constructor
      80        1117 :         string()
      81        1117 :         : array(0), allocated(1), used(1)
      82             :         {
      83        1117 :                 array = allocator.allocate(1); // new T[1];
      84        1117 :                 array[0] = 0;
      85        1117 :         }
      86             : 
      87             : 
      88             :         //! Constructor
      89       20266 :         string(const string<T,TAlloc>& other)
      90       20266 :         : array(0), allocated(0), used(0)
      91             :         {
      92       20266 :                 *this = other;
      93       20266 :         }
      94             : 
      95             :         //! Constructor from other string types
      96             :         template <class B, class A>
      97             :         string(const string<B, A>& other)
      98             :         : array(0), allocated(0), used(0)
      99             :         {
     100             :                 *this = other;
     101             :         }
     102             : 
     103             : 
     104             :         //! Constructs a string from a float
     105             :         explicit string(const double number)
     106             :         : array(0), allocated(0), used(0)
     107             :         {
     108             :                 c8 tmpbuf[255];
     109             :                 snprintf(tmpbuf, 255, "%0.6f", number);
     110             :                 *this = tmpbuf;
     111             :         }
     112             : 
     113             : 
     114             :         //! Constructs a string from an int
     115           0 :         explicit string(int number)
     116           0 :         : array(0), allocated(0), used(0)
     117             :         {
     118             :                 // store if negative and make positive
     119             : 
     120           0 :                 bool negative = false;
     121           0 :                 if (number < 0)
     122             :                 {
     123           0 :                         number *= -1;
     124           0 :                         negative = true;
     125             :                 }
     126             : 
     127             :                 // temporary buffer for 16 numbers
     128             : 
     129           0 :                 c8 tmpbuf[16]={0};
     130           0 :                 u32 idx = 15;
     131             : 
     132             :                 // special case '0'
     133             : 
     134           0 :                 if (!number)
     135             :                 {
     136           0 :                         tmpbuf[14] = '0';
     137           0 :                         *this = &tmpbuf[14];
     138           0 :                         return;
     139             :                 }
     140             : 
     141             :                 // add numbers
     142             : 
     143           0 :                 while(number && idx)
     144             :                 {
     145           0 :                         --idx;
     146           0 :                         tmpbuf[idx] = (c8)('0' + (number % 10));
     147           0 :                         number /= 10;
     148             :                 }
     149             : 
     150             :                 // add sign
     151             : 
     152           0 :                 if (negative)
     153             :                 {
     154           0 :                         --idx;
     155           0 :                         tmpbuf[idx] = '-';
     156             :                 }
     157             : 
     158           0 :                 *this = &tmpbuf[idx];
     159             :         }
     160             : 
     161             : 
     162             :         //! Constructs a string from an unsigned int
     163             :         explicit string(unsigned int number)
     164             :         : array(0), allocated(0), used(0)
     165             :         {
     166             :                 // temporary buffer for 16 numbers
     167             : 
     168             :                 c8 tmpbuf[16]={0};
     169             :                 u32 idx = 15;
     170             : 
     171             :                 // special case '0'
     172             : 
     173             :                 if (!number)
     174             :                 {
     175             :                         tmpbuf[14] = '0';
     176             :                         *this = &tmpbuf[14];
     177             :                         return;
     178             :                 }
     179             : 
     180             :                 // add numbers
     181             : 
     182             :                 while(number && idx)
     183             :                 {
     184             :                         --idx;
     185             :                         tmpbuf[idx] = (c8)('0' + (number % 10));
     186             :                         number /= 10;
     187             :                 }
     188             : 
     189             :                 *this = &tmpbuf[idx];
     190             :         }
     191             : 
     192             : 
     193             :         //! Constructs a string from a long
     194             :         explicit string(long number)
     195             :         : array(0), allocated(0), used(0)
     196             :         {
     197             :                 // store if negative and make positive
     198             : 
     199             :                 bool negative = false;
     200             :                 if (number < 0)
     201             :                 {
     202             :                         number *= -1;
     203             :                         negative = true;
     204             :                 }
     205             : 
     206             :                 // temporary buffer for 16 numbers
     207             : 
     208             :                 c8 tmpbuf[16]={0};
     209             :                 u32 idx = 15;
     210             : 
     211             :                 // special case '0'
     212             : 
     213             :                 if (!number)
     214             :                 {
     215             :                         tmpbuf[14] = '0';
     216             :                         *this = &tmpbuf[14];
     217             :                         return;
     218             :                 }
     219             : 
     220             :                 // add numbers
     221             : 
     222             :                 while(number && idx)
     223             :                 {
     224             :                         --idx;
     225             :                         tmpbuf[idx] = (c8)('0' + (number % 10));
     226             :                         number /= 10;
     227             :                 }
     228             : 
     229             :                 // add sign
     230             : 
     231             :                 if (negative)
     232             :                 {
     233             :                         --idx;
     234             :                         tmpbuf[idx] = '-';
     235             :                 }
     236             : 
     237             :                 *this = &tmpbuf[idx];
     238             :         }
     239             : 
     240             : 
     241             :         //! Constructs a string from an unsigned long
     242             :         explicit string(unsigned long number)
     243             :         : array(0), allocated(0), used(0)
     244             :         {
     245             :                 // temporary buffer for 16 numbers
     246             : 
     247             :                 c8 tmpbuf[16]={0};
     248             :                 u32 idx = 15;
     249             : 
     250             :                 // special case '0'
     251             : 
     252             :                 if (!number)
     253             :                 {
     254             :                         tmpbuf[14] = '0';
     255             :                         *this = &tmpbuf[14];
     256             :                         return;
     257             :                 }
     258             : 
     259             :                 // add numbers
     260             : 
     261             :                 while(number && idx)
     262             :                 {
     263             :                         --idx;
     264             :                         tmpbuf[idx] = (c8)('0' + (number % 10));
     265             :                         number /= 10;
     266             :                 }
     267             : 
     268             :                 *this = &tmpbuf[idx];
     269             :         }
     270             : 
     271             : 
     272             :         //! Constructor for copying a string from a pointer with a given length
     273             :         template <class B>
     274             :         string(const B* const c, u32 length)
     275             :         : array(0), allocated(0), used(0)
     276             :         {
     277             :                 if (!c)
     278             :                 {
     279             :                         // correctly init the string to an empty one
     280             :                         *this="";
     281             :                         return;
     282             :                 }
     283             : 
     284             :                 allocated = used = length+1;
     285             :                 array = allocator.allocate(used); // new T[used];
     286             : 
     287             :                 for (u32 l = 0; l<length; ++l)
     288             :                         array[l] = (T)c[l];
     289             : 
     290             :                 array[length] = 0;
     291             :         }
     292             : 
     293             : 
     294             :         //! Constructor for unicode and ascii strings
     295             :         template <class B>
     296       13203 :         string(const B* const c)
     297       13203 :         : array(0), allocated(0), used(0)
     298             :         {
     299       13203 :                 *this = c;
     300       13203 :         }
     301             : 
     302             : 
     303             :         //! Destructor
     304       19345 :         ~string()
     305             :         {
     306       19345 :                 allocator.deallocate(array); // delete [] array;
     307       19345 :         }
     308             : 
     309             : 
     310             :         //! Assignment operator
     311       21737 :         string<T,TAlloc>& operator=(const string<T,TAlloc>& other)
     312             :         {
     313       21737 :                 if (this == &other)
     314           0 :                         return *this;
     315             : 
     316       21737 :                 used = other.size()+1;
     317       21737 :                 if (used>allocated)
     318             :                 {
     319       21422 :                         allocator.deallocate(array); // delete [] array;
     320       21422 :                         allocated = used;
     321       21422 :                         array = allocator.allocate(used); //new T[used];
     322             :                 }
     323             : 
     324       21737 :                 const T* p = other.c_str();
     325     1214181 :                 for (u32 i=0; i<used; ++i, ++p)
     326     1192444 :                         array[i] = *p;
     327             : 
     328       21737 :                 return *this;
     329             :         }
     330             : 
     331             :         //! Assignment operator for other string types
     332             :         template <class B, class A>
     333             :         string<T,TAlloc>& operator=(const string<B,A>& other)
     334             :         {
     335             :                 *this = other.c_str();
     336             :                 return *this;
     337             :         }
     338             : 
     339             : 
     340             :         //! Assignment operator for strings, ascii and unicode
     341             :         template <class B>
     342       13371 :         string<T,TAlloc>& operator=(const B* const c)
     343             :         {
     344       13371 :                 if (!c)
     345             :                 {
     346           0 :                         if (!array)
     347             :                         {
     348           0 :                                 array = allocator.allocate(1); //new T[1];
     349           0 :                                 allocated = 1;
     350             :                         }
     351           0 :                         used = 1;
     352           0 :                         array[0] = 0x0;
     353           0 :                         return *this;
     354             :                 }
     355             : 
     356       13371 :                 if ((void*)c == (void*)array)
     357           0 :                         return *this;
     358             : 
     359       13371 :                 u32 len = 0;
     360       13371 :                 const B* p = c;
     361      392780 :                 do
     362             :                 {
     363      392780 :                         ++len;
     364             :                 } while(*p++);
     365             : 
     366             :                 // we'll keep the old string for a while, because the new
     367             :                 // string could be a part of the current string.
     368       13371 :                 T* oldArray = array;
     369             : 
     370       13371 :                 used = len;
     371       13371 :                 if (used>allocated)
     372             :                 {
     373       13365 :                         allocated = used;
     374       13365 :                         array = allocator.allocate(used); //new T[used];
     375             :                 }
     376             : 
     377      406151 :                 for (u32 l = 0; l<len; ++l)
     378      392780 :                         array[l] = (T)c[l];
     379             : 
     380       13371 :                 if (oldArray != array)
     381       13365 :                         allocator.deallocate(oldArray); // delete [] oldArray;
     382             : 
     383       13371 :                 return *this;
     384             :         }
     385             : 
     386             : 
     387             :         //! Append operator for other strings
     388             :         string<T,TAlloc> operator+(const string<T,TAlloc>& other) const
     389             :         {
     390             :                 string<T,TAlloc> str(*this);
     391             :                 str.append(other);
     392             : 
     393             :                 return str;
     394             :         }
     395             : 
     396             : 
     397             :         //! Append operator for strings, ascii and unicode
     398             :         template <class B>
     399           0 :         string<T,TAlloc> operator+(const B* const c) const
     400             :         {
     401           0 :                 string<T,TAlloc> str(*this);
     402           0 :                 str.append(c);
     403             : 
     404           0 :                 return str;
     405             :         }
     406             : 
     407             : 
     408             :         //! Direct access operator
     409         273 :         T& operator [](const u32 index)
     410             :         {
     411             :                 _IRR_DEBUG_BREAK_IF(index>=used) // bad index
     412         273 :                 return array[index];
     413             :         }
     414             : 
     415             : 
     416             :         //! Direct access operator
     417           0 :         const T& operator [](const u32 index) const
     418             :         {
     419             :                 _IRR_DEBUG_BREAK_IF(index>=used) // bad index
     420           0 :                 return array[index];
     421             :         }
     422             : 
     423             : 
     424             :         //! Equality operator
     425             :         bool operator==(const T* const str) const
     426             :         {
     427             :                 if (!str)
     428             :                         return false;
     429             : 
     430             :                 u32 i;
     431             :                 for (i=0; array[i] && str[i]; ++i)
     432             :                         if (array[i] != str[i])
     433             :                                 return false;
     434             : 
     435             :                 return (!array[i] && !str[i]);
     436             :         }
     437             : 
     438             : 
     439             :         //! Equality operator
     440             :         bool operator==(const string<T,TAlloc>& other) const
     441             :         {
     442             :                 for (u32 i=0; array[i] && other.array[i]; ++i)
     443             :                         if (array[i] != other.array[i])
     444             :                                 return false;
     445             : 
     446             :                 return used == other.used;
     447             :         }
     448             : 
     449             : 
     450             :         //! Is smaller comparator
     451           0 :         bool operator<(const string<T,TAlloc>& other) const
     452             :         {
     453           0 :                 for (u32 i=0; array[i] && other.array[i]; ++i)
     454             :                 {
     455           0 :                         const s32 diff = array[i] - other.array[i];
     456           0 :                         if (diff)
     457           0 :                                 return (diff < 0);
     458             :                 }
     459             : 
     460           0 :                 return (used < other.used);
     461             :         }
     462             : 
     463             : 
     464             :         //! Inequality operator
     465             :         bool operator!=(const T* const str) const
     466             :         {
     467             :                 return !(*this == str);
     468             :         }
     469             : 
     470             : 
     471             :         //! Inequality operator
     472             :         bool operator!=(const string<T,TAlloc>& other) const
     473             :         {
     474             :                 return !(*this == other);
     475             :         }
     476             : 
     477             : 
     478             :         //! Returns length of the string's content
     479             :         /** \return Length of the string's content in characters, excluding
     480             :         the trailing NUL. */
     481       22574 :         u32 size() const
     482             :         {
     483       22574 :                 return used-1;
     484             :         }
     485             : 
     486             :         //! Informs if the string is empty or not.
     487             :         //! \return True if the string is empty, false if not.
     488             :         bool empty() const
     489             :         {
     490             :                 return (size() == 0);
     491             :         }
     492             : 
     493             :         //! Returns character string
     494             :         /** \return pointer to C-style NUL terminated string. */
     495       23392 :         const T* c_str() const
     496             :         {
     497       23392 :                 return array;
     498             :         }
     499             : 
     500             : 
     501             :         //! Makes the string lower case.
     502             :         string<T,TAlloc>& make_lower()
     503             :         {
     504             :                 for (u32 i=0; array[i]; ++i)
     505             :                         array[i] = locale_lower ( array[i] );
     506             :                 return *this;
     507             :         }
     508             : 
     509             : 
     510             :         //! Makes the string upper case.
     511             :         string<T,TAlloc>& make_upper()
     512             :         {
     513             :                 for (u32 i=0; array[i]; ++i)
     514             :                         array[i] = locale_upper ( array[i] );
     515             :                 return *this;
     516             :         }
     517             : 
     518             : 
     519             :         //! Compares the strings ignoring case.
     520             :         /** \param other: Other string to compare.
     521             :         \return True if the strings are equal ignoring case. */
     522           0 :         bool equals_ignore_case(const string<T,TAlloc>& other) const
     523             :         {
     524           0 :                 for(u32 i=0; array[i] && other[i]; ++i)
     525           0 :                         if (locale_lower( array[i]) != locale_lower(other[i]))
     526           0 :                                 return false;
     527             : 
     528           0 :                 return used == other.used;
     529             :         }
     530             : 
     531             :         //! Compares the strings ignoring case.
     532             :         /** \param other: Other string to compare.
     533             :                 \param sourcePos: where to start to compare in the string
     534             :         \return True if the strings are equal ignoring case. */
     535             :         bool equals_substring_ignore_case(const string<T,TAlloc>&other, const s32 sourcePos = 0 ) const
     536             :         {
     537             :                 if ( (u32) sourcePos >= used )
     538             :                         return false;
     539             : 
     540             :                 u32 i;
     541             :                 for( i=0; array[sourcePos + i] && other[i]; ++i)
     542             :                         if (locale_lower( array[sourcePos + i]) != locale_lower(other[i]))
     543             :                                 return false;
     544             : 
     545             :                 return array[sourcePos + i] == 0 && other[i] == 0;
     546             :         }
     547             : 
     548             : 
     549             :         //! Compares the strings ignoring case.
     550             :         /** \param other: Other string to compare.
     551             :         \return True if this string is smaller ignoring case. */
     552             :         bool lower_ignore_case(const string<T,TAlloc>& other) const
     553             :         {
     554             :                 for(u32 i=0; array[i] && other.array[i]; ++i)
     555             :                 {
     556             :                         s32 diff = (s32) locale_lower ( array[i] ) - (s32) locale_lower ( other.array[i] );
     557             :                         if ( diff )
     558             :                                 return diff < 0;
     559             :                 }
     560             : 
     561             :                 return used < other.used;
     562             :         }
     563             : 
     564             : 
     565             :         //! compares the first n characters of the strings
     566             :         /** \param other Other string to compare.
     567             :         \param n Number of characters to compare
     568             :         \return True if the n first characters of both strings are equal. */
     569             :         bool equalsn(const string<T,TAlloc>& other, u32 n) const
     570             :         {
     571             :                 u32 i;
     572             :                 for(i=0; array[i] && other[i] && i < n; ++i)
     573             :                         if (array[i] != other[i])
     574             :                                 return false;
     575             : 
     576             :                 // if one (or both) of the strings was smaller then they
     577             :                 // are only equal if they have the same length
     578             :                 return (i == n) || (used == other.used);
     579             :         }
     580             : 
     581             : 
     582             :         //! compares the first n characters of the strings
     583             :         /** \param str Other string to compare.
     584             :         \param n Number of characters to compare
     585             :         \return True if the n first characters of both strings are equal. */
     586             :         bool equalsn(const T* const str, u32 n) const
     587             :         {
     588             :                 if (!str)
     589             :                         return false;
     590             :                 u32 i;
     591             :                 for(i=0; array[i] && str[i] && i < n; ++i)
     592             :                         if (array[i] != str[i])
     593             :                                 return false;
     594             : 
     595             :                 // if one (or both) of the strings was smaller then they
     596             :                 // are only equal if they have the same length
     597             :                 return (i == n) || (array[i] == 0 && str[i] == 0);
     598             :         }
     599             : 
     600             : 
     601             :         //! Appends a character to this string
     602             :         /** \param character: Character to append. */
     603           0 :         string<T,TAlloc>& append(T character)
     604             :         {
     605           0 :                 if (used + 1 > allocated)
     606           0 :                         reallocate(used + 1);
     607             : 
     608           0 :                 ++used;
     609             : 
     610           0 :                 array[used-2] = character;
     611           0 :                 array[used-1] = 0;
     612             : 
     613           0 :                 return *this;
     614             :         }
     615             : 
     616             : 
     617             :         //! Appends a char string to this string
     618             :         /** \param other: Char string to append. */
     619             :         /** \param length: The length of the string to append. */
     620          10 :         string<T,TAlloc>& append(const T* const other, u32 length=0xffffffff)
     621             :         {
     622          10 :                 if (!other)
     623           0 :                         return *this;
     624             : 
     625          10 :                 u32 len = 0;
     626          10 :                 const T* p = other;
     627         106 :                 while(*p)
     628             :                 {
     629          48 :                         ++len;
     630          48 :                         ++p;
     631             :                 }
     632          10 :                 if (len > length)
     633           0 :                         len = length;
     634             : 
     635          10 :                 if (used + len > allocated)
     636          10 :                         reallocate(used + len);
     637             : 
     638          10 :                 --used;
     639          10 :                 ++len;
     640             : 
     641          68 :                 for (u32 l=0; l<len; ++l)
     642          58 :                         array[l+used] = *(other+l);
     643             : 
     644          10 :                 used += len;
     645             : 
     646          10 :                 return *this;
     647             :         }
     648             : 
     649             : 
     650             :         //! Appends a string to this string
     651             :         /** \param other: String to append. */
     652           0 :         string<T,TAlloc>& append(const string<T,TAlloc>& other)
     653             :         {
     654           0 :                 if (other.size() == 0)
     655           0 :                         return *this;
     656             : 
     657           0 :                 --used;
     658           0 :                 u32 len = other.size()+1;
     659             : 
     660           0 :                 if (used + len > allocated)
     661           0 :                         reallocate(used + len);
     662             : 
     663           0 :                 for (u32 l=0; l<len; ++l)
     664           0 :                         array[used+l] = other[l];
     665             : 
     666           0 :                 used += len;
     667             : 
     668           0 :                 return *this;
     669             :         }
     670             : 
     671             : 
     672             :         //! Appends a string of the length l to this string.
     673             :         /** \param other: other String to append to this string.
     674             :         \param length: How much characters of the other string to add to this one. */
     675             :         string<T,TAlloc>& append(const string<T,TAlloc>& other, u32 length)
     676             :         {
     677             :                 if (other.size() == 0)
     678             :                         return *this;
     679             : 
     680             :                 if (other.size() < length)
     681             :                 {
     682             :                         append(other);
     683             :                         return *this;
     684             :                 }
     685             : 
     686             :                 if (used + length > allocated)
     687             :                         reallocate(used + length);
     688             : 
     689             :                 --used;
     690             : 
     691             :                 for (u32 l=0; l<length; ++l)
     692             :                         array[l+used] = other[l];
     693             :                 used += length;
     694             : 
     695             :                 // ensure proper termination
     696             :                 array[used]=0;
     697             :                 ++used;
     698             : 
     699             :                 return *this;
     700             :         }
     701             : 
     702             : 
     703             :         //! Reserves some memory.
     704             :         /** \param count: Amount of characters to reserve. */
     705         279 :         void reserve(u32 count)
     706             :         {
     707         279 :                 if (count < allocated)
     708           0 :                         return;
     709             : 
     710         279 :                 reallocate(count);
     711             :         }
     712             : 
     713             : 
     714             :         //! finds first occurrence of character in string
     715             :         /** \param c: Character to search for.
     716             :         \return Position where the character has been found,
     717             :         or -1 if not found. */
     718             :         s32 findFirst(T c) const
     719             :         {
     720             :                 for (u32 i=0; i<used-1; ++i)
     721             :                         if (array[i] == c)
     722             :                                 return i;
     723             : 
     724             :                 return -1;
     725             :         }
     726             : 
     727             :         //! finds first occurrence of a character of a list in string
     728             :         /** \param c: List of characters to find. For example if the method
     729             :         should find the first occurrence of 'a' or 'b', this parameter should be "ab".
     730             :         \param count: Amount of characters in the list. Usually,
     731             :         this should be strlen(c)
     732             :         \return Position where one of the characters has been found,
     733             :         or -1 if not found. */
     734             :         s32 findFirstChar(const T* const c, u32 count=1) const
     735             :         {
     736             :                 if (!c || !count)
     737             :                         return -1;
     738             : 
     739             :                 for (u32 i=0; i<used-1; ++i)
     740             :                         for (u32 j=0; j<count; ++j)
     741             :                                 if (array[i] == c[j])
     742             :                                         return i;
     743             : 
     744             :                 return -1;
     745             :         }
     746             : 
     747             : 
     748             :         //! Finds first position of a character not in a given list.
     749             :         /** \param c: List of characters not to find. For example if the method
     750             :         should find the first occurrence of a character not 'a' or 'b', this parameter should be "ab".
     751             :         \param count: Amount of characters in the list. Usually,
     752             :         this should be strlen(c)
     753             :         \return Position where the character has been found,
     754             :         or -1 if not found. */
     755             :         template <class B>
     756             :         s32 findFirstCharNotInList(const B* const c, u32 count=1) const
     757             :         {
     758             :                 if (!c || !count)
     759             :                         return -1;
     760             : 
     761             :                 for (u32 i=0; i<used-1; ++i)
     762             :                 {
     763             :                         u32 j;
     764             :                         for (j=0; j<count; ++j)
     765             :                                 if (array[i] == c[j])
     766             :                                         break;
     767             : 
     768             :                         if (j==count)
     769             :                                 return i;
     770             :                 }
     771             : 
     772             :                 return -1;
     773             :         }
     774             : 
     775             :         //! Finds last position of a character not in a given list.
     776             :         /** \param c: List of characters not to find. For example if the method
     777             :         should find the first occurrence of a character not 'a' or 'b', this parameter should be "ab".
     778             :         \param count: Amount of characters in the list. Usually,
     779             :         this should be strlen(c)
     780             :         \return Position where the character has been found,
     781             :         or -1 if not found. */
     782             :         template <class B>
     783             :         s32 findLastCharNotInList(const B* const c, u32 count=1) const
     784             :         {
     785             :                 if (!c || !count)
     786             :                         return -1;
     787             : 
     788             :                 for (s32 i=(s32)(used-2); i>=0; --i)
     789             :                 {
     790             :                         u32 j;
     791             :                         for (j=0; j<count; ++j)
     792             :                                 if (array[i] == c[j])
     793             :                                         break;
     794             : 
     795             :                         if (j==count)
     796             :                                 return i;
     797             :                 }
     798             : 
     799             :                 return -1;
     800             :         }
     801             : 
     802             :         //! finds next occurrence of character in string
     803             :         /** \param c: Character to search for.
     804             :         \param startPos: Position in string to start searching.
     805             :         \return Position where the character has been found,
     806             :         or -1 if not found. */
     807             :         s32 findNext(T c, u32 startPos) const
     808             :         {
     809             :                 for (u32 i=startPos; i<used-1; ++i)
     810             :                         if (array[i] == c)
     811             :                                 return i;
     812             : 
     813             :                 return -1;
     814             :         }
     815             : 
     816             : 
     817             :         //! finds last occurrence of character in string
     818             :         /** \param c: Character to search for.
     819             :         \param start: start to search reverse ( default = -1, on end )
     820             :         \return Position where the character has been found,
     821             :         or -1 if not found. */
     822             :         s32 findLast(T c, s32 start = -1) const
     823             :         {
     824             :                 start = core::clamp ( start < 0 ? (s32)(used) - 2 : start, 0, (s32)(used) - 2 );
     825             :                 for (s32 i=start; i>=0; --i)
     826             :                         if (array[i] == c)
     827             :                                 return i;
     828             : 
     829             :                 return -1;
     830             :         }
     831             : 
     832             :         //! finds last occurrence of a character of a list in string
     833             :         /** \param c: List of strings to find. For example if the method
     834             :         should find the last occurrence of 'a' or 'b', this parameter should be "ab".
     835             :         \param count: Amount of characters in the list. Usually,
     836             :         this should be strlen(c)
     837             :         \return Position where one of the characters has been found,
     838             :         or -1 if not found. */
     839             :         s32 findLastChar(const T* const c, u32 count=1) const
     840             :         {
     841             :                 if (!c || !count)
     842             :                         return -1;
     843             : 
     844             :                 for (s32 i=(s32)used-2; i>=0; --i)
     845             :                         for (u32 j=0; j<count; ++j)
     846             :                                 if (array[i] == c[j])
     847             :                                         return i;
     848             : 
     849             :                 return -1;
     850             :         }
     851             : 
     852             : 
     853             :         //! finds another string in this string
     854             :         /** \param str: Another string
     855             :         \param start: Start position of the search
     856             :         \return Positions where the string has been found,
     857             :         or -1 if not found. */
     858             :         template <class B>
     859             :         s32 find(const B* const str, const u32 start = 0) const
     860             :         {
     861             :                 if (str && *str)
     862             :                 {
     863             :                         u32 len = 0;
     864             : 
     865             :                         while (str[len])
     866             :                                 ++len;
     867             : 
     868             :                         if (len > used-1)
     869             :                                 return -1;
     870             : 
     871             :                         for (u32 i=start; i<used-len; ++i)
     872             :                         {
     873             :                                 u32 j=0;
     874             : 
     875             :                                 while(str[j] && array[i+j] == str[j])
     876             :                                         ++j;
     877             : 
     878             :                                 if (!str[j])
     879             :                                         return i;
     880             :                         }
     881             :                 }
     882             : 
     883             :                 return -1;
     884             :         }
     885             : 
     886             : 
     887             :         //! Returns a substring
     888             :         /** \param begin Start of substring.
     889             :         \param length Length of substring.
     890             :         \param make_lower copy only lower case */
     891         285 :         string<T> subString(u32 begin, s32 length, bool make_lower = false ) const
     892             :         {
     893             :                 // if start after string
     894             :                 // or no proper substring length
     895         285 :                 if ((length <= 0) || (begin>=size()))
     896           6 :                         return string<T>("");
     897             :                 // clamp length to maximal value
     898         279 :                 if ((length+begin) > size())
     899           0 :                         length = size()-begin;
     900             : 
     901         558 :                 string<T> o;
     902         279 :                 o.reserve(length+1);
     903             : 
     904             :                 s32 i;
     905         279 :                 if ( !make_lower )
     906             :                 {
     907        2511 :                         for (i=0; i<length; ++i)
     908        2232 :                                 o.array[i] = array[i+begin];
     909             :                 }
     910             :                 else
     911             :                 {
     912           0 :                         for (i=0; i<length; ++i)
     913           0 :                                 o.array[i] = locale_lower ( array[i+begin] );
     914             :                 }
     915             : 
     916         279 :                 o.array[length] = 0;
     917         279 :                 o.used = length + 1;
     918             : 
     919         279 :                 return o;
     920             :         }
     921             : 
     922             : 
     923             :         //! Appends a character to this string
     924             :         /** \param c Character to append. */
     925           0 :         string<T,TAlloc>& operator += (T c)
     926             :         {
     927           0 :                 append(c);
     928           0 :                 return *this;
     929             :         }
     930             : 
     931             : 
     932             :         //! Appends a char string to this string
     933             :         /** \param c Char string to append. */
     934             :         string<T,TAlloc>& operator += (const T* const c)
     935             :         {
     936             :                 append(c);
     937             :                 return *this;
     938             :         }
     939             : 
     940             : 
     941             :         //! Appends a string to this string
     942             :         /** \param other String to append. */
     943           0 :         string<T,TAlloc>& operator += (const string<T,TAlloc>& other)
     944             :         {
     945           0 :                 append(other);
     946           0 :                 return *this;
     947             :         }
     948             : 
     949             : 
     950             :         //! Appends a string representation of a number to this string
     951             :         /** \param i Number to append. */
     952             :         string<T,TAlloc>& operator += (const int i)
     953             :         {
     954             :                 append(string<T,TAlloc>(i));
     955             :                 return *this;
     956             :         }
     957             : 
     958             : 
     959             :         //! Appends a string representation of a number to this string
     960             :         /** \param i Number to append. */
     961             :         string<T,TAlloc>& operator += (const unsigned int i)
     962             :         {
     963             :                 append(string<T,TAlloc>(i));
     964             :                 return *this;
     965             :         }
     966             : 
     967             : 
     968             :         //! Appends a string representation of a number to this string
     969             :         /** \param i Number to append. */
     970             :         string<T,TAlloc>& operator += (const long i)
     971             :         {
     972             :                 append(string<T,TAlloc>(i));
     973             :                 return *this;
     974             :         }
     975             : 
     976             : 
     977             :         //! Appends a string representation of a number to this string
     978             :         /** \param i Number to append. */
     979             :         string<T,TAlloc>& operator += (const unsigned long i)
     980             :         {
     981             :                 append(string<T,TAlloc>(i));
     982             :                 return *this;
     983             :         }
     984             : 
     985             : 
     986             :         //! Appends a string representation of a number to this string
     987             :         /** \param i Number to append. */
     988             :         string<T,TAlloc>& operator += (const double i)
     989             :         {
     990             :                 append(string<T,TAlloc>(i));
     991             :                 return *this;
     992             :         }
     993             : 
     994             : 
     995             :         //! Appends a string representation of a number to this string
     996             :         /** \param i Number to append. */
     997             :         string<T,TAlloc>& operator += (const float i)
     998             :         {
     999             :                 append(string<T,TAlloc>(i));
    1000             :                 return *this;
    1001             :         }
    1002             : 
    1003             : 
    1004             :         //! Replaces all characters of a special type with another one
    1005             :         /** \param toReplace Character to replace.
    1006             :         \param replaceWith Character replacing the old one. */
    1007             :         string<T,TAlloc>& replace(T toReplace, T replaceWith)
    1008             :         {
    1009             :                 for (u32 i=0; i<used-1; ++i)
    1010             :                         if (array[i] == toReplace)
    1011             :                                 array[i] = replaceWith;
    1012             :                 return *this;
    1013             :         }
    1014             : 
    1015             : 
    1016             :         //! Replaces all instances of a string with another one.
    1017             :         /** \param toReplace The string to replace.
    1018             :         \param replaceWith The string replacing the old one. */
    1019             :         string<T,TAlloc>& replace(const string<T,TAlloc>& toReplace, const string<T,TAlloc>& replaceWith)
    1020             :         {
    1021             :                 if (toReplace.size() == 0)
    1022             :                         return *this;
    1023             : 
    1024             :                 const T* other = toReplace.c_str();
    1025             :                 const T* replace = replaceWith.c_str();
    1026             :                 const u32 other_size = toReplace.size();
    1027             :                 const u32 replace_size = replaceWith.size();
    1028             : 
    1029             :                 // Determine the delta.  The algorithm will change depending on the delta.
    1030             :                 s32 delta = replace_size - other_size;
    1031             : 
    1032             :                 // A character for character replace.  The string will not shrink or grow.
    1033             :                 if (delta == 0)
    1034             :                 {
    1035             :                         s32 pos = 0;
    1036             :                         while ((pos = find(other, pos)) != -1)
    1037             :                         {
    1038             :                                 for (u32 i = 0; i < replace_size; ++i)
    1039             :                                         array[pos + i] = replace[i];
    1040             :                                 ++pos;
    1041             :                         }
    1042             :                         return *this;
    1043             :                 }
    1044             : 
    1045             :                 // We are going to be removing some characters.  The string will shrink.
    1046             :                 if (delta < 0)
    1047             :                 {
    1048             :                         u32 i = 0;
    1049             :                         for (u32 pos = 0; pos < used; ++i, ++pos)
    1050             :                         {
    1051             :                                 // Is this potentially a match?
    1052             :                                 if (array[pos] == *other)
    1053             :                                 {
    1054             :                                         // Check to see if we have a match.
    1055             :                                         u32 j;
    1056             :                                         for (j = 0; j < other_size; ++j)
    1057             :                                         {
    1058             :                                                 if (array[pos + j] != other[j])
    1059             :                                                         break;
    1060             :                                         }
    1061             : 
    1062             :                                         // If we have a match, replace characters.
    1063             :                                         if (j == other_size)
    1064             :                                         {
    1065             :                                                 for (j = 0; j < replace_size; ++j)
    1066             :                                                         array[i + j] = replace[j];
    1067             :                                                 i += replace_size - 1;
    1068             :                                                 pos += other_size - 1;
    1069             :                                                 continue;
    1070             :                                         }
    1071             :                                 }
    1072             : 
    1073             :                                 // No match found, just copy characters.
    1074             :                                 array[i] = array[pos];
    1075             :                         }
    1076             :                         array[i-1] = 0;
    1077             :                         used = i;
    1078             : 
    1079             :                         return *this;
    1080             :                 }
    1081             : 
    1082             :                 // We are going to be adding characters, so the string size will increase.
    1083             :                 // Count the number of times toReplace exists in the string so we can allocate the new size.
    1084             :                 u32 find_count = 0;
    1085             :                 s32 pos = 0;
    1086             :                 while ((pos = find(other, pos)) != -1)
    1087             :                 {
    1088             :                         ++find_count;
    1089             :                         ++pos;
    1090             :                 }
    1091             : 
    1092             :                 // Re-allocate the string now, if needed.
    1093             :                 u32 len = delta * find_count;
    1094             :                 if (used + len > allocated)
    1095             :                         reallocate(used + len);
    1096             : 
    1097             :                 // Start replacing.
    1098             :                 pos = 0;
    1099             :                 while ((pos = find(other, pos)) != -1)
    1100             :                 {
    1101             :                         T* start = array + pos + other_size - 1;
    1102             :                         T* ptr   = array + used - 1;
    1103             :                         T* end   = array + delta + used -1;
    1104             : 
    1105             :                         // Shift characters to make room for the string.
    1106             :                         while (ptr != start)
    1107             :                         {
    1108             :                                 *end = *ptr;
    1109             :                                 --ptr;
    1110             :                                 --end;
    1111             :                         }
    1112             : 
    1113             :                         // Add the new string now.
    1114             :                         for (u32 i = 0; i < replace_size; ++i)
    1115             :                                 array[pos + i] = replace[i];
    1116             : 
    1117             :                         pos += replace_size;
    1118             :                         used += delta;
    1119             :                 }
    1120             : 
    1121             :                 return *this;
    1122             :         }
    1123             : 
    1124             : 
    1125             :         //! Removes characters from a string.
    1126             :         /** \param c: Character to remove. */
    1127             :         string<T,TAlloc>& remove(T c)
    1128             :         {
    1129             :                 u32 pos = 0;
    1130             :                 u32 found = 0;
    1131             :                 for (u32 i=0; i<used-1; ++i)
    1132             :                 {
    1133             :                         if (array[i] == c)
    1134             :                         {
    1135             :                                 ++found;
    1136             :                                 continue;
    1137             :                         }
    1138             : 
    1139             :                         array[pos++] = array[i];
    1140             :                 }
    1141             :                 used -= found;
    1142             :                 array[used-1] = 0;
    1143             :                 return *this;
    1144             :         }
    1145             : 
    1146             : 
    1147             :         //! Removes a string from the string.
    1148             :         /** \param toRemove: String to remove. */
    1149             :         string<T,TAlloc>& remove(const string<T,TAlloc>& toRemove)
    1150             :         {
    1151             :                 u32 size = toRemove.size();
    1152             :                 if ( size == 0 )
    1153             :                         return *this;
    1154             :                 u32 pos = 0;
    1155             :                 u32 found = 0;
    1156             :                 for (u32 i=0; i<used-1; ++i)
    1157             :                 {
    1158             :                         u32 j = 0;
    1159             :                         while (j < size)
    1160             :                         {
    1161             :                                 if (array[i + j] != toRemove[j])
    1162             :                                         break;
    1163             :                                 ++j;
    1164             :                         }
    1165             :                         if (j == size)
    1166             :                         {
    1167             :                                 found += size;
    1168             :                                 i += size - 1;
    1169             :                                 continue;
    1170             :                         }
    1171             : 
    1172             :                         array[pos++] = array[i];
    1173             :                 }
    1174             :                 used -= found;
    1175             :                 array[used-1] = 0;
    1176             :                 return *this;
    1177             :         }
    1178             : 
    1179             : 
    1180             :         //! Removes characters from a string.
    1181             :         /** \param characters: Characters to remove. */
    1182             :         string<T,TAlloc>& removeChars(const string<T,TAlloc> & characters)
    1183             :         {
    1184             :                 if (characters.size() == 0)
    1185             :                         return *this;
    1186             : 
    1187             :                 u32 pos = 0;
    1188             :                 u32 found = 0;
    1189             :                 for (u32 i=0; i<used-1; ++i)
    1190             :                 {
    1191             :                         // Don't use characters.findFirst as it finds the \0,
    1192             :                         // causing used to become incorrect.
    1193             :                         bool docontinue = false;
    1194             :                         for (u32 j=0; j<characters.size(); ++j)
    1195             :                         {
    1196             :                                 if (characters[j] == array[i])
    1197             :                                 {
    1198             :                                         ++found;
    1199             :                                         docontinue = true;
    1200             :                                         break;
    1201             :                                 }
    1202             :                         }
    1203             :                         if (docontinue)
    1204             :                                 continue;
    1205             : 
    1206             :                         array[pos++] = array[i];
    1207             :                 }
    1208             :                 used -= found;
    1209             :                 array[used-1] = 0;
    1210             : 
    1211             :                 return *this;
    1212             :         }
    1213             : 
    1214             : 
    1215             :         //! Trims the string.
    1216             :         /** Removes the specified characters (by default, Latin-1 whitespace)
    1217             :         from the begining and the end of the string. */
    1218             :         string<T,TAlloc>& trim(const string<T,TAlloc> & whitespace = " \t\n\r")
    1219             :         {
    1220             :                 // find start and end of the substring without the specified characters
    1221             :                 const s32 begin = findFirstCharNotInList(whitespace.c_str(), whitespace.used);
    1222             :                 if (begin == -1)
    1223             :                         return (*this="");
    1224             : 
    1225             :                 const s32 end = findLastCharNotInList(whitespace.c_str(), whitespace.used);
    1226             : 
    1227             :                 return (*this = subString(begin, (end +1) - begin));
    1228             :         }
    1229             : 
    1230             : 
    1231             :         //! Erases a character from the string.
    1232             :         /** May be slow, because all elements
    1233             :         following after the erased element have to be copied.
    1234             :         \param index: Index of element to be erased. */
    1235           0 :         string<T,TAlloc>& erase(u32 index)
    1236             :         {
    1237             :                 _IRR_DEBUG_BREAK_IF(index>=used) // access violation
    1238             : 
    1239           0 :                 for (u32 i=index+1; i<used; ++i)
    1240           0 :                         array[i-1] = array[i];
    1241             : 
    1242           0 :                 --used;
    1243           0 :                 return *this;
    1244             :         }
    1245             : 
    1246             :         //! verify the existing string.
    1247             :         string<T,TAlloc>& validate()
    1248             :         {
    1249             :                 // terminate on existing null
    1250             :                 for (u32 i=0; i<allocated; ++i)
    1251             :                 {
    1252             :                         if (array[i] == 0)
    1253             :                         {
    1254             :                                 used = i + 1;
    1255             :                                 return *this;
    1256             :                         }
    1257             :                 }
    1258             : 
    1259             :                 // terminate
    1260             :                 if ( allocated > 0 )
    1261             :                 {
    1262             :                         used = allocated;
    1263             :                         array[used-1] = 0;
    1264             :                 }
    1265             :                 else
    1266             :                 {
    1267             :                         used = 0;
    1268             :                 }
    1269             : 
    1270             :                 return *this;
    1271             :         }
    1272             : 
    1273             :         //! gets the last char of a string or null
    1274             :         T lastChar() const
    1275             :         {
    1276             :                 return used > 1 ? array[used-2] : 0;
    1277             :         }
    1278             : 
    1279             :         //! split string into parts.
    1280             :         /** This method will split a string at certain delimiter characters
    1281             :         into the container passed in as reference. The type of the container
    1282             :         has to be given as template parameter. It must provide a push_back and
    1283             :         a size method.
    1284             :         \param ret The result container
    1285             :         \param c C-style string of delimiter characters
    1286             :         \param count Number of delimiter characters
    1287             :         \param ignoreEmptyTokens Flag to avoid empty substrings in the result
    1288             :         container. If two delimiters occur without a character in between, an
    1289             :         empty substring would be placed in the result. If this flag is set,
    1290             :         only non-empty strings are stored.
    1291             :         \param keepSeparators Flag which allows to add the separator to the
    1292             :         result string. If this flag is true, the concatenation of the
    1293             :         substrings results in the original string. Otherwise, only the
    1294             :         characters between the delimiters are returned.
    1295             :         \return The number of resulting substrings
    1296             :         */
    1297             :         template<class container>
    1298             :         u32 split(container& ret, const T* const c, u32 count=1, bool ignoreEmptyTokens=true, bool keepSeparators=false) const
    1299             :         {
    1300             :                 if (!c)
    1301             :                         return 0;
    1302             : 
    1303             :                 const u32 oldSize=ret.size();
    1304             :                 u32 lastpos = 0;
    1305             :                 bool lastWasSeparator = false;
    1306             :                 for (u32 i=0; i<used; ++i)
    1307             :                 {
    1308             :                         bool foundSeparator = false;
    1309             :                         for (u32 j=0; j<count; ++j)
    1310             :                         {
    1311             :                                 if (array[i] == c[j])
    1312             :                                 {
    1313             :                                         if ((!ignoreEmptyTokens || i - lastpos != 0) &&
    1314             :                                                         !lastWasSeparator)
    1315             :                                                 ret.push_back(string<T,TAlloc>(&array[lastpos], i - lastpos));
    1316             :                                         foundSeparator = true;
    1317             :                                         lastpos = (keepSeparators ? i : i + 1);
    1318             :                                         break;
    1319             :                                 }
    1320             :                         }
    1321             :                         lastWasSeparator = foundSeparator;
    1322             :                 }
    1323             :                 if ((used - 1) > lastpos)
    1324             :                         ret.push_back(string<T,TAlloc>(&array[lastpos], (used - 1) - lastpos));
    1325             :                 return ret.size()-oldSize;
    1326             :         }
    1327             : 
    1328             : private:
    1329             : 
    1330             :         //! Reallocate the array, make it bigger or smaller
    1331         289 :         void reallocate(u32 new_size)
    1332             :         {
    1333         289 :                 T* old_array = array;
    1334             : 
    1335         289 :                 array = allocator.allocate(new_size); //new T[new_size];
    1336         289 :                 allocated = new_size;
    1337             : 
    1338         289 :                 u32 amount = used < new_size ? used : new_size;
    1339         896 :                 for (u32 i=0; i<amount; ++i)
    1340         607 :                         array[i] = old_array[i];
    1341             : 
    1342         289 :                 if (allocated < used)
    1343           0 :                         used = allocated;
    1344             : 
    1345         289 :                 allocator.deallocate(old_array); // delete [] old_array;
    1346         289 :         }
    1347             : 
    1348             :         //--- member variables
    1349             : 
    1350             :         T* array;
    1351             :         u32 allocated;
    1352             :         u32 used;
    1353             :         TAlloc allocator;
    1354             : };
    1355             : 
    1356             : 
    1357             : //! Typedef for character strings
    1358             : typedef string<c8> stringc;
    1359             : 
    1360             : //! Typedef for wide character strings
    1361             : typedef string<wchar_t> stringw;
    1362             : 
    1363             : 
    1364             : } // end namespace core
    1365             : } // end namespace irr
    1366             : 
    1367             : #endif
    1368             : 

Generated by: LCOV version 1.11