diff options
Diffstat (limited to 'include/irrString.h')
-rw-r--r-- | include/irrString.h | 978 |
1 files changed, 232 insertions, 746 deletions
diff --git a/include/irrString.h b/include/irrString.h index 0742e0b..d62eeee 100644 --- a/include/irrString.h +++ b/include/irrString.h @@ -6,12 +6,11 @@ #define __IRR_STRING_H_INCLUDED__
#include "irrTypes.h"
-#include "irrAllocator.h"
-#include "irrMath.h"
-#include <stdio.h>
-#include <string.h>
-#include <stdlib.h>
-#include <wchar.h>
+#include <string>
+#include <algorithm>
+#include <cstdio>
+#include <cstring>
+#include <cwchar>
namespace irr
{
@@ -34,11 +33,10 @@ outside the string class for explicit use. */
// forward declarations
-template <typename T, typename TAlloc = irrAllocator<T> >
+template <typename T>
class string;
static size_t multibyteToWString(string<wchar_t>& destination, const char* source, u32 sourceSize);
static size_t wStringToMultibyte(string<c8>& destination, const wchar_t* source, u32 sourceSize);
-//inline bool isdigit(s32 c);
//! Returns a character converted to lower case
static inline u32 locale_lower ( u32 x )
@@ -55,7 +53,7 @@ static inline u32 locale_upper ( u32 x ) }
-template <typename T, typename TAlloc>
+template <typename T>
class string
{
public:
@@ -64,24 +62,18 @@ public: //! Default constructor
string()
- : array(0), allocated(1), used(1)
- {
- array = allocator.allocate(1); // new T[1];
- array[0] = 0;
- }
+ {}
- //! Constructor
- string(const string<T,TAlloc>& other)
- : array(0), allocated(0), used(0)
+ //! Copy constructor
+ string(const string<T>& other)
{
*this = other;
}
//! Constructor from other string types
- template <class B, class A>
- string(const string<B, A>& other)
- : array(0), allocated(0), used(0)
+ template <class B>
+ string(const string<B>& other)
{
*this = other;
}
@@ -89,198 +81,57 @@ public: //! Constructs a string from a float
explicit string(const double number)
- : array(0), allocated(0), used(0)
{
- c8 tmpbuf[255];
- snprintf_irr(tmpbuf, 255, "%0.6f", number);
- *this = tmpbuf;
+ c8 tmpbuf[32];
+ snprintf_irr(tmpbuf, sizeof(tmpbuf), "%0.6f", number);
+ str = tmpbuf;
}
//! Constructs a string from an int
explicit string(int number)
- : array(0), allocated(0), used(0)
{
- // store if negative and make positive
-
- bool negative = false;
- if (number < 0)
- {
- number *= -1;
- negative = true;
- }
-
- // temporary buffer for 16 numbers
-
- c8 tmpbuf[16]={0};
- u32 idx = 15;
-
- // special case '0'
-
- if (!number)
- {
- tmpbuf[14] = '0';
- *this = &tmpbuf[14];
- return;
- }
-
- // add numbers
-
- while(number && idx)
- {
- --idx;
- tmpbuf[idx] = (c8)('0' + (number % 10));
- number /= 10;
- }
-
- // add sign
-
- if (negative)
- {
- --idx;
- tmpbuf[idx] = '-';
- }
-
- *this = &tmpbuf[idx];
+ str = std::to_string(number);
}
//! Constructs a string from an unsigned int
explicit string(unsigned int number)
- : array(0), allocated(0), used(0)
{
- // temporary buffer for 16 numbers
-
- c8 tmpbuf[16]={0};
- u32 idx = 15;
-
- // special case '0'
-
- if (!number)
- {
- tmpbuf[14] = '0';
- *this = &tmpbuf[14];
- return;
- }
-
- // add numbers
-
- while(number && idx)
- {
- --idx;
- tmpbuf[idx] = (c8)('0' + (number % 10));
- number /= 10;
- }
-
- *this = &tmpbuf[idx];
+ str = std::to_string(number);
}
//! Constructs a string from a long
explicit string(long number)
- : array(0), allocated(0), used(0)
{
- // store if negative and make positive
-
- bool negative = false;
- if (number < 0)
- {
- number *= -1;
- negative = true;
- }
-
- // temporary buffer for 16 numbers
-
- c8 tmpbuf[16]={0};
- u32 idx = 15;
-
- // special case '0'
-
- if (!number)
- {
- tmpbuf[14] = '0';
- *this = &tmpbuf[14];
- return;
- }
-
- // add numbers
-
- while(number && idx)
- {
- --idx;
- tmpbuf[idx] = (c8)('0' + (number % 10));
- number /= 10;
- }
-
- // add sign
-
- if (negative)
- {
- --idx;
- tmpbuf[idx] = '-';
- }
-
- *this = &tmpbuf[idx];
+ str = std::to_string(number);
}
//! Constructs a string from an unsigned long
explicit string(unsigned long number)
- : array(0), allocated(0), used(0)
{
- // temporary buffer for 16 numbers
-
- c8 tmpbuf[16]={0};
- u32 idx = 15;
-
- // special case '0'
-
- if (!number)
- {
- tmpbuf[14] = '0';
- *this = &tmpbuf[14];
- return;
- }
-
- // add numbers
-
- while(number && idx)
- {
- --idx;
- tmpbuf[idx] = (c8)('0' + (number % 10));
- number /= 10;
- }
-
- *this = &tmpbuf[idx];
+ str = std::to_string(number);
}
//! Constructor for copying a string from a pointer with a given length
template <class B>
string(const B* const c, u32 length)
- : array(0), allocated(0), used(0)
{
if (!c)
- {
- // correctly init the string to an empty one
- *this="";
return;
- }
-
- allocated = used = length+1;
- array = allocator.allocate(used); // new T[used];
+ str.resize(length);
for (u32 l = 0; l<length; ++l)
- array[l] = (T)c[l];
-
- array[length] = 0;
+ str[l] = (T)c[l];
}
//! Constructor for Unicode and ASCII strings
template <class B>
string(const B* const c)
- : array(0), allocated(0), used(0)
{
*this = c;
}
@@ -288,35 +139,22 @@ public: //! Destructor
~string()
- {
- allocator.deallocate(array); // delete [] array;
- }
+ {}
//! Assignment operator
- string<T,TAlloc>& operator=(const string<T,TAlloc>& other)
+ string<T>& operator=(const string<T>& other)
{
if (this == &other)
return *this;
- used = other.size()+1;
- if (used>allocated)
- {
- allocator.deallocate(array); // delete [] array;
- allocated = used;
- array = allocator.allocate(used); //new T[used];
- }
-
- const T* p = other.c_str();
- for (u32 i=0; i<used; ++i, ++p)
- array[i] = *p;
-
+ str = other.str;
return *this;
}
//! Assignment operator for other string types
- template <class B, class A>
- string<T,TAlloc>& operator=(const string<B,A>& other)
+ template <class B>
+ string<T>& operator=(const string<B>& other)
{
*this = other.c_str();
return *this;
@@ -325,137 +163,93 @@ public: //! Assignment operator for strings, ASCII and Unicode
template <class B>
- string<T,TAlloc>& operator=(const B* const c)
+ string<T>& operator=(const B* const c)
{
if (!c)
{
- if (!array)
- {
- array = allocator.allocate(1); //new T[1];
- allocated = 1;
- }
- used = 1;
- array[0] = 0x0;
+ clear();
return *this;
}
- if ((void*)c == (void*)array)
- return *this;
-
- u32 len = 0;
- const B* p = c;
- do
- {
- ++len;
- } while(*p++);
-
- // we'll keep the old string for a while, because the new
- // string could be a part of the current string.
- T* oldArray = array;
-
- used = len;
- if (used>allocated)
- {
- allocated = used;
- array = allocator.allocate(used); //new T[used];
- }
+ // no longer allowed!
+ _IRR_DEBUG_BREAK_IF((void*)c == (void*)c_str());
+ u32 len = calclen(c);
+ str.resize(len);
for (u32 l = 0; l<len; ++l)
- array[l] = (T)c[l];
-
- if (oldArray != array)
- allocator.deallocate(oldArray); // delete [] oldArray;
+ str[l] = (T)c[l];
return *this;
}
//! Append operator for other strings
- string<T,TAlloc> operator+(const string<T,TAlloc>& other) const
+ string<T> operator+(const string<T>& other) const
{
- string<T,TAlloc> str(*this);
- str.append(other);
+ string<T> tmp(*this);
+ tmp.append(other);
- return str;
+ return tmp;
}
//! Append operator for strings, ASCII and Unicode
template <class B>
- string<T,TAlloc> operator+(const B* const c) const
+ string<T> operator+(const B* const c) const
{
- string<T,TAlloc> str(*this);
- str.append(c);
+ string<T> tmp(*this);
+ tmp.append(c);
- return str;
+ return tmp;
}
//! Direct access operator
T& operator [](const u32 index)
{
- _IRR_DEBUG_BREAK_IF(index>=used) // bad index
- return array[index];
+ return str[index];
}
//! Direct access operator
const T& operator [](const u32 index) const
{
- _IRR_DEBUG_BREAK_IF(index>=used) // bad index
- return array[index];
+ return str[index];
}
//! Equality operator
- bool operator==(const T* const str) const
+ bool operator==(const T* const other) const
{
- if (!str)
+ if (!other)
return false;
-
- u32 i;
- for (i=0; array[i] && str[i]; ++i)
- if (array[i] != str[i])
- return false;
-
- return (!array[i] && !str[i]);
+ return !cmp(c_str(), other);
}
//! Equality operator
- bool operator==(const string<T,TAlloc>& other) const
+ bool operator==(const string<T>& other) const
{
- for (u32 i=0; array[i] && other.array[i]; ++i)
- if (array[i] != other.array[i])
- return false;
-
- return used == other.used;
+ return str == other.str;
}
//! Is smaller comparator
- bool operator<(const string<T,TAlloc>& other) const
+ bool operator<(const string<T>& other) const
{
- for (u32 i=0; array[i] && other.array[i]; ++i)
- {
- const s32 diff = array[i] - other.array[i];
- if (diff)
- return (diff < 0);
- }
-
- return (used < other.used);
+ return str < other.str;
}
//! Inequality operator
- bool operator!=(const T* const str) const
+ bool operator!=(const T* const other) const
{
- return !(*this == str);
+ return !(*this == other);
}
//! Inequality operator
- bool operator!=(const string<T,TAlloc>& other) const
+ bool operator!=(const string<T>& other) const
{
return !(*this == other);
}
@@ -466,48 +260,50 @@ public: the trailing NUL. */
u32 size() const
{
- return used-1;
+ return str.size();
}
//! Informs if the string is empty or not.
//! \return True if the string is empty, false if not.
bool empty() const
{
- return (size() == 0);
+ return str.empty();
}
void clear(bool releaseMemory=true)
{
- if ( releaseMemory )
- {
- reallocate(1);
+ if (releaseMemory) {
+ stl_type empty;
+ std::swap(str, empty);
+ } else {
+ str.clear();
}
- array[0] = 0;
- used = 1;
}
//! Returns character string
/** \return pointer to C-style NUL terminated string. */
const T* c_str() const
{
- return array;
+ return str.c_str();
}
//! Makes the string lower case.
- string<T,TAlloc>& make_lower()
+ string<T>& make_lower()
{
- for (u32 i=0; array[i]; ++i)
- array[i] = locale_lower ( array[i] );
+ std::transform(str.begin(), str.end(), str.begin(), [](const T& c) {
+ return locale_lower(c);
+ });
return *this;
}
//! Makes the string upper case.
- string<T,TAlloc>& make_upper()
+ string<T>& make_upper()
{
- for (u32 i=0; array[i]; ++i)
- array[i] = locale_upper ( array[i] );
+ std::transform(str.begin(), str.end(), str.begin(), [](const T& c) {
+ return locale_upper(c);
+ });
return *this;
}
@@ -515,27 +311,29 @@ public: //! Compares the strings ignoring case.
/** \param other: Other string to compare.
\return True if the strings are equal ignoring case. */
- bool equals_ignore_case(const string<T,TAlloc>& other) const
+ bool equals_ignore_case(const string<T>& other) const
{
+ const T* array = c_str();
for(u32 i=0; array[i] && other[i]; ++i)
- if (locale_lower( array[i]) != locale_lower(other[i]))
+ if (locale_lower(array[i]) != locale_lower(other[i]))
return false;
- return used == other.used;
+ return size() == other.size();
}
//! Compares the strings ignoring case.
/** \param other: Other string to compare.
\param sourcePos: where to start to compare in the string
\return True if the strings are equal ignoring case. */
- bool equals_substring_ignore_case(const string<T,TAlloc>&other, const s32 sourcePos = 0 ) const
+ bool equals_substring_ignore_case(const string<T>&other, const u32 sourcePos = 0 ) const
{
- if ( (u32) sourcePos >= used )
+ if ( sourcePos >= size() + 1 )
return false;
+ const T* array = c_str();
u32 i;
- for( i=0; array[sourcePos + i] && other[i]; ++i)
- if (locale_lower( array[sourcePos + i]) != locale_lower(other[i]))
+ for(i=0; array[sourcePos + i] && other[i]; ++i)
+ if (locale_lower(array[sourcePos + i]) != locale_lower(other[i]))
return false;
return array[sourcePos + i] == 0 && other[i] == 0;
@@ -545,16 +343,17 @@ public: //! Compares the strings ignoring case.
/** \param other: Other string to compare.
\return True if this string is smaller ignoring case. */
- bool lower_ignore_case(const string<T,TAlloc>& other) const
+ bool lower_ignore_case(const string<T>& other) const
{
- for(u32 i=0; array[i] && other.array[i]; ++i)
+ const T* array = c_str();
+ for(u32 i=0; array[i] && other[i]; ++i)
{
- s32 diff = (s32) locale_lower ( array[i] ) - (s32) locale_lower ( other.array[i] );
+ s32 diff = (s32) locale_lower ( array[i] ) - (s32) locale_lower ( other[i] );
if ( diff )
return diff < 0;
}
- return used < other.used;
+ return size() < other.size();
}
@@ -562,8 +361,9 @@ public: /** \param other Other string to compare.
\param n Number of characters to compare
\return True if the n first characters of both strings are equal. */
- bool equalsn(const string<T,TAlloc>& other, u32 n) const
+ bool equalsn(const string<T>& other, u32 n) const
{
+ const T* array = c_str();
u32 i;
for(i=0; i < n && array[i] && other[i]; ++i)
if (array[i] != other[i])
@@ -571,7 +371,7 @@ public: // if one (or both) of the strings was smaller then they
// are only equal if they have the same length
- return (i == n) || (used == other.used);
+ return (i == n) || (size() == other.size());
}
@@ -579,33 +379,27 @@ public: /** \param str Other string to compare.
\param n Number of characters to compare
\return True if the n first characters of both strings are equal. */
- bool equalsn(const T* const str, u32 n) const
+ bool equalsn(const T* const other, u32 n) const
{
- if (!str)
+ if (!other)
return false;
+ const T* array = c_str();
u32 i;
- for(i=0; i < n && array[i] && str[i]; ++i)
- if (array[i] != str[i])
+ for(i=0; i < n && array[i] && other[i]; ++i)
+ if (array[i] != other[i])
return false;
// if one (or both) of the strings was smaller then they
// are only equal if they have the same length
- return (i == n) || (array[i] == 0 && str[i] == 0);
+ return (i == n) || (array[i] == 0 && other[i] == 0);
}
//! Appends a character to this string
/** \param character: Character to append. */
- string<T,TAlloc>& append(T character)
+ string<T>& append(T character)
{
- if (used + 1 > allocated)
- reallocate(used + 1);
-
- ++used;
-
- array[used-2] = character;
- array[used-1] = 0;
-
+ str.append(1, character);
return *this;
}
@@ -613,55 +407,25 @@ public: //! Appends a char string to this string
/** \param other: Char string to append. */
/** \param length: The length of the string to append. */
- string<T,TAlloc>& append(const T* const other, u32 length=0xffffffff)
+ string<T>& append(const T* const other, u32 length=0xffffffff)
{
if (!other)
return *this;
- u32 len = 0;
- const T* p = other;
- while(*p)
- {
- ++len;
- ++p;
- }
+ u32 len = calclen(other);
if (len > length)
len = length;
- if (used + len > allocated)
- reallocate(used + len);
-
- --used;
- ++len;
-
- for (u32 l=0; l<len; ++l)
- array[l+used] = *(other+l);
-
- used += len;
- array[used-1] = 0;
-
+ str.append(other, len);
return *this;
}
//! Appends a string to this string
/** \param other: String to append. */
- string<T,TAlloc>& append(const string<T,TAlloc>& other)
+ string<T>& append(const string<T>& other)
{
- if (other.size() == 0)
- return *this;
-
- --used;
- const u32 len = other.size()+1;
-
- if (used + len > allocated)
- reallocate(used + len);
-
- for (u32 l=0; l<len; ++l)
- array[used+l] = other[l];
-
- used += len;
-
+ str.append(other.str);
return *this;
}
@@ -669,30 +433,12 @@ public: //! Appends a string of the length l to this string.
/** \param other: other String to append to this string.
\param length: How much characters of the other string to add to this one. */
- string<T,TAlloc>& append(const string<T,TAlloc>& other, u32 length)
+ string<T>& append(const string<T>& other, u32 length)
{
- if (other.size() == 0)
- return *this;
-
if (other.size() < length)
- {
append(other);
- return *this;
- }
-
- if (used + length > allocated)
- reallocate(used + length);
-
- --used;
-
- for (u32 l=0; l<length; ++l)
- array[l+used] = other[l];
- used += length;
-
- // ensure proper termination
- array[used]=0;
- ++used;
-
+ else
+ str.append(other.c_str(), length);
return *this;
}
@@ -700,37 +446,24 @@ public: //\param pos Insert the characters before this index
//\param s String to insert. Must be at least of size n
//\param n Number of characters from string s to use.
- string<T,TAlloc>& insert(u32 pos, const char* s, u32 n)
+ string<T>& insert(u32 pos, const T* s, u32 n)
{
- if ( pos < used )
+ if ( pos < size()+1 )
{
- reserve(used+n);
-
- // move stuff behind insert point
- const u32 end = used+n-1;
- for (u32 i=0; i<used-pos; ++i)
- {
- array[end-i] = array[end-(i+n)];
- }
- used += n;
-
- for (u32 i=0; i<n; ++i)
- {
- array[pos+i] = s[i];
- }
+ str.insert(pos, s, n);
}
return *this;
}
//! Reserves some memory.
- /** \param count: Amount of characters to reserve. */
+ /** \param count: Amount of characters to reserve, including
+ the trailing NUL. */
void reserve(u32 count)
{
- if (count < allocated)
+ if (count == 0)
return;
-
- reallocate(count);
+ str.reserve(count - 1);
}
@@ -740,11 +473,8 @@ public: or -1 if not found. */
s32 findFirst(T c) const
{
- for (u32 i=0; i<used-1; ++i)
- if (array[i] == c)
- return i;
-
- return -1;
+ auto r = str.find(c);
+ return pos_from_stl(r);
}
//! finds first occurrence of a character of a list in string
@@ -759,12 +489,8 @@ public: if (!c || !count)
return -1;
- for (u32 i=0; i<used-1; ++i)
- for (u32 j=0; j<count; ++j)
- if (array[i] == c[j])
- return i;
-
- return -1;
+ auto r = str.find_first_of(c, 0, count);
+ return pos_from_stl(r);
}
@@ -775,24 +501,13 @@ public: this should be strlen(c)
\return Position where the character has been found,
or -1 if not found. */
- template <class B>
- s32 findFirstCharNotInList(const B* const c, u32 count=1) const
+ s32 findFirstCharNotInList(const T* const c, u32 count=1) const
{
if (!c || !count)
return -1;
- for (u32 i=0; i<used-1; ++i)
- {
- u32 j;
- for (j=0; j<count; ++j)
- if (array[i] == c[j])
- break;
-
- if (j==count)
- return i;
- }
-
- return -1;
+ auto r = str.find_first_not_of(c, 0, count);
+ return pos_from_stl(r);
}
//! Finds last position of a character not in a given list.
@@ -802,24 +517,13 @@ public: this should be strlen(c)
\return Position where the character has been found,
or -1 if not found. */
- template <class B>
- s32 findLastCharNotInList(const B* const c, u32 count=1) const
+ s32 findLastCharNotInList(const T* const c, u32 count=1) const
{
if (!c || !count)
return -1;
- for (s32 i=(s32)(used-2); i>=0; --i)
- {
- u32 j;
- for (j=0; j<count; ++j)
- if (array[i] == c[j])
- break;
-
- if (j==count)
- return i;
- }
-
- return -1;
+ auto r = str.find_last_not_of(c, npos, count);
+ return pos_from_stl(r);
}
//! finds next occurrence of character in string
@@ -829,11 +533,8 @@ public: or -1 if not found. */
s32 findNext(T c, u32 startPos) const
{
- for (u32 i=startPos; i<used-1; ++i)
- if (array[i] == c)
- return i;
-
- return -1;
+ auto r = str.find(c, startPos);
+ return pos_from_stl(r);
}
@@ -844,12 +545,8 @@ public: or -1 if not found. */
s32 findLast(T c, s32 start = -1) const
{
- start = core::clamp ( start < 0 ? (s32)(used) - 2 : start, 0, (s32)(used) - 2 );
- for (s32 i=start; i>=0; --i)
- if (array[i] == c)
- return i;
-
- return -1;
+ auto r = str.rfind(c, pos_to_stl(start));
+ return pos_from_stl(r);
}
//! finds last occurrence of a character of a list in string
@@ -864,12 +561,8 @@ public: if (!c || !count)
return -1;
- for (s32 i=(s32)used-2; i>=0; --i)
- for (u32 j=0; j<count; ++j)
- if (array[i] == c[j])
- return i;
-
- return -1;
+ auto r = str.find_last_of(c, npos, count);
+ return pos_from_stl(r);
}
@@ -878,29 +571,12 @@ public: \param start: Start position of the search
\return Positions where the string has been found,
or -1 if not found. */
- template <class B>
- s32 find(const B* const str, const u32 start = 0) const
+ s32 find(const T* const other, const u32 start = 0) const
{
- if (str && *str)
+ if (other && *other)
{
- u32 len = 0;
-
- while (str[len])
- ++len;
-
- if (len > used-1)
- return -1;
-
- for (u32 i=start; i<used-len; ++i)
- {
- u32 j=0;
-
- while(str[j] && array[i+j] == str[j])
- ++j;
-
- if (!str[j])
- return i;
- }
+ auto r = str.find(other, start);
+ return pos_from_stl(r);
}
return -1;
@@ -917,36 +593,17 @@ public: // or no proper substring length
if ((length <= 0) || (begin>=size()))
return string<T>("");
- // clamp length to maximal value
- if ((length+begin) > size())
- length = size()-begin;
-
- // accounting for null terminator.
- s32 substrAllocLength = length + 1;
- string<T> o;
- o.reserve(substrAllocLength);
-
- if ( !make_lower )
- {
- for (s32 i=0; i<length; ++i)
- o.array[i] = array[i+begin];
- }
- else
- {
- for (s32 i=0; i<length; ++i)
- o.array[i] = locale_lower ( array[i+begin] );
- }
-
- o.array[substrAllocLength - 1] = 0;
- o.used = length + 1;
+ string<T> o = str.substr(begin, length);
+ if (make_lower)
+ o.make_lower();
return o;
}
//! Appends a character to this string
/** \param c Character to append. */
- string<T,TAlloc>& operator += (T c)
+ string<T>& operator += (T c)
{
append(c);
return *this;
@@ -955,7 +612,7 @@ public: //! Appends a char string to this string
/** \param c Char string to append. */
- string<T,TAlloc>& operator += (const T* const c)
+ string<T>& operator += (const T* const c)
{
append(c);
return *this;
@@ -964,7 +621,7 @@ public: //! Appends a string to this string
/** \param other String to append. */
- string<T,TAlloc>& operator += (const string<T,TAlloc>& other)
+ string<T>& operator += (const string<T>& other)
{
append(other);
return *this;
@@ -973,54 +630,54 @@ public: //! Appends a string representation of a number to this string
/** \param i Number to append. */
- string<T,TAlloc>& operator += (const int i)
+ string<T>& operator += (const int i)
{
- append(string<T,TAlloc>(i));
+ append(string<T>(i));
return *this;
}
//! Appends a string representation of a number to this string
/** \param i Number to append. */
- string<T,TAlloc>& operator += (const unsigned int i)
+ string<T>& operator += (const unsigned int i)
{
- append(string<T,TAlloc>(i));
+ append(string<T>(i));
return *this;
}
//! Appends a string representation of a number to this string
/** \param i Number to append. */
- string<T,TAlloc>& operator += (const long i)
+ string<T>& operator += (const long i)
{
- append(string<T,TAlloc>(i));
+ append(string<T>(i));
return *this;
}
//! Appends a string representation of a number to this string
/** \param i Number to append. */
- string<T,TAlloc>& operator += (const unsigned long i)
+ string<T>& operator += (const unsigned long i)
{
- append(string<T,TAlloc>(i));
+ append(string<T>(i));
return *this;
}
//! Appends a string representation of a number to this string
/** \param i Number to append. */
- string<T,TAlloc>& operator += (const double i)
+ string<T>& operator += (const double i)
{
- append(string<T,TAlloc>(i));
+ append(string<T>(i));
return *this;
}
//! Appends a string representation of a number to this string
/** \param i Number to append. */
- string<T,TAlloc>& operator += (const float i)
+ string<T>& operator += (const float i)
{
- append(string<T,TAlloc>(i));
+ append(string<T>(i));
return *this;
}
@@ -1028,11 +685,9 @@ public: //! Replaces all characters of a special type with another one
/** \param toReplace Character to replace.
\param replaceWith Character replacing the old one. */
- string<T,TAlloc>& replace(T toReplace, T replaceWith)
+ string<T>& replace(T toReplace, T replaceWith)
{
- for (u32 i=0; i<used-1; ++i)
- if (array[i] == toReplace)
- array[i] = replaceWith;
+ std::replace(str.begin(), str.end(), toReplace, replaceWith);
return *this;
}
@@ -1040,149 +695,42 @@ public: //! Replaces all instances of a string with another one.
/** \param toReplace The string to replace.
\param replaceWith The string replacing the old one. */
- string<T,TAlloc>& replace(const string<T,TAlloc>& toReplace, const string<T,TAlloc>& replaceWith)
+ string<T>& replace(const string<T>& toReplace, const string<T>& replaceWith)
{
- if (toReplace.size() == 0)
- return *this;
-
- const T* other = toReplace.c_str();
- const T* replace = replaceWith.c_str();
- const u32 other_size = toReplace.size();
- const u32 replace_size = replaceWith.size();
-
- // Determine the delta. The algorithm will change depending on the delta.
- s32 delta = replace_size - other_size;
-
- // A character for character replace. The string will not shrink or grow.
- if (delta == 0)
- {
- s32 pos = 0;
- while ((pos = find(other, pos)) != -1)
- {
- for (u32 i = 0; i < replace_size; ++i)
- array[pos + i] = replace[i];
- ++pos;
- }
- return *this;
- }
-
- // We are going to be removing some characters. The string will shrink.
- if (delta < 0)
- {
- u32 i = 0;
- for (u32 pos = 0; pos < used; ++i, ++pos)
- {
- // Is this potentially a match?
- if (array[pos] == *other)
- {
- // Check to see if we have a match.
- u32 j;
- for (j = 0; j < other_size; ++j)
- {
- if (array[pos + j] != other[j])
- break;
- }
-
- // If we have a match, replace characters.
- if (j == other_size)
- {
- for (j = 0; j < replace_size; ++j)
- array[i + j] = replace[j];
- i += replace_size - 1;
- pos += other_size - 1;
- continue;
- }
- }
-
- // No match found, just copy characters.
- array[i] = array[pos];
- }
- array[i-1] = 0;
- used = i;
-
- return *this;
- }
-
- // We are going to be adding characters, so the string size will increase.
- // Count the number of times toReplace exists in the string so we can allocate the new size.
- u32 find_count = 0;
- s32 pos = 0;
- while ((pos = find(other, pos)) != -1)
- {
- ++find_count;
- ++pos;
- }
-
- // Re-allocate the string now, if needed.
- u32 len = delta * find_count;
- if (used + len > allocated)
- reallocate(used + len);
-
- // Start replacing.
- pos = 0;
- while ((pos = find(other, pos)) != -1)
- {
- T* start = array + pos + other_size - 1;
- T* ptr = array + used - 1;
- T* end = array + delta + used -1;
-
- // Shift characters to make room for the string.
- while (ptr != start)
- {
- *end = *ptr;
- --ptr;
- --end;
- }
-
- // Add the new string now.
- for (u32 i = 0; i < replace_size; ++i)
- array[pos + i] = replace[i];
-
- pos += replace_size;
- used += delta;
- }
+ size_type pos = 0;
+ while ((pos = str.find(toReplace.str, pos)) != npos) {
+ str.replace(pos, toReplace.size(), replaceWith.str);
+ pos += replaceWith.size();
+ }
return *this;
}
- //! Removes characters from a string.
+ //! Removes a character from a string.
/** \param c: Character to remove. */
- string<T,TAlloc>& remove(T c)
+ string<T>& remove(T c)
{
- u32 pos = 0;
- u32 found = 0;
- for (u32 i=0; i<used-1; ++i)
- {
- if (array[i] == c)
- {
- ++found;
- continue;
- }
-
- array[pos++] = array[i];
- }
- used -= found;
- array[used-1] = 0;
+ str.erase(std::remove(str.begin(), str.end(), c), str.end());
return *this;
}
//! Removes a string from the string.
/** \param toRemove: String to remove. */
- string<T,TAlloc>& remove(const string<T,TAlloc>& toRemove)
+ string<T>& remove(const string<T>& toRemove)
{
u32 size = toRemove.size();
if ( size == 0 )
return *this;
u32 pos = 0;
u32 found = 0;
- for (u32 i=0; i<used-1; ++i)
+ for (u32 i=0; i<str.size(); ++i)
{
u32 j = 0;
while (j < size)
{
- if (array[i + j] != toRemove[j])
+ if (str[i + j] != toRemove[j])
break;
++j;
}
@@ -1193,45 +741,22 @@ public: continue;
}
- array[pos++] = array[i];
+ str[pos++] = str[i];
}
- used -= found;
- array[used-1] = 0;
+ str.resize(str.size() - found);
return *this;
}
//! Removes characters from a string.
/** \param characters: Characters to remove. */
- string<T,TAlloc>& removeChars(const string<T,TAlloc> & characters)
+ string<T>& removeChars(const string<T> & characters)
{
if (characters.size() == 0)
return *this;
- u32 pos = 0;
- u32 found = 0;
- for (u32 i=0; i<used-1; ++i)
- {
- // Don't use characters.findFirst as it finds the \0,
- // causing used to become incorrect.
- bool docontinue = false;
- for (u32 j=0; j<characters.size(); ++j)
- {
- if (characters[j] == array[i])
- {
- ++found;
- docontinue = true;
- break;
- }
- }
- if (docontinue)
- continue;
-
- array[pos++] = array[i];
- }
- used -= found;
- array[used-1] = 0;
-
+ for (u32 i = 0; i < characters.size(); i++)
+ remove(characters[i]);
return *this;
}
@@ -1239,94 +764,35 @@ public: //! Trims the string.
/** Removes the specified characters (by default, Latin-1 whitespace)
from the beginning and the end of the string. */
- string<T,TAlloc>& trim(const string<T,TAlloc> & whitespace = " \t\n\r")
+ string<T>& trim(const string<T> & whitespace = " \t\n\r")
{
// find start and end of the substring without the specified characters
- const s32 begin = findFirstCharNotInList(whitespace.c_str(), whitespace.used);
+ const s32 begin = findFirstCharNotInList(whitespace.c_str(), whitespace.size());
if (begin == -1)
return (*this="");
- const s32 end = findLastCharNotInList(whitespace.c_str(), whitespace.used);
+ const s32 end = findLastCharNotInList(whitespace.c_str(), whitespace.size());
return (*this = subString(begin, (end +1) - begin));
}
-#if 0
- //! Erase 0's at the end when a string ends with a floating point number
- /** After generating strings from floats we often end up with strings
- ending up with lots of zeros which don't add any value. Erase 'em all.
- Examples: "0.100000" becomes "0.1"
- "10.000000" becomes "10"
- "foo 3.140000" becomes "foo 3.14"
- "no_num.000" stays "no_num.000"
- "1." stays "1."
- */
- string<T,TAlloc>& eraseTrailingFloatZeros(char decimalPoint='.')
- {
- s32 i=findLastCharNotInList("0", 1);
- if ( i > 0 && (u32)i < used-2 ) // non 0 must be found and not last char (also used is at least 2 when i > 0)
- {
- u32 eraseStart=i+1;
- u32 dot=0;
- if( core::isdigit(array[i]) )
- {
- while( --i>0 && core::isdigit(array[i]) );
- if ( array[i] == decimalPoint )
- dot = i;
- }
- else if ( array[i] == decimalPoint )
- {
- dot = i;
- eraseStart = i;
- }
- if ( dot > 0 && core::isdigit(array[dot-1]) )
- {
- array[eraseStart] = 0;
- used = eraseStart+1;
- }
- }
- return *this;
- }
-#endif
-
//! Erases a character from the string.
/** May be slow, because all elements
following after the erased element have to be copied.
\param index: Index of element to be erased. */
- string<T,TAlloc>& erase(u32 index)
+ string<T>& erase(u32 index)
{
- _IRR_DEBUG_BREAK_IF(index>=used) // access violation
-
- for (u32 i=index+1; i<used; ++i)
- array[i-1] = array[i];
-
- --used;
+ str.erase(str.begin() + index);
return *this;
}
//! verify the existing string.
- string<T,TAlloc>& validate()
+ string<T>& validate()
{
- // terminate on existing null
- for (u32 i=0; i<allocated; ++i)
- {
- if (array[i] == 0)
- {
- used = i + 1;
- return *this;
- }
- }
-
- // terminate
- if ( allocated > 0 )
- {
- used = allocated;
- array[used-1] = 0;
- }
- else
- {
- used = 0;
- }
+ // truncate to existing null
+ u32 len = calclen(c_str());
+ if (len != size())
+ str.resize(len);
return *this;
}
@@ -1334,7 +800,7 @@ public: //! gets the last char of a string or null
T lastChar() const
{
- return used > 1 ? array[used-2] : 0;
+ return !str.empty() ? str.back() : 0;
}
//! Split string into parts (tokens).
@@ -1365,19 +831,19 @@ public: const u32 oldSize=ret.size();
u32 tokenStartIdx = 0;
- for (u32 i=0; i<used; ++i)
+ for (u32 i=0; i<size()+1; ++i)
{
for (u32 j=0; j<countDelimiters; ++j)
{
- if (array[i] == delimiter[j])
+ if (str[i] == delimiter[j])
{
if (i - tokenStartIdx > 0)
- ret.push_back(string<T,TAlloc>(&array[tokenStartIdx], i - tokenStartIdx));
+ ret.push_back(string<T>(&str[tokenStartIdx], i - tokenStartIdx));
else if ( !ignoreEmptyTokens )
- ret.push_back(string<T,TAlloc>());
+ ret.push_back(string<T>());
if ( keepSeparators )
{
- ret.push_back(string<T,TAlloc>(&array[i], 1));
+ ret.push_back(string<T>(&str[i], 1));
}
tokenStartIdx = i+1;
@@ -1385,10 +851,10 @@ public: }
}
}
- if ((used - 1) > tokenStartIdx)
- ret.push_back(string<T,TAlloc>(&array[tokenStartIdx], (used - 1) - tokenStartIdx));
- else if ( !ignoreEmptyTokens )
- ret.push_back(string<T,TAlloc>());
+ if (size() > tokenStartIdx)
+ ret.push_back(string<T>(&str[tokenStartIdx], size() - tokenStartIdx));
+ else if (!ignoreEmptyTokens)
+ ret.push_back(string<T>());
return ret.size()-oldSize;
}
@@ -1398,30 +864,52 @@ public: private:
- //! Reallocate the array, make it bigger or smaller
- void reallocate(u32 new_size)
- {
- T* old_array = array;
-
- array = allocator.allocate(new_size); //new T[new_size];
- allocated = new_size;
+ typedef std::basic_string<T> stl_type;
- const u32 amount = used < new_size ? used : new_size;
- for (u32 i=0; i<amount; ++i)
- array[i] = old_array[i];
+ //! Private constructor
+ string(stl_type &&str) : str(str)
+ {}
- if (allocated < used)
- used = allocated;
+ //! strlen wrapper
+ template <typename U>
+ static inline u32 calclen(const U* p) {
+ u32 len = 0;
+ while (*p++)
+ len++;
+ return len;
+ }
+ static inline u32 calclen(const char* p) {
+ return strlen(p);
+ }
+ static inline u32 calclen(const wchar_t* p) {
+ return wcslen(p);
+ }
- allocator.deallocate(old_array); // delete [] old_array;
+ //! strcmp wrapper
+ template <typename U>
+ static inline int cmp(const U* p, const U* p2) {
+ while (*p && *p == *p2)
+ p++, p2++;
+ return (int)*p - (int)*p2;
+ }
+ static inline int cmp(const char* p, const char* p2) {
+ return strcmp(p, p2);
}
+ static inline int cmp(const wchar_t* p, const wchar_t* p2) {
+ return wcscmp(p, p2);
+ }
+
+ typedef typename stl_type::size_type size_type;
+ static const size_type npos = stl_type::npos;
- //--- member variables
+ static inline s32 pos_from_stl(size_type pos) {
+ return pos == npos ? -1 : (s32)pos;
+ }
+ static inline size_type pos_to_stl(s32 pos) {
+ return pos == -1 ? npos : (size_type)pos;
+ }
- T* array;
- u32 allocated;
- u32 used;
- TAlloc allocator;
+ stl_type str;
};
@@ -1459,19 +947,18 @@ static size_t multibyteToWString(string<wchar_t>& destination, const char* sourc {
if ( sourceSize )
{
- destination.reserve(sourceSize+1);
+ destination.str.resize(sourceSize+1);
#if defined(_MSC_VER)
#pragma warning(push)
#pragma warning(disable: 4996) // 'mbstowcs': This function or variable may be unsafe. Consider using mbstowcs_s instead.
#endif
- const size_t written = mbstowcs(destination.array, source, (size_t)sourceSize);
+ const size_t written = mbstowcs(&destination[0], source, (size_t)sourceSize);
#if defined(_MSC_VER)
#pragma warning(pop)
#endif
if ( written != (size_t)-1 )
{
- destination.used = (u32)written+1;
- destination.array[destination.used-1] = 0;
+ destination.str.resize(written);
}
else
{
@@ -1506,19 +993,18 @@ static size_t wStringToMultibyte(string<c8>& destination, const wchar_t* source, {
if ( sourceSize )
{
- destination.reserve(sizeof(wchar_t)*sourceSize+1);
+ destination.str.resize(sizeof(wchar_t)*sourceSize+1);
#if defined(_MSC_VER)
#pragma warning(push)
#pragma warning(disable: 4996) // 'wcstombs': This function or variable may be unsafe. Consider using wcstombs_s instead.
#endif
- const size_t written = wcstombs(destination.array, source, destination.allocated-1);
+ const size_t written = wcstombs(&destination[0], source, destination.size());
#if defined(_MSC_VER)
#pragma warning(pop)
#endif
if ( written != (size_t)-1 )
{
- destination.used = (u32)written+1;
- destination.array[destination.used-1] = 0;
+ destination.str.resize(written);
}
else
{
|