FString allocates no new memory if the size sufficient

This commit is contained in:
Markus Gans 2017-04-17 22:49:42 +02:00
parent 0c3668573d
commit a7a11083d5
4 changed files with 120 additions and 49 deletions

View File

@ -1,6 +1,7 @@
2017-04-17 Markus Gans <guru.mail@muenster.de> 2017-04-17 Markus Gans <guru.mail@muenster.de>
* Speed up FString::setNumber() by using a decimal * Speed up FString::setNumber() by using a decimal
string lookup table string lookup table
* FString allocates no new memory if the size sufficient.
2017-04-15 Markus Gans <guru.mail@muenster.de> 2017-04-15 Markus Gans <guru.mail@muenster.de>
* Fix unsigned integer underflow in FString::_insert() * Fix unsigned integer underflow in FString::_insert()

View File

@ -51,7 +51,7 @@ FString::FString (int len, wchar_t c)
, c_string(0) , c_string(0)
{ {
if ( len > 0 ) if ( len > 0 )
_replace ( FString(uInt(len), c).string ); _assign ( FString(uInt(len), c).string );
else else
initLength(0); initLength(0);
} }
@ -87,7 +87,7 @@ FString::FString (int len, char c)
c_string = 0; c_string = 0;
if ( len > 0 ) if ( len > 0 )
_replace ( FString(uInt(len), c).string ); _assign ( FString(uInt(len), c).string );
else else
initLength(0); initLength(0);
} }
@ -118,7 +118,7 @@ FString::FString (const FString& s) // copy constructor
, c_string(0) , c_string(0)
{ {
if ( s.string ) if ( s.string )
_replace (s.string); _assign (s.string);
} }
//---------------------------------------------------------------------- //----------------------------------------------------------------------
@ -129,7 +129,7 @@ FString::FString (const std::wstring& s)
, c_string(0) , c_string(0)
{ {
if ( ! s.empty() ) if ( ! s.empty() )
_replace ( s.c_str() ); _assign ( s.c_str() );
} }
//---------------------------------------------------------------------- //----------------------------------------------------------------------
@ -140,7 +140,7 @@ FString::FString (const wchar_t* s)
, c_string(0) , c_string(0)
{ {
if ( s ) if ( s )
_replace (s); _assign (s);
} }
//---------------------------------------------------------------------- //----------------------------------------------------------------------
@ -158,7 +158,7 @@ FString::FString (const std::string& s)
if ( wc_string ) if ( wc_string )
{ {
_replace( wc_string ); _assign( wc_string );
delete[] wc_string; delete[] wc_string;
} }
} }
@ -175,7 +175,7 @@ FString::FString (const char* s)
if ( wc_string ) if ( wc_string )
{ {
_replace( wc_string ); _assign (wc_string);
delete[] wc_string; delete[] wc_string;
} }
} }
@ -190,7 +190,7 @@ FString::FString (const wchar_t c)
wchar_t s[2]; wchar_t s[2];
s[0] = c; s[0] = c;
s[1] = L'\0'; s[1] = L'\0';
_replace (s); _assign (s);
} }
//---------------------------------------------------------------------- //----------------------------------------------------------------------
@ -203,7 +203,7 @@ FString::FString (const char c)
wchar_t s[2]; wchar_t s[2];
s[0] = wchar_t(c & 0xff); s[0] = wchar_t(c & 0xff);
s[1] = L'\0'; s[1] = L'\0';
_replace (s); _assign (s);
} }
//---------------------------------------------------------------------- //----------------------------------------------------------------------
@ -222,7 +222,7 @@ FString::~FString() // destructor
FString& FString::operator = (const FString& s) FString& FString::operator = (const FString& s)
{ {
if ( s ) if ( s )
_replace (s.string); _assign (s.string);
else else
clear(); clear();
@ -233,7 +233,7 @@ FString& FString::operator = (const FString& s)
FString& FString::operator = (const std::wstring& s) FString& FString::operator = (const std::wstring& s)
{ {
if ( ! s.empty() ) if ( ! s.empty() )
_replace (s.c_str()); _assign (s.c_str());
else else
clear(); clear();
@ -244,7 +244,7 @@ FString& FString::operator = (const std::wstring& s)
const FString& FString::operator = (const wchar_t* s) const FString& FString::operator = (const wchar_t* s)
{ {
if ( s ) if ( s )
_replace (s); _assign (s);
else else
clear(); clear();
@ -258,7 +258,7 @@ FString& FString::operator = (const std::string& s)
if ( wc_string ) if ( wc_string )
{ {
_replace( wc_string ); _assign( wc_string );
delete[] wc_string; delete[] wc_string;
} }
else else
@ -274,7 +274,7 @@ const FString& FString::operator = (const char* s)
if ( wc_string ) if ( wc_string )
{ {
_replace( wc_string ); _assign( wc_string );
delete[] wc_string; delete[] wc_string;
} }
else else
@ -289,7 +289,7 @@ const FString& FString::operator = (const wchar_t c)
wchar_t s[2]; wchar_t s[2];
s[0] = c; s[0] = c;
s[1] = L'\0'; s[1] = L'\0';
_replace (s); _assign (s);
return (*this); return (*this);
} }
@ -299,7 +299,7 @@ const FString& FString::operator = (const char c)
wchar_t s[2]; wchar_t s[2];
s[0] = wchar_t(c & 0xff); s[0] = wchar_t(c & 0xff);
s[1] = L'\0'; s[1] = L'\0';
_replace (s); _assign (s);
return (*this); return (*this);
} }
@ -502,7 +502,7 @@ FString& FString::sprintf (const wchar_t* format, ...)
std::vswprintf (buffer, buf_size, format, args); std::vswprintf (buffer, buf_size, format, args);
va_end (args); va_end (args);
_replace (buffer); _assign (buffer);
return (*this); return (*this);
} }
@ -532,7 +532,7 @@ FString& FString::sprintf (const char* format, ...)
if ( wc_string ) if ( wc_string )
{ {
_replace(wc_string); _assign(wc_string);
delete[] wc_string; delete[] wc_string;
} }
@ -974,7 +974,7 @@ std::vector<FString> FString::split (const FString& delimiter)
//---------------------------------------------------------------------- //----------------------------------------------------------------------
FString& FString::setString (const wchar_t* s) FString& FString::setString (const wchar_t* s)
{ {
_replace (s); _assign (s);
return (*this); return (*this);
} }
@ -985,7 +985,7 @@ FString& FString::setString (const char* s)
if ( wc_string ) if ( wc_string )
{ {
_replace (wc_string); _assign (wc_string);
delete[] wc_string; delete[] wc_string;
} }
@ -1023,7 +1023,7 @@ FString& FString::setNumber (long num)
if ( neg ) if ( neg )
*--s = '-'; *--s = '-';
_replace (s); _assign (s);
return *this; return *this;
} }
@ -1043,7 +1043,7 @@ FString& FString::setNumber (uLong num)
} }
while ( num ); while ( num );
_replace (s); _assign (s);
return *this; return *this;
} }
@ -1113,7 +1113,7 @@ FString& FString::setFormatedNumber (long num, char separator)
if ( neg ) if ( neg )
*--s = '-'; *--s = '-';
_replace (s); _assign (s);
return *this; return *this;
} }
@ -1142,7 +1142,7 @@ FString& FString::setFormatedNumber (uLong num, char separator)
} }
while ( num ); while ( num );
_replace (s); _assign (s);
return *this; return *this;
} }
@ -2212,13 +2212,19 @@ inline void FString::initLength (uInt len)
} }
//---------------------------------------------------------------------- //----------------------------------------------------------------------
inline void FString::_replace (const wchar_t* s) inline void FString::_assign (const wchar_t* s)
{ {
if ( s == string )
return;
uInt new_length = uInt(std::wcslen(s));
if ( ! string || new_length > bufsize - 1 )
{
if ( string ) if ( string )
delete[](string); delete[](string);
length = uInt(std::wcslen(s)); bufsize = FWDBUFFER + new_length + 1;
bufsize = FWDBUFFER + length + 1;
try try
{ {
@ -2229,13 +2235,10 @@ inline void FString::_replace (const wchar_t* s)
std::cerr << bad_alloc_str << ex.what() << std::endl; std::cerr << bad_alloc_str << ex.what() << std::endl;
return; return;
} }
/* catch (std::exception& e) }
{
std::cerr << "not enough memory for a new FString object "
<< e.what() << std::endl;
return;
}*/
std::wcsncpy (string, s, bufsize); std::wcsncpy (string, s, bufsize);
length = new_length;
} }
//---------------------------------------------------------------------- //----------------------------------------------------------------------
@ -2517,7 +2520,7 @@ std::istream& operator >> (std::istream& instr, FString& s)
if ( wc_str ) if ( wc_str )
{ {
s._replace (wc_str); s._assign (wc_str);
delete[] wc_str; delete[] wc_str;
} }
@ -2538,7 +2541,7 @@ std::wistream& operator >> (std::wistream& instr, FString& s)
{ {
wchar_t buf[FString::INPBUFFER + 1]; wchar_t buf[FString::INPBUFFER + 1];
instr.getline (buf, FString::INPBUFFER); instr.getline (buf, FString::INPBUFFER);
s._replace (buf); s._assign (buf);
return (instr); return (instr);
} }

View File

@ -330,7 +330,7 @@ class FString
// Methods // Methods
void initLength (uInt); void initLength (uInt);
void _replace (const wchar_t*); void _assign (const wchar_t*);
void _insert (uInt, uInt, const wchar_t*); void _insert (uInt, uInt, const wchar_t*);
void _remove (uInt, uInt); void _remove (uInt, uInt);
char* wc_to_c_str (const wchar_t*) const; char* wc_to_c_str (const wchar_t*) const;

View File

@ -28,58 +28,96 @@ int main (int, char**)
std::cout << "--------------[ FString test ]-----------------" std::cout << "--------------[ FString test ]-----------------"
<< std::endl; << std::endl;
// Test: input stream (operator >>)
FString in; FString in;
std::cout << " Input: "; std::cin >> in; std::cout << " Input: "; std::cin >> in;
std::cout << " instream >> " << in << std::endl; std::cout << " instream >> " << in << std::endl;
// Test: output stream (operator <<)
FString out = L"A test string for 0 \x20ac"; FString out = L"A test string for 0 \x20ac";
std::cout << " outstream << " << out.c_str() << std::endl; std::cout << " outstream << " << out << std::endl;
// Test: c-string output
printf (" c_str: \"%s\"\n", out.c_str()); printf (" c_str: \"%s\"\n", out.c_str());
// Test: copy a c++ string
FString cpp_str( std::string("c++ String") ); FString cpp_str( std::string("c++ String") );
std::cout << " cpp_str: \"" << cpp_str << "\"" << std::endl; std::cout << " cpp_str: \"" << cpp_str << "\"" << std::endl;
// Test: copy a character
FString ch('c'); FString ch('c');
std::cout << " char: '" << ch << "'" << std::endl; std::cout << " char: '" << ch << "'" << std::endl;
// Test: copy a wide character
FString wch(L'w'); FString wch(L'w');
std::cout << " wchar_t: '" << wch << "'" << std::endl; std::cout << " wchar_t: '" << wch << "'" << std::endl;
// Test: utf-8 string
FString len = "длина́"; FString len = "длина́";
std::cout << " length: \"" << len << "\" has " std::cout << " length: \"" << len << "\" has "
<< len.getLength() << " characters" << std::endl; << len.getLength() << " characters" << std::endl;
// Test: convert uppercase letter to lowercase
FString lower = FString(L"InPut").toLower(); FString lower = FString(L"InPut").toLower();
std::wcout << L" toLower: " << lower << std::endl; std::wcout << L" toLower: " << lower << std::endl;
// Test: convert lowercase letter to uppercase
FString upper = FString("inPut").toUpper(); FString upper = FString("inPut").toUpper();
std::cout << " toUpper: " << upper << std::endl; std::cout << " toUpper: " << upper << std::endl;
// Test: concatenate two FStrings (operator +)
FString add1 = FString("FString + ") + FString("FString"); FString add1 = FString("FString + ") + FString("FString");
std::cout << " add: " << add1 << std::endl; std::cout << " add: " << add1 << std::endl;
// Test: concatenate a FString and a c++ wide string (operator +)
FString add2 = FString("FString + ") + std::wstring(L"std::wstring"); FString add2 = FString("FString + ") + std::wstring(L"std::wstring");
std::cout << " add: " << add2 << std::endl; std::cout << " add: " << add2 << std::endl;
// Test: concatenate a FString and a wide string (operator +)
FString add3 = FString("FString + ") + const_cast<wchar_t*>(L"wchar_t*"); FString add3 = FString("FString + ") + const_cast<wchar_t*>(L"wchar_t*");
std::cout << " add: " << add3 << std::endl; std::cout << " add: " << add3 << std::endl;
// Test: concatenate a FString and a c++ string (operator +)
FString add4 = FString("FString + ") + std::string("std::string"); FString add4 = FString("FString + ") + std::string("std::string");
std::cout << " add: " << add4 << std::endl; std::cout << " add: " << add4 << std::endl;
// Test: concatenate a FString and a c-string (operator +)
FString add5 = FString("FString + ") + const_cast<char*>("char*"); FString add5 = FString("FString + ") + const_cast<char*>("char*");
std::cout << " add: " << add5 << std::endl; std::cout << " add: " << add5 << std::endl;
// Test: concatenate a FString and a wide character (operator +)
FString add6 = FString("FString + ") + wchar_t(L'w'); FString add6 = FString("FString + ") + wchar_t(L'w');
std::cout << " add: " << add6 << std::endl; std::cout << " add: " << add6 << std::endl;
// Test: concatenate a FString and a character (operator +)
FString add7 = FString("FString + ") + char('c'); FString add7 = FString("FString + ") + char('c');
std::cout << " add: " << add7 << std::endl; std::cout << " add: " << add7 << std::endl;
// Test: concatenate a character and a FString (operator +)
FString add8 = 'c' + FString(" + FString"); FString add8 = 'c' + FString(" + FString");
std::cout << " add: " << add8 << std::endl; std::cout << " add: " << add8 << std::endl;
// Test: concatenate a wide character and a FString (operator +)
FString add9 = L'w' + FString(" + FString"); FString add9 = L'w' + FString(" + FString");
std::cout << " add: " << add9 << std::endl; std::cout << " add: " << add9 << std::endl;
// Test: concatenate a c-string and a FString (operator +)
FString add10 = const_cast<char*>("char*") + FString(" + FString"); FString add10 = const_cast<char*>("char*") + FString(" + FString");
std::cout << " add: " << add10 << std::endl; std::cout << " add: " << add10 << std::endl;
// Test: concatenate a c++ string and a FString (operator +)
FString add11 = std::string("std::string") + FString(" + FString"); FString add11 = std::string("std::string") + FString(" + FString");
std::cout << " add: " << add11 << std::endl; std::cout << " add: " << add11 << std::endl;
// Test: concatenate a wide string and a FString (operator +)
FString add12 = const_cast<wchar_t*>(L"wchar_t*") + FString(" + FString"); FString add12 = const_cast<wchar_t*>(L"wchar_t*") + FString(" + FString");
std::cout << " add: " << add12 << std::endl; std::cout << " add: " << add12 << std::endl;
// Test: concatenate a c++ wide string and a FString (operator +)
FString add13 = std::wstring(L"std::wstring") + FString(" + FString"); FString add13 = std::wstring(L"std::wstring") + FString(" + FString");
std::cout << " add: " << add13 << std::endl; std::cout << " add: " << add13 << std::endl;
// Test: compare operators ==, <=, <, >=, >, !=
FString cmp = "compare"; FString cmp = "compare";
if ( cmp == FString("compare") ) if ( cmp == FString("compare") )
@ -112,6 +150,7 @@ int main (int, char**)
else else
std::cout << " cmp: != Not Ok" << std::endl; std::cout << " cmp: != Not Ok" << std::endl;
// Test: split a string with a delimiter and returns a vector (array)
FString split_str = "a,b,c,d"; FString split_str = "a,b,c,d";
std::cout << " split: \"" std::cout << " split: \""
<< split_str << "\" into substrings ->"; << split_str << "\" into substrings ->";
@ -124,10 +163,13 @@ int main (int, char**)
std::cout << std::endl; std::cout << std::endl;
// Test: format a string with sprintf
FString formatStr = ""; FString formatStr = "";
std::cout << " formatted: " std::cout << " formatted: "
<< formatStr.sprintf("sqrt(%d) = %d", 16, 4) << formatStr.sprintf("sqrt(%d) = %d", 16, 4)
<< std::endl; << std::endl;
// Test: convert a string to a unsigned long interger
try try
{ {
uLong ulong_num = FString("123456789").toULong(); uLong ulong_num = FString("123456789").toULong();
@ -142,6 +184,7 @@ int main (int, char**)
std::cerr << "Arithmetic error: " << ex.what() << std::endl; std::cerr << "Arithmetic error: " << ex.what() << std::endl;
} }
// Test: convert a string to a signed long interger
try try
{ {
long long_num = FString("-9876543210").toLong(); long long_num = FString("-9876543210").toLong();
@ -156,6 +199,7 @@ int main (int, char**)
std::cerr << "Arithmetic error: " << ex.what() << std::endl; std::cerr << "Arithmetic error: " << ex.what() << std::endl;
} }
// Test: convert a string to a double value
std::setlocale(LC_NUMERIC, "C"); std::setlocale(LC_NUMERIC, "C");
try try
@ -175,6 +219,7 @@ int main (int, char**)
std::cerr << "Arithmetic error: " << ex.what() << std::endl; std::cerr << "Arithmetic error: " << ex.what() << std::endl;
} }
// Test: convert integer and double value to a string
FString num1, num2, num3; FString num1, num2, num3;
num1.setNumber(137); num1.setNumber(137);
num2.setNumber(-512); num2.setNumber(-512);
@ -186,6 +231,7 @@ int main (int, char**)
std::cout << " setNumber: " std::cout << " setNumber: "
<< num3 << " (long double)" << std::endl; << num3 << " (long double)" << std::endl;
// Test: convert and format a integer number with thousand separator
std::setlocale (LC_NUMERIC, ""); std::setlocale (LC_NUMERIC, "");
FString fnum1, fnum2; FString fnum1, fnum2;
#if defined(__LP64__) || defined(_LP64) #if defined(__LP64__) || defined(_LP64)
@ -202,22 +248,33 @@ int main (int, char**)
std::cout << "setFormatedNumber: " std::cout << "setFormatedNumber: "
<< fnum2 << " (signed)" << std::endl; << fnum2 << " (signed)" << std::endl;
// Test: remove whitespace from the end of a string
FString trim_str = " A string \t"; FString trim_str = " A string \t";
std::wcout << " rtrim: \"" std::wcout << " rtrim: \""
<< trim_str.rtrim() << "\"" << std::endl; << trim_str.rtrim() << "\"" << std::endl;
// Test: remove whitespace from the beginning of a string
std::cout << " ltrim: \"" std::cout << " ltrim: \""
<< trim_str.ltrim() << "\"" << std::endl; << trim_str.ltrim() << "\"" << std::endl;
// Test: remove whitespace from the beginning and end of a string
std::cout << " trim: \"" std::cout << " trim: \""
<< trim_str.trim() << "\"" << std::endl; << trim_str.trim() << "\"" << std::endl;
// Test: 11 characters from the left of the string
FString alphabet = "a b c d e f g h i j k l m n o p q r s t u v w x y z"; FString alphabet = "a b c d e f g h i j k l m n o p q r s t u v w x y z";
std::cout << " left: \"" std::cout << " left: \""
<< alphabet.left(11) << "\"" << std::endl; << alphabet.left(11) << "\"" << std::endl;
// Test: extract a substring of 27 characters from position 12
std::cout << " mid: \"" std::cout << " mid: \""
<< alphabet.mid(13,27) << "\"" << std::endl; << alphabet.mid(13,27) << "\"" << std::endl;
// Test: 11 characters from the right of the string
std::cout << " right: \"" std::cout << " right: \""
<< alphabet.right(11) << "\"" << std::endl; << alphabet.right(11) << "\"" << std::endl;
// Test: insert a string at index position 7
FString insert_str = "I am a string"; FString insert_str = "I am a string";
try try
@ -230,7 +287,8 @@ int main (int, char**)
std::cerr << "Out of Range error: " << ex.what() << std::endl; std::cerr << "Out of Range error: " << ex.what() << std::endl;
} }
FString index(5); // a string with five characters // Test: get character access at a specified index position
FString index(5); // string with five characters
index = "index"; index = "index";
try try
@ -245,6 +303,7 @@ int main (int, char**)
std::cerr << "Out of Range error: " << ex.what() << std::endl; std::cerr << "Out of Range error: " << ex.what() << std::endl;
} }
// Test: character access with std::iterator
FString stringIterator = "iterator"; FString stringIterator = "iterator";
FString::iterator iter; FString::iterator iter;
iter = stringIterator.begin(); iter = stringIterator.begin();
@ -260,14 +319,17 @@ int main (int, char**)
<< "', back='" << char(stringIterator.back()) << "', back='" << char(stringIterator.back())
<< "')" << std::endl; << "')" << std::endl;
// Test: overwrite string at position 10 with "for t"
FString overwrite_std = "Overwrite the rest"; FString overwrite_std = "Overwrite the rest";
std::cout << "overwrite: " std::cout << "overwrite: "
<< overwrite_std.overwrite("for t", 10) << std::endl; << overwrite_std.overwrite("for t", 10) << std::endl;
// Test: remove 2 characters at position 7
FString remove_std = "A fast remove"; FString remove_std = "A fast remove";
std::cout << " remove: " std::cout << " remove: "
<< remove_std.remove(7,2) << std::endl; << remove_std.remove(7,2) << std::endl;
// Test: includes a substring (positive test)
FString include_std = "string"; FString include_std = "string";
if ( include_std.includes("ring") ) if ( include_std.includes("ring") )
@ -279,6 +341,7 @@ int main (int, char**)
<< include_std << "\" includes no \"ring\" " << include_std << "\" includes no \"ring\" "
<< std::endl; << std::endl;
// Test: includes a substring (negativ test)
if ( include_std.includes("data") ) if ( include_std.includes("data") )
std::cout << " includes: \"" std::cout << " includes: \""
<< include_std << "\" includes \"data\" " << include_std << "\" includes \"data\" "
@ -288,19 +351,23 @@ int main (int, char**)
<< include_std << "\" includes no \"data\" " << include_std << "\" includes no \"data\" "
<< std::endl; << std::endl;
// Test: find and replace a substring
FString source_str = "computer and software"; FString source_str = "computer and software";
FString replace_str = source_str.replace("computer", "hard-"); FString replace_str = source_str.replace("computer", "hard-");
std::cout << " replace: " std::cout << " replace: "
<< replace_str << std::endl; << replace_str << std::endl;
// Test: convert tabs to spaces
FString tab_str = "1234\t5678"; FString tab_str = "1234\t5678";
std::cout << " tab: " std::cout << " tab: "
<< tab_str.expandTabs() << std::endl; << tab_str.expandTabs() << std::endl;
// Test: backspaces remove characters in the string
FString bs_str = "t\b\bTesT\bt"; FString bs_str = "t\b\bTesT\bt";
std::cout << "backspace: " std::cout << "backspace: "
<< bs_str.removeBackspaces() << std::endl; << bs_str.removeBackspaces() << std::endl;
// Test: delete characters remove characters in the string
FString del_str = "apple \177\177\177pietree"; FString del_str = "apple \177\177\177pietree";
std::cout << " delete: " std::cout << " delete: "
<< del_str.removeDel() << std::endl; << del_str.removeDel() << std::endl;