mirror of
https://github.com/FirebirdSQL/firebird.git
synced 2025-02-02 09:20:39 +01:00
Implementation of move semantics for Firebird::string (#8059)
This commit is contained in:
parent
f1c4e00cc4
commit
2d8c006140
@ -232,6 +232,16 @@ public:
|
||||
// The same routine, but more easily callable from the debugger
|
||||
void print_contents(const char* filename, unsigned flags = 0, const char* filter_path = 0) noexcept;
|
||||
|
||||
inline bool operator==(const MemoryPool& rhs) const
|
||||
{
|
||||
return pool == rhs.pool;
|
||||
}
|
||||
|
||||
inline bool operator!=(const MemoryPool& rhs) const
|
||||
{
|
||||
return !operator==(rhs);
|
||||
}
|
||||
|
||||
public:
|
||||
struct Finalizer
|
||||
{
|
||||
|
@ -396,6 +396,20 @@ extern "C" {
|
||||
shrinkBuffer();
|
||||
}
|
||||
|
||||
bool AbstractString::baseMove(AbstractString&& rhs)
|
||||
{
|
||||
if (getPool() == rhs.getPool() && rhs.inlineBuffer != rhs.stringBuffer)
|
||||
{
|
||||
stringBuffer = std::exchange(rhs.stringBuffer, rhs.inlineBuffer);
|
||||
stringLength = std::exchange(rhs.stringLength, 0);
|
||||
bufferSize = std::exchange(rhs.bufferSize, INLINE_BUFFER_SIZE);
|
||||
rhs.inlineBuffer[0] = '\0';
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
void AbstractString::printf(const char* format,...)
|
||||
{
|
||||
va_list params;
|
||||
|
@ -32,6 +32,7 @@
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <stdarg.h>
|
||||
#include <utility>
|
||||
|
||||
#include "firebird.h"
|
||||
#include "fb_types.h"
|
||||
@ -203,6 +204,27 @@ namespace Firebird
|
||||
memcpy(stringBuffer, s, l);
|
||||
}
|
||||
|
||||
AbstractString(const size_type limit, AbstractString&& rhs) :
|
||||
max_length(static_cast<internal_size_type>(limit))
|
||||
{
|
||||
// We can move only string with default pool
|
||||
if (!baseMove(std::forward<AbstractString>(rhs)))
|
||||
{
|
||||
initialize(rhs.length());
|
||||
memcpy(stringBuffer, rhs.c_str(), stringLength);
|
||||
}
|
||||
}
|
||||
|
||||
AbstractString(const size_type limit, MemoryPool& p, AbstractString&& rhs)
|
||||
: AutoStorage(p), max_length(static_cast<internal_size_type>(limit))
|
||||
{
|
||||
if (!baseMove(std::forward<AbstractString>(rhs)))
|
||||
{
|
||||
initialize(rhs.length());
|
||||
memcpy(stringBuffer, rhs.c_str(), stringLength);
|
||||
}
|
||||
}
|
||||
|
||||
pointer modify()
|
||||
{
|
||||
return stringBuffer;
|
||||
@ -223,6 +245,8 @@ namespace Firebird
|
||||
|
||||
void baseTrim(const TrimType whereTrim, const_pointer toTrim);
|
||||
|
||||
bool baseMove(AbstractString&& rhs);
|
||||
|
||||
size_type getMaxLength() const
|
||||
{
|
||||
return max_length;
|
||||
@ -676,6 +700,10 @@ namespace Firebird
|
||||
AbstractString(Comparator::getMaxLength(), p, s, static_cast<size_type>(s ? strlen(s) : 0)) {}
|
||||
StringBase(MemoryPool& p, const char_type* s, size_type l) :
|
||||
AbstractString(Comparator::getMaxLength(), p, s, l) {}
|
||||
StringBase(StringType&& rhs) :
|
||||
AbstractString(Comparator::getMaxLength(), std::forward<AbstractString>(rhs)) {}
|
||||
StringBase(MemoryPool& p, StringType&& rhs) :
|
||||
AbstractString(Comparator::getMaxLength(), p, std::forward<AbstractString>(rhs)) {}
|
||||
|
||||
static size_type max_length()
|
||||
{
|
||||
@ -754,6 +782,25 @@ namespace Firebird
|
||||
{
|
||||
return add(&c, 1);
|
||||
}
|
||||
StringType& operator=(StringType&& rhs)
|
||||
{
|
||||
// baseMove do not clear the buffer so do it in this method
|
||||
char_type* backup = nullptr;
|
||||
if (stringBuffer != inlineBuffer)
|
||||
backup = stringBuffer;
|
||||
|
||||
if (baseMove(std::forward<AbstractString>(rhs)))
|
||||
{
|
||||
// The dynamic buffer has been replaced, so clear the old one
|
||||
delete[] backup;
|
||||
}
|
||||
else
|
||||
{
|
||||
// Cannot move, do the base assignment
|
||||
assign(rhs.c_str(), rhs.length());
|
||||
}
|
||||
return *this;
|
||||
}
|
||||
|
||||
StringBase<StringComparator> ToString() const
|
||||
{
|
||||
|
@ -1,676 +0,0 @@
|
||||
char lbl[] = "0123456789";
|
||||
|
||||
//#define CHECK_FATAL_RANGE_EXCEPTION
|
||||
//Don't modify 3 lines upper from this - they are used in file read test
|
||||
//If you plan to check range exception, you may uncomment it -
|
||||
//anyway file test should not happen
|
||||
|
||||
/*
|
||||
* PROGRAM: Class library integrity tests
|
||||
* MODULE: string_test.cpp
|
||||
* DESCRIPTION: test class Firebird::string
|
||||
*
|
||||
* The contents of this file are subject to the Initial
|
||||
* Developer's Public License Version 1.0 (the "License");
|
||||
* you may not use this file except in compliance with the
|
||||
* License. You may obtain a copy of the License at
|
||||
* http://www.ibphoenix.com/main.nfs?a=ibphoenix&page=ibp_idpl.
|
||||
*
|
||||
* Software distributed under the License is distributed AS IS,
|
||||
* WITHOUT WARRANTY OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing rights
|
||||
* and limitations under the License.
|
||||
*
|
||||
* The Original Code was created by Alexander Peshkoff
|
||||
* for the Firebird Open Source RDBMS project.
|
||||
*
|
||||
* Copyright (c) 2004 Alexander Peshkoff <peshkoff@mail.ru>
|
||||
* and all contributors signed below.
|
||||
*
|
||||
* All Rights Reserved.
|
||||
* Contributor(s): ______________________________________.
|
||||
*/
|
||||
|
||||
#if defined(FIRESTR) && defined(DEV_BUILD)
|
||||
#define FULL_FIRE
|
||||
#endif
|
||||
|
||||
#ifdef FIRESTR
|
||||
#define NAME "Firebird::string"
|
||||
#include "../common/classes/fb_string.h"
|
||||
|
||||
using namespace Firebird;
|
||||
#else
|
||||
#define NAME "std::basic_string"
|
||||
#include <string>
|
||||
typedef std::basic_string<char> string;
|
||||
typedef string AbstractString;
|
||||
#endif
|
||||
|
||||
#include <time.h>
|
||||
|
||||
#ifdef DEV_BUILD
|
||||
void CheckStr(const AbstractString& check, const char* want, int line)
|
||||
{
|
||||
if (strlen(check.c_str()) != check.length()) {
|
||||
printf("Length error at %d\n\n", line);
|
||||
}
|
||||
if (strcmp(check.c_str(), want)) {
|
||||
printf("Wanted >%s<,\n got >%s< at %d\n\n", want, check.c_str(), line);
|
||||
}
|
||||
}
|
||||
#define validate(a, b) CheckStr(a, b, __LINE__)
|
||||
#else
|
||||
#define validate(a, b)
|
||||
#define check(a, b)
|
||||
#endif
|
||||
|
||||
void test()
|
||||
{
|
||||
{
|
||||
string a;
|
||||
validate(a, "");
|
||||
a = lbl;
|
||||
string b = a;
|
||||
validate(b, lbl);
|
||||
string f = "0123456789";
|
||||
validate(f, lbl);
|
||||
string g("0123456789", 5);
|
||||
validate(g, "01234");
|
||||
string h(5, '7');
|
||||
validate(h, "77777");
|
||||
#ifdef FULL_FIRE
|
||||
string i('7');
|
||||
validate(i, "7");
|
||||
#endif
|
||||
string j(&lbl[3], &lbl[5]);
|
||||
validate(j, "34");
|
||||
}
|
||||
|
||||
{
|
||||
string a = lbl;
|
||||
string b;
|
||||
b = a;
|
||||
validate(b, lbl);
|
||||
b = lbl;
|
||||
validate(b, lbl);
|
||||
a = 'X';
|
||||
validate(a, "X");
|
||||
|
||||
a = b;
|
||||
for (string::iterator x = b.begin(); x < b.end(); x++)
|
||||
*x = 'u';
|
||||
validate(a, lbl);
|
||||
validate(b, "uuuuuuuuuu");
|
||||
|
||||
char y[20], *z = y;
|
||||
const string c = a;
|
||||
for (string::const_iterator x1 = c.begin(); x1 < c.end(); x1++)
|
||||
*z++ = *x1;
|
||||
*z = 0;
|
||||
b = y;
|
||||
validate(b, lbl);
|
||||
}
|
||||
|
||||
#ifdef FULL_FIRE
|
||||
{
|
||||
const string a = lbl;
|
||||
string b = a.at(5);
|
||||
validate(b, "5");
|
||||
}
|
||||
|
||||
{
|
||||
string a = lbl;
|
||||
string b = a.at(5);
|
||||
validate(b, "5");
|
||||
}
|
||||
#endif
|
||||
|
||||
// conflict with J. requirement to string class - operator const char*
|
||||
// {
|
||||
// string a = lbl;
|
||||
// char c = a[5];
|
||||
// a[5] = 'u';
|
||||
// validate(a, "01234u6789");
|
||||
// }
|
||||
{
|
||||
string a = lbl;
|
||||
char c = a[5]; // via operator const char*
|
||||
a.at(5) = 'u';
|
||||
a.at(7) = c;
|
||||
validate(a, "01234u6589");
|
||||
}
|
||||
|
||||
#ifdef CHECK_FATAL_RANGE_EXCEPTION
|
||||
{
|
||||
const string a = lbl;
|
||||
string b = a.at(15);
|
||||
}
|
||||
#endif
|
||||
|
||||
{
|
||||
string a = lbl;
|
||||
a.resize(15, 'u');
|
||||
validate(a, "0123456789uuuuu");
|
||||
}
|
||||
|
||||
{
|
||||
string a;
|
||||
string x = lbl;
|
||||
x += lbl;
|
||||
x += lbl;
|
||||
x += lbl;
|
||||
x += lbl;
|
||||
x += lbl;
|
||||
x += lbl;
|
||||
x += lbl;
|
||||
x += lbl;
|
||||
x += lbl;
|
||||
x += lbl;
|
||||
x += lbl; //120 bytes
|
||||
a = x;
|
||||
validate(a, x.c_str());
|
||||
|
||||
x = lbl;
|
||||
x += lbl;
|
||||
x += lbl;
|
||||
x += lbl; //40 bytes
|
||||
a = x;
|
||||
validate(a, x.c_str());
|
||||
}
|
||||
|
||||
{
|
||||
string a = lbl;
|
||||
const string b = a;
|
||||
a += b;
|
||||
validate(a, "01234567890123456789");
|
||||
|
||||
a = lbl;
|
||||
a += lbl;
|
||||
validate(a, "01234567890123456789");
|
||||
|
||||
a = lbl;
|
||||
a += 'u';
|
||||
validate(a, "0123456789u");
|
||||
}
|
||||
|
||||
{
|
||||
string a, b, c;
|
||||
|
||||
a = "uuu";
|
||||
b = lbl;
|
||||
c = a + b;
|
||||
validate(c, "uuu0123456789");
|
||||
|
||||
c = a + lbl;
|
||||
validate(c, "uuu0123456789");
|
||||
|
||||
c = b + 'u';
|
||||
validate(c, "0123456789u");
|
||||
|
||||
c = lbl + a;
|
||||
validate(c, "0123456789uuu");
|
||||
|
||||
c = 'u' + b;
|
||||
validate(c, "u0123456789");
|
||||
|
||||
validate(a, "uuu");
|
||||
validate(b, lbl);
|
||||
}
|
||||
|
||||
{
|
||||
string a = lbl;
|
||||
const string b = a;
|
||||
a.append(b);
|
||||
validate(a, "01234567890123456789");
|
||||
|
||||
a = lbl;
|
||||
a.append(lbl);
|
||||
validate(a, "01234567890123456789");
|
||||
|
||||
a = lbl;
|
||||
a.append(lbl, 6);
|
||||
validate(a, "0123456789012345");
|
||||
|
||||
a = lbl;
|
||||
a.append(b, 3, 2);
|
||||
validate(a, "012345678934");
|
||||
|
||||
a = lbl;
|
||||
a.append(b, 3, 20);
|
||||
validate(a, "01234567893456789");
|
||||
|
||||
a = lbl;
|
||||
a.append(3, 'u');
|
||||
validate(a, "0123456789uuu");
|
||||
|
||||
a = lbl;
|
||||
a.append(b.begin(), b.end());
|
||||
validate(a, "01234567890123456789");
|
||||
|
||||
a = lbl;
|
||||
a.append("Something reaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaally long");
|
||||
validate(a, "0123456789Something reaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaally long");
|
||||
a = lbl;
|
||||
validate(a, lbl);
|
||||
|
||||
string c = lbl;
|
||||
c += lbl;
|
||||
c += lbl;
|
||||
c += lbl;
|
||||
a = lbl;
|
||||
a.append("Something reaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaally long");
|
||||
validate(a, "0123456789Something reaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaally long");
|
||||
a = c;
|
||||
validate(a, c.c_str());
|
||||
}
|
||||
|
||||
{
|
||||
string a, b;
|
||||
b = lbl;
|
||||
|
||||
a.assign(3, 'u');
|
||||
validate(a, "uuu");
|
||||
|
||||
a.assign(lbl);
|
||||
validate(a, lbl);
|
||||
|
||||
a.assign(lbl, 2);
|
||||
validate(a, "01");
|
||||
|
||||
a.assign(b, 3, 3);
|
||||
validate(a, "345");
|
||||
|
||||
a.assign(b);
|
||||
validate(a, lbl);
|
||||
|
||||
a = "";
|
||||
validate(a, "");
|
||||
string::iterator x = b.begin();
|
||||
string::iterator y = b.end();
|
||||
a.assign(x, y);
|
||||
validate(a, lbl);
|
||||
}
|
||||
|
||||
{
|
||||
string a, b = lbl;
|
||||
|
||||
a = lbl;
|
||||
a.insert(5, 3, 'u');
|
||||
validate(a, "01234uuu56789");
|
||||
|
||||
a = lbl;
|
||||
a.insert(3, lbl);
|
||||
validate(a, "01201234567893456789");
|
||||
|
||||
a = lbl;
|
||||
a.insert(4, lbl, 2);
|
||||
validate(a, "012301456789");
|
||||
|
||||
a = lbl;
|
||||
a.insert(5, b, 3, 3);
|
||||
validate(a, "0123434556789");
|
||||
|
||||
a = lbl;
|
||||
a.insert(5, b);
|
||||
validate(a, "01234012345678956789");
|
||||
|
||||
a = lbl;
|
||||
a.insert(2, "Something reaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaally long");
|
||||
validate(a, "01Something reaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaally long23456789");
|
||||
|
||||
a = lbl;
|
||||
string::iterator x = a.begin();
|
||||
x++;
|
||||
a.insert(x, 5, 'u');
|
||||
validate(a, "0uuuuu123456789");
|
||||
|
||||
a = lbl;
|
||||
x = a.begin();
|
||||
x += 2;
|
||||
string::iterator f = b.begin();
|
||||
string::iterator t = b.end();
|
||||
f++; t--;
|
||||
a.insert(x, f, t);
|
||||
validate(a, "011234567823456789");
|
||||
|
||||
a = lbl;
|
||||
a.erase();
|
||||
validate(a, "");
|
||||
|
||||
a = lbl;
|
||||
a.erase(3, 6);
|
||||
validate(a, "0129");
|
||||
|
||||
a = lbl;
|
||||
a.erase(3, 16);
|
||||
validate(a, "012");
|
||||
|
||||
a = lbl;
|
||||
a.erase(3);
|
||||
validate(a, "012");
|
||||
|
||||
a = lbl;
|
||||
x = a.begin();
|
||||
x += 3;
|
||||
a.erase(x);
|
||||
validate(a, "012456789");
|
||||
|
||||
a = lbl;
|
||||
x = a.begin();
|
||||
x += 3;
|
||||
string::iterator y = a.end();
|
||||
y -= 2;
|
||||
a.erase(x, y);
|
||||
validate(a, "01289");
|
||||
}
|
||||
|
||||
{
|
||||
string a;
|
||||
const string b = lbl;
|
||||
string::iterator f0, t0;
|
||||
string::const_iterator f, t;
|
||||
|
||||
a = lbl;
|
||||
a.replace(5, 2, 3, 'u');
|
||||
validate(a, "01234uuu789");
|
||||
|
||||
a = lbl;
|
||||
f0 = a.begin() + 5;
|
||||
t0 = f0 + 2;
|
||||
a.replace(f0, t0, 3, 'u');
|
||||
validate(a, "01234uuu789");
|
||||
|
||||
a = lbl;
|
||||
a.replace(3, 3, lbl);
|
||||
validate(a, "01201234567896789");
|
||||
|
||||
a = lbl;
|
||||
f0 = a.begin() + 3;
|
||||
t0 = f0 + 3;
|
||||
a.replace(f0, t0, lbl);
|
||||
validate(a, "01201234567896789");
|
||||
|
||||
a = lbl;
|
||||
a.replace(4, 4, lbl, 2);
|
||||
validate(a, "01230189");
|
||||
|
||||
a = lbl;
|
||||
f0 = a.begin() + 4;
|
||||
t0 = f0 + 4;
|
||||
a.replace(f0, t0, lbl, 2);
|
||||
validate(a, "01230189");
|
||||
|
||||
a = lbl;
|
||||
a.replace(5, 10, b, 3, 3);
|
||||
validate(a, "01234345");
|
||||
|
||||
a = lbl;
|
||||
f0 = a.begin() + 5;
|
||||
t0 = f0 + 10;
|
||||
f = b.begin() + 3;
|
||||
t = f + 3;
|
||||
a.replace(f0, t0, f, t);
|
||||
validate(a, "01234345");
|
||||
|
||||
a = lbl;
|
||||
a.replace(5, 0, b);
|
||||
validate(a, "01234012345678956789");
|
||||
|
||||
a = lbl;
|
||||
f0 = a.begin() + 5;
|
||||
t0 = f0;
|
||||
a.replace(f0, t0, b);
|
||||
validate(a, "01234012345678956789");
|
||||
|
||||
a = lbl;
|
||||
a.replace(2, 1, "Something reaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaally long");
|
||||
validate(a, "01Something reaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaally long3456789");
|
||||
}
|
||||
|
||||
{
|
||||
string a, b = lbl;
|
||||
char s[40];
|
||||
memset(s, 0, 40);
|
||||
|
||||
#ifdef FULL_FIRE
|
||||
b.copyTo(s, 5);
|
||||
a = s;
|
||||
validate(a, "0123");
|
||||
|
||||
b.copyTo(s, 40);
|
||||
a = s;
|
||||
validate(a, lbl);
|
||||
#endif
|
||||
|
||||
// a.swap(b);
|
||||
// validate(b, "3456789");
|
||||
// validate(a, lbl);
|
||||
}
|
||||
|
||||
#ifdef DEV_BUILD
|
||||
#undef check
|
||||
#define check(a, b) if (a != b) printf("Wanted %d got %d at %d\n\n", b, a, __LINE__)
|
||||
#endif
|
||||
|
||||
{
|
||||
string a = "012345uuu345678";
|
||||
// 9
|
||||
string b = "345";
|
||||
|
||||
check(a.find(b), 3);
|
||||
check(a.find("45"), 4);
|
||||
check(a.find('5'), 5);
|
||||
check(a.find("ZZ"), string::npos);
|
||||
|
||||
check(a.rfind(b), 9);
|
||||
check(a.rfind("45"), 10);
|
||||
check(a.rfind('5'), 11);
|
||||
check(a.rfind("ZZ"), string::npos);
|
||||
|
||||
check(a.find("45", 8), 10);
|
||||
|
||||
check(a.find_first_of("aub"), 6);
|
||||
check(a.find_first_of(b), 3);
|
||||
check(a.find_first_of("54"), 4);
|
||||
check(a.find_first_of('5'), 5);
|
||||
check(a.find_first_of("ZZ"), string::npos);
|
||||
|
||||
check(a.find_last_of("aub"), 8);
|
||||
check(a.find_last_of(b), 11);
|
||||
check(a.find_last_of("54"), 11);
|
||||
check(a.find_last_of('5'), 11);
|
||||
check(a.find_last_of("ZZ"), string::npos);
|
||||
|
||||
check(a.find_first_of("45", 8), 10);
|
||||
|
||||
b = "010";
|
||||
check(a.find_first_not_of("aub"), 0);
|
||||
check(a.find_first_not_of(b), 2);
|
||||
check(a.find_first_not_of("0102"), 3);
|
||||
check(a.find_first_not_of('0'), 1);
|
||||
check(a.find_first_not_of(a), string::npos);
|
||||
|
||||
b = "878";
|
||||
check(a.find_last_not_of("aub"), 14);
|
||||
check(a.find_last_not_of(b), 12);
|
||||
check(a.find_last_not_of("78"), 12);
|
||||
check(a.find_last_not_of('8'), 13);
|
||||
check(a.find_last_not_of(a), string::npos);
|
||||
|
||||
check(a.find_first_not_of("u345", 8), 12);
|
||||
}
|
||||
|
||||
{
|
||||
string a = lbl;
|
||||
string b;
|
||||
|
||||
b = a.substr(3, 4);
|
||||
validate(b, "3456");
|
||||
|
||||
b = a.substr(5, 20);
|
||||
validate(b, "56789");
|
||||
|
||||
#ifdef FULL_FIRE
|
||||
b = a.substr(50, 20);
|
||||
validate(b, "");
|
||||
#endif
|
||||
}
|
||||
|
||||
#ifdef FULL_FIRE
|
||||
{
|
||||
string b;
|
||||
FILE *x = fopen("string_test.cpp", "rt");
|
||||
b.LoadFromFile(x);
|
||||
validate(b, "char lbl[] = \"0123456789\";");
|
||||
b.LoadFromFile(x);
|
||||
validate(b, "");
|
||||
b.LoadFromFile(x);
|
||||
validate(b, "//#define CHECK_FATAL_RANGE_EXCEPTION");
|
||||
fclose(x);
|
||||
}
|
||||
#endif
|
||||
|
||||
{
|
||||
string a = "Something moderaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaately long";
|
||||
string a1 = a;
|
||||
string b = a + a1;
|
||||
string b1 = b;
|
||||
string c = b + b1;
|
||||
string d = c;
|
||||
string e = c;
|
||||
string f = c;
|
||||
string g = c;
|
||||
string h = c;
|
||||
string i = c;
|
||||
string j = c;
|
||||
string k = c;
|
||||
string l = c;
|
||||
string m = c;
|
||||
string n = c;
|
||||
string o = c;
|
||||
string p = c;
|
||||
}
|
||||
|
||||
#ifdef DEV_BUILD
|
||||
#undef check
|
||||
#define check(get, want) if ( (get < 0 ? -1 : get > 0 ? 1 : 0) != want)\
|
||||
printf("Wanted %d got %d at %d\n\n", want, get, __LINE__)
|
||||
#endif
|
||||
|
||||
#ifdef FULL_FIRE
|
||||
{
|
||||
PathName c = "Aa";
|
||||
PathName d = "AB";
|
||||
|
||||
check(c.compare(d), -1);
|
||||
}
|
||||
#endif
|
||||
|
||||
{
|
||||
string a = lbl;
|
||||
string b = a;
|
||||
string c = "Aaa";
|
||||
string d = "AB";
|
||||
string e = "Aa";
|
||||
|
||||
check(a.compare(b), 0);
|
||||
check(a.compare(c), -1);
|
||||
check(c.compare(a), 1);
|
||||
|
||||
check(c.compare(d), 1);
|
||||
check(c.compare(e), 1);
|
||||
|
||||
check(a.compare(1, 10, b), 1);
|
||||
check(a.compare(1, 10, b, 1, 10), 0);
|
||||
check(a.compare(lbl), 0);
|
||||
check(a.compare(1, 3, lbl + 1, 3), 0);
|
||||
}
|
||||
|
||||
#ifdef FULL_FIRE
|
||||
{
|
||||
string a = " 011100 ", b;
|
||||
|
||||
b = a;
|
||||
b.ltrim();
|
||||
validate(b, "011100 ");
|
||||
|
||||
b = a;
|
||||
b.rtrim();
|
||||
validate(b, " 011100");
|
||||
|
||||
b = a;
|
||||
b.trim(" 0");
|
||||
validate(b, "111");
|
||||
|
||||
b = a;
|
||||
b.alltrim("02 ");
|
||||
validate(b, "111");
|
||||
|
||||
b = a;
|
||||
b.trim("012");
|
||||
validate(b, " 011100 ");
|
||||
|
||||
validate(a, " 011100 ");
|
||||
}
|
||||
|
||||
{
|
||||
string a = lbl;
|
||||
a += '\377';
|
||||
string b = a;
|
||||
a += " ";
|
||||
a.rtrim();
|
||||
validate(a, b.c_str());
|
||||
}
|
||||
|
||||
{
|
||||
string a = "AaBbCc", b;
|
||||
|
||||
b = a;
|
||||
b.lower();
|
||||
validate(b, "aabbcc");
|
||||
|
||||
b = a;
|
||||
b.upper();
|
||||
validate(b, "AABBCC");
|
||||
|
||||
validate(a, "AaBbCc");
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
clock_t t;
|
||||
|
||||
void start()
|
||||
{
|
||||
t = clock();
|
||||
}
|
||||
|
||||
#ifdef DEV_BUILD
|
||||
#define TEST_ITEMS 1
|
||||
#else
|
||||
#define TEST_ITEMS 100000
|
||||
#endif
|
||||
|
||||
void report()
|
||||
{
|
||||
clock_t d = clock();
|
||||
printf("Test of %d iterations with %s took %d milliseconds.\n",
|
||||
TEST_ITEMS, NAME, (int) (d - t) * 1000 / CLOCKS_PER_SEC);
|
||||
}
|
||||
|
||||
int main(int ac, char **av)
|
||||
{
|
||||
int n = TEST_ITEMS;
|
||||
start();
|
||||
while (n--) {
|
||||
test();
|
||||
}
|
||||
report();
|
||||
#if defined(DEV_BUILD) && defined(FIRESTR)
|
||||
getDefaultMemoryPool()->print_contents(stdout, 0);
|
||||
#endif
|
||||
printf("Press enter to continue\n");
|
||||
getchar();
|
||||
return 0;
|
||||
}
|
730
src/common/tests/StringTest.cpp
Normal file
730
src/common/tests/StringTest.cpp
Normal file
@ -0,0 +1,730 @@
|
||||
#include "boost/test/unit_test.hpp"
|
||||
#include "../common/classes/fb_string.h"
|
||||
|
||||
#include <string_view>
|
||||
|
||||
using namespace Firebird;
|
||||
|
||||
|
||||
BOOST_AUTO_TEST_SUITE(StringSuite)
|
||||
BOOST_AUTO_TEST_SUITE(StringFunctionalTests)
|
||||
|
||||
// Constant and utils
|
||||
static constexpr char lbl[] = "0123456789";
|
||||
#define validate(A, B) BOOST_TEST(std::string_view(A.c_str(), A.length()) == std::string_view(B))
|
||||
#define check(A, B) BOOST_TEST(A == B)
|
||||
|
||||
BOOST_AUTO_TEST_CASE(StringInitializeTest)
|
||||
{
|
||||
string a;
|
||||
validate(a, "");
|
||||
a = lbl;
|
||||
string b = a;
|
||||
validate(b, lbl);
|
||||
string f = "0123456789";
|
||||
validate(f, lbl);
|
||||
string g("0123456789", 5);
|
||||
validate(g, "01234");
|
||||
string h(5, '7');
|
||||
validate(h, "77777");
|
||||
|
||||
string i(1, '7');
|
||||
validate(i, "7");
|
||||
|
||||
string j(&lbl[3], &lbl[5]);
|
||||
validate(j, "34");
|
||||
}
|
||||
|
||||
BOOST_AUTO_TEST_CASE(StringAssignmentTest)
|
||||
{
|
||||
string a = lbl;
|
||||
string b;
|
||||
b = a;
|
||||
validate(b, lbl);
|
||||
b = lbl;
|
||||
validate(b, lbl);
|
||||
a = 'X';
|
||||
validate(a, "X");
|
||||
|
||||
a = b;
|
||||
for (string::iterator x = b.begin(); x < b.end(); x++)
|
||||
*x = 'u';
|
||||
validate(a, lbl);
|
||||
validate(b, "uuuuuuuuuu");
|
||||
|
||||
char y[20], *z = y;
|
||||
const string c = a;
|
||||
for (string::const_iterator x1 = c.begin(); x1 < c.end(); x1++)
|
||||
*z++ = *x1;
|
||||
*z = 0;
|
||||
b = y;
|
||||
validate(b, lbl);
|
||||
}
|
||||
|
||||
BOOST_AUTO_TEST_CASE(AtConstTest)
|
||||
{
|
||||
const string a = lbl;
|
||||
string b(1, a.at(5));
|
||||
validate(b, "5");
|
||||
}
|
||||
|
||||
BOOST_AUTO_TEST_CASE(GetAtTest)
|
||||
{
|
||||
string a = lbl;
|
||||
string b(1, a.at(5));
|
||||
validate(b, "5");
|
||||
}
|
||||
|
||||
BOOST_AUTO_TEST_CASE(SetAtTest)
|
||||
{
|
||||
string a = lbl;
|
||||
char c = a[5]; // via operator const char*
|
||||
a.at(5) = 'u';
|
||||
a.at(7) = c;
|
||||
validate(a, "01234u6589");
|
||||
}
|
||||
|
||||
BOOST_AUTO_TEST_CASE(FatalRangeTest)
|
||||
{
|
||||
try
|
||||
{
|
||||
const string a = lbl;
|
||||
char b = a.at(15);
|
||||
|
||||
BOOST_TEST_FAIL("Range exception is missing");
|
||||
}
|
||||
catch(Firebird::fatal_exception& ex)
|
||||
{
|
||||
std::string_view what = ex.what();
|
||||
BOOST_TEST(what == "Firebird::string - pos out of range");
|
||||
}
|
||||
catch(...)
|
||||
{
|
||||
BOOST_TEST_FAIL("Wrong exception");
|
||||
}
|
||||
}
|
||||
|
||||
BOOST_AUTO_TEST_CASE(ResizeTest)
|
||||
{
|
||||
string a = lbl;
|
||||
a.resize(15, 'u');
|
||||
validate(a, "0123456789uuuuu");
|
||||
}
|
||||
|
||||
BOOST_AUTO_TEST_CASE(BigBufferAssignmentTest)
|
||||
{
|
||||
string a;
|
||||
string x = lbl;
|
||||
x += lbl;
|
||||
x += lbl;
|
||||
x += lbl;
|
||||
x += lbl;
|
||||
x += lbl;
|
||||
x += lbl;
|
||||
x += lbl;
|
||||
x += lbl;
|
||||
x += lbl;
|
||||
x += lbl;
|
||||
x += lbl; //120 bytes
|
||||
a = x;
|
||||
validate(a, x.c_str());
|
||||
|
||||
x = lbl;
|
||||
x += lbl;
|
||||
x += lbl;
|
||||
x += lbl; //40 bytes
|
||||
a = x;
|
||||
validate(a, x.c_str());
|
||||
}
|
||||
|
||||
BOOST_AUTO_TEST_CASE(AddConstStringTest)
|
||||
{
|
||||
string a = lbl;
|
||||
const string b = a;
|
||||
a += b;
|
||||
validate(a, "01234567890123456789");
|
||||
|
||||
a = lbl;
|
||||
a += lbl;
|
||||
validate(a, "01234567890123456789");
|
||||
|
||||
a = lbl;
|
||||
a += 'u';
|
||||
validate(a, "0123456789u");
|
||||
}
|
||||
|
||||
BOOST_AUTO_TEST_CASE(OperatorAddTest)
|
||||
{
|
||||
string a, b, c;
|
||||
|
||||
a = "uuu";
|
||||
b = lbl;
|
||||
c = a + b;
|
||||
validate(c, "uuu0123456789");
|
||||
|
||||
c = a + lbl;
|
||||
validate(c, "uuu0123456789");
|
||||
|
||||
c = b + 'u';
|
||||
validate(c, "0123456789u");
|
||||
|
||||
c = lbl + a;
|
||||
validate(c, "0123456789uuu");
|
||||
|
||||
c = 'u' + b;
|
||||
validate(c, "u0123456789");
|
||||
|
||||
validate(a, "uuu");
|
||||
validate(b, lbl);
|
||||
}
|
||||
|
||||
BOOST_AUTO_TEST_CASE(AppendTest)
|
||||
{
|
||||
string a = lbl;
|
||||
const string b = a;
|
||||
a.append(b);
|
||||
validate(a, "01234567890123456789");
|
||||
|
||||
a = lbl;
|
||||
a.append(lbl);
|
||||
validate(a, "01234567890123456789");
|
||||
|
||||
a = lbl;
|
||||
a.append(lbl, 6);
|
||||
validate(a, "0123456789012345");
|
||||
|
||||
a = lbl;
|
||||
a.append(b, 3, 2);
|
||||
validate(a, "012345678934");
|
||||
|
||||
a = lbl;
|
||||
a.append(b, 3, 20);
|
||||
validate(a, "01234567893456789");
|
||||
|
||||
a = lbl;
|
||||
a.append(3, 'u');
|
||||
validate(a, "0123456789uuu");
|
||||
|
||||
a = lbl;
|
||||
a.append(b.begin(), b.end());
|
||||
validate(a, "01234567890123456789");
|
||||
|
||||
a = lbl;
|
||||
a.append("Something reaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaally long");
|
||||
validate(a, "0123456789Something reaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaally long");
|
||||
a = lbl;
|
||||
validate(a, lbl);
|
||||
|
||||
string c = lbl;
|
||||
c += lbl;
|
||||
c += lbl;
|
||||
c += lbl;
|
||||
a = lbl;
|
||||
a.append("Something reaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaally long");
|
||||
validate(a, "0123456789Something reaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaally long");
|
||||
a = c;
|
||||
validate(a, c.c_str());
|
||||
}
|
||||
|
||||
BOOST_AUTO_TEST_CASE(AssignTest)
|
||||
{
|
||||
string a, b;
|
||||
b = lbl;
|
||||
|
||||
a.assign(3, 'u');
|
||||
validate(a, "uuu");
|
||||
|
||||
a.assign(lbl);
|
||||
validate(a, lbl);
|
||||
|
||||
a.assign(lbl, 2);
|
||||
validate(a, "01");
|
||||
|
||||
a.assign(b, 3, 3);
|
||||
validate(a, "345");
|
||||
|
||||
a.assign(b);
|
||||
validate(a, lbl);
|
||||
|
||||
a = "";
|
||||
validate(a, "");
|
||||
string::iterator x = b.begin();
|
||||
string::iterator y = b.end();
|
||||
a.assign(x, y);
|
||||
validate(a, lbl);
|
||||
}
|
||||
|
||||
BOOST_AUTO_TEST_CASE(InsertEraseTest)
|
||||
{
|
||||
string a, b = lbl;
|
||||
|
||||
a = lbl;
|
||||
a.insert(5, 3, 'u');
|
||||
validate(a, "01234uuu56789");
|
||||
|
||||
a = lbl;
|
||||
a.insert(3, lbl);
|
||||
validate(a, "01201234567893456789");
|
||||
|
||||
a = lbl;
|
||||
a.insert(4, lbl, 2);
|
||||
validate(a, "012301456789");
|
||||
|
||||
a = lbl;
|
||||
a.insert(5, b, 3, 3);
|
||||
validate(a, "0123434556789");
|
||||
|
||||
a = lbl;
|
||||
a.insert(5, b);
|
||||
validate(a, "01234012345678956789");
|
||||
|
||||
a = lbl;
|
||||
a.insert(2, "Something reaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaally long");
|
||||
validate(a, "01Something reaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaally long23456789");
|
||||
|
||||
a = lbl;
|
||||
string::iterator x = a.begin();
|
||||
x++;
|
||||
a.insert(x, 5, 'u');
|
||||
validate(a, "0uuuuu123456789");
|
||||
|
||||
a = lbl;
|
||||
x = a.begin();
|
||||
x += 2;
|
||||
string::iterator f = b.begin();
|
||||
string::iterator t = b.end();
|
||||
f++; t--;
|
||||
a.insert(x, f, t);
|
||||
validate(a, "011234567823456789");
|
||||
|
||||
a = lbl;
|
||||
a.erase();
|
||||
validate(a, "");
|
||||
|
||||
a = lbl;
|
||||
a.erase(3, 6);
|
||||
validate(a, "0129");
|
||||
|
||||
a = lbl;
|
||||
a.erase(3, 16);
|
||||
validate(a, "012");
|
||||
|
||||
a = lbl;
|
||||
a.erase(3);
|
||||
validate(a, "012");
|
||||
|
||||
a = lbl;
|
||||
x = a.begin();
|
||||
x += 3;
|
||||
a.erase(x);
|
||||
validate(a, "012456789");
|
||||
|
||||
a = lbl;
|
||||
x = a.begin();
|
||||
x += 3;
|
||||
string::iterator y = a.end();
|
||||
y -= 2;
|
||||
a.erase(x, y);
|
||||
validate(a, "01289");
|
||||
}
|
||||
|
||||
BOOST_AUTO_TEST_CASE(ReplaceTest)
|
||||
{
|
||||
string a;
|
||||
const string b = lbl;
|
||||
string::iterator f0, t0;
|
||||
string::const_iterator f, t;
|
||||
|
||||
a = lbl;
|
||||
a.replace(5, 2, 3, 'u');
|
||||
validate(a, "01234uuu789");
|
||||
|
||||
a = lbl;
|
||||
f0 = a.begin() + 5;
|
||||
t0 = f0 + 2;
|
||||
a.replace(f0, t0, 3, 'u');
|
||||
validate(a, "01234uuu789");
|
||||
|
||||
a = lbl;
|
||||
a.replace(3, 3, lbl);
|
||||
validate(a, "01201234567896789");
|
||||
|
||||
a = lbl;
|
||||
f0 = a.begin() + 3;
|
||||
t0 = f0 + 3;
|
||||
a.replace(f0, t0, lbl);
|
||||
validate(a, "01201234567896789");
|
||||
|
||||
a = lbl;
|
||||
a.replace(4, 4, lbl, 2);
|
||||
validate(a, "01230189");
|
||||
|
||||
a = lbl;
|
||||
f0 = a.begin() + 4;
|
||||
t0 = f0 + 4;
|
||||
a.replace(f0, t0, lbl, 2);
|
||||
validate(a, "01230189");
|
||||
|
||||
a = lbl;
|
||||
a.replace(5, 10, b, 3, 3);
|
||||
validate(a, "01234345");
|
||||
|
||||
a = lbl;
|
||||
f0 = a.begin() + 5;
|
||||
t0 = f0 + 10;
|
||||
f = b.begin() + 3;
|
||||
t = f + 3;
|
||||
a.replace(f0, t0, f, t);
|
||||
validate(a, "01234345");
|
||||
|
||||
a = lbl;
|
||||
a.replace(5, 0, b);
|
||||
validate(a, "01234012345678956789");
|
||||
|
||||
a = lbl;
|
||||
f0 = a.begin() + 5;
|
||||
t0 = f0;
|
||||
a.replace(f0, t0, b);
|
||||
validate(a, "01234012345678956789");
|
||||
|
||||
a = lbl;
|
||||
a.replace(2, 1, "Something reaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaally long");
|
||||
validate(a, "01Something reaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaally long3456789");
|
||||
}
|
||||
|
||||
BOOST_AUTO_TEST_CASE(CopyToTest)
|
||||
{
|
||||
string a, b = lbl;
|
||||
char s[40];
|
||||
memset(s, 0, 40);
|
||||
|
||||
b.copyTo(s, 5);
|
||||
a = s;
|
||||
validate(a, "0123");
|
||||
|
||||
b.copyTo(s, 40);
|
||||
a = s;
|
||||
validate(a, lbl);
|
||||
|
||||
// a.swap(b);
|
||||
// validate(b, "3456789");
|
||||
// validate(a, lbl);
|
||||
}
|
||||
|
||||
|
||||
BOOST_AUTO_TEST_CASE(FindTest)
|
||||
{
|
||||
string a = "012345uuu345678";
|
||||
// 9
|
||||
string b = "345";
|
||||
|
||||
check(a.find(b), 3);
|
||||
check(a.find("45"), 4);
|
||||
check(a.find('5'), 5);
|
||||
check(a.find("ZZ"), string::npos);
|
||||
|
||||
check(a.rfind(b), 9);
|
||||
check(a.rfind("45"), 10);
|
||||
check(a.rfind('5'), 11);
|
||||
check(a.rfind("ZZ"), string::npos);
|
||||
|
||||
check(a.find("45", 8), 10);
|
||||
|
||||
check(a.find_first_of("aub"), 6);
|
||||
check(a.find_first_of(b), 3);
|
||||
check(a.find_first_of("54"), 4);
|
||||
check(a.find_first_of('5'), 5);
|
||||
check(a.find_first_of("ZZ"), string::npos);
|
||||
|
||||
check(a.find_last_of("aub"), 8);
|
||||
check(a.find_last_of(b), 11);
|
||||
check(a.find_last_of("54"), 11);
|
||||
check(a.find_last_of('5'), 11);
|
||||
check(a.find_last_of("ZZ"), string::npos);
|
||||
|
||||
check(a.find_first_of("45", 8), 10);
|
||||
|
||||
b = "010";
|
||||
check(a.find_first_not_of("aub"), 0);
|
||||
check(a.find_first_not_of(b), 2);
|
||||
check(a.find_first_not_of("0102"), 3);
|
||||
check(a.find_first_not_of('0'), 1);
|
||||
check(a.find_first_not_of(a), string::npos);
|
||||
|
||||
b = "878";
|
||||
check(a.find_last_not_of("aub"), 14);
|
||||
check(a.find_last_not_of(b), 12);
|
||||
check(a.find_last_not_of("78"), 12);
|
||||
check(a.find_last_not_of('8'), 13);
|
||||
check(a.find_last_not_of(a), string::npos);
|
||||
|
||||
check(a.find_first_not_of("u345", 8), 12);
|
||||
}
|
||||
|
||||
BOOST_AUTO_TEST_CASE(SubstrTest)
|
||||
{
|
||||
string a = lbl;
|
||||
string b;
|
||||
|
||||
b = a.substr(3, 4);
|
||||
validate(b, "3456");
|
||||
|
||||
b = a.substr(5, 20);
|
||||
validate(b, "56789");
|
||||
|
||||
b = a.substr(50, 20);
|
||||
validate(b, "");
|
||||
}
|
||||
|
||||
BOOST_AUTO_TEST_CASE(LoadFromFileTest)
|
||||
{
|
||||
// Find the path of the file 'test.txt' to read from
|
||||
// The file in the same directory
|
||||
|
||||
string path = __FILE__;
|
||||
FB_SIZE_T pos = path.rfind('/');
|
||||
if (pos == string::npos)
|
||||
{
|
||||
pos = path.rfind('\\');
|
||||
if (pos == string::npos)
|
||||
{
|
||||
pos = 0;
|
||||
}
|
||||
else
|
||||
++pos;
|
||||
}
|
||||
else
|
||||
++pos;
|
||||
|
||||
path.resize(pos);
|
||||
path += "test.txt";
|
||||
|
||||
string b;
|
||||
FILE *x = fopen(path.data(), "rt");
|
||||
b.LoadFromFile(x);
|
||||
validate(b, "char lbl[] = \"0123456789\";");
|
||||
b.LoadFromFile(x);
|
||||
validate(b, "");
|
||||
b.LoadFromFile(x);
|
||||
validate(b, "//#define CHECK_FATAL_RANGE_EXCEPTION");
|
||||
fclose(x);
|
||||
}
|
||||
|
||||
BOOST_AUTO_TEST_CASE(BigAssignmentTest)
|
||||
{
|
||||
string a = "Something moderaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaately long";
|
||||
string a1 = a;
|
||||
string b = a + a1;
|
||||
string b1 = b;
|
||||
string c = b + b1;
|
||||
string d = c;
|
||||
validate(d, c.data());
|
||||
}
|
||||
|
||||
BOOST_AUTO_TEST_CASE(CompareTests)
|
||||
{
|
||||
string a = lbl;
|
||||
string b = a;
|
||||
string c = "Aaa";
|
||||
string d = "AB";
|
||||
string e = "Aa";
|
||||
|
||||
BOOST_TEST(a.compare(b) == 0);
|
||||
BOOST_TEST(a.compare(c) < 0);
|
||||
BOOST_TEST(c.compare(a) > 0);
|
||||
|
||||
BOOST_TEST(c.compare(d) > 0);
|
||||
BOOST_TEST(c.compare(e) > 0);
|
||||
|
||||
BOOST_TEST(a.compare(1, 10, b) > 0);
|
||||
BOOST_TEST(a.compare(1, 10, b, 1, 10) == 0);
|
||||
BOOST_TEST(a.compare(lbl) == 0);
|
||||
BOOST_TEST(a.compare(1, 3, lbl + 1, 3) == 0);
|
||||
}
|
||||
|
||||
BOOST_AUTO_TEST_CASE(LTrimTest)
|
||||
{
|
||||
string a = " 011100 ", b;
|
||||
|
||||
b = a;
|
||||
b.ltrim();
|
||||
validate(b, "011100 ");
|
||||
|
||||
b = a;
|
||||
b.rtrim();
|
||||
validate(b, " 011100");
|
||||
|
||||
b = a;
|
||||
b.trim(" 0");
|
||||
validate(b, "111");
|
||||
|
||||
b = a;
|
||||
b.alltrim("02 ");
|
||||
validate(b, "111");
|
||||
|
||||
b = a;
|
||||
b.trim("012");
|
||||
validate(b, " 011100 ");
|
||||
|
||||
validate(a, " 011100 ");
|
||||
}
|
||||
|
||||
BOOST_AUTO_TEST_CASE(RTrimTest)
|
||||
{
|
||||
string a = lbl;
|
||||
a += '\377';
|
||||
string b = a;
|
||||
a += " ";
|
||||
a.rtrim();
|
||||
validate(a, b.c_str());
|
||||
}
|
||||
|
||||
BOOST_AUTO_TEST_CASE(LowerTest)
|
||||
{
|
||||
string a = "AaBbCc", b;
|
||||
|
||||
b = a;
|
||||
b.lower();
|
||||
validate(b, "aabbcc");
|
||||
|
||||
b = a;
|
||||
b.upper();
|
||||
validate(b, "AABBCC");
|
||||
|
||||
validate(a, "AaBbCc");
|
||||
}
|
||||
|
||||
// Constants
|
||||
static constexpr std::string_view EmptyString = "";
|
||||
static constexpr std::string_view SmallStringValue = "123";
|
||||
static constexpr std::string_view BigStringValue = "BiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiigString";
|
||||
static_assert(BigStringValue.length() > Firebird::string::INLINE_BUFFER_SIZE);
|
||||
|
||||
// Utils
|
||||
void checkMovedString(const string& moved)
|
||||
{
|
||||
BOOST_CHECK(moved.c_str() != nullptr);
|
||||
BOOST_CHECK(moved.length() == 0);
|
||||
BOOST_CHECK(std::string_view(moved.data(), moved.length()) == EmptyString);
|
||||
}
|
||||
|
||||
#define testSmallString(str) BOOST_TEST(std::string_view(str.data(), str.length()) == SmallStringValue)
|
||||
|
||||
#define testBigString(str) \
|
||||
BOOST_CHECK(std::string_view(str.data(), str.length()) == BigStringValue)
|
||||
|
||||
|
||||
BOOST_AUTO_TEST_SUITE(MoveSematicsTests)
|
||||
|
||||
// Move only big strings in the same pool
|
||||
BOOST_AUTO_TEST_CASE(DefaultPoolMoveTest)
|
||||
{
|
||||
string sourceString(BigStringValue.data(), BigStringValue.length());
|
||||
|
||||
// Move c'tor
|
||||
string newString(std::move(sourceString));
|
||||
checkMovedString(sourceString);
|
||||
testBigString(newString);
|
||||
|
||||
// Reuse
|
||||
sourceString.assign(BigStringValue.data(), BigStringValue.length());
|
||||
testBigString(sourceString);
|
||||
|
||||
// Move assignment
|
||||
newString = std::move(sourceString);
|
||||
checkMovedString(sourceString);
|
||||
testBigString(newString);
|
||||
}
|
||||
|
||||
BOOST_AUTO_TEST_CASE(NewPoolMoveTest)
|
||||
{
|
||||
AutoMemoryPool pool(MemoryPool::createPool());
|
||||
string sourceString(*pool, BigStringValue.data(), BigStringValue.length());
|
||||
|
||||
// Move c'tor
|
||||
string newString(*pool, std::move(sourceString));
|
||||
checkMovedString(sourceString);
|
||||
testBigString(newString);
|
||||
|
||||
// Reuse
|
||||
sourceString.assign(BigStringValue.data(), BigStringValue.length());
|
||||
testBigString(sourceString);
|
||||
|
||||
// Move assignment
|
||||
newString = std::move(sourceString);
|
||||
checkMovedString(sourceString);
|
||||
testBigString(newString);
|
||||
}
|
||||
|
||||
BOOST_AUTO_TEST_SUITE_END() // MoveSematicsTests
|
||||
|
||||
|
||||
BOOST_AUTO_TEST_SUITE(CannotMoveTests)
|
||||
|
||||
// Do not move
|
||||
BOOST_AUTO_TEST_CASE(DifferentVsDefaultPoolMove)
|
||||
{
|
||||
AutoMemoryPool pool(MemoryPool::createPool());
|
||||
string sourceString(*pool, BigStringValue.data(), BigStringValue.length());
|
||||
|
||||
// Move c'tor
|
||||
string newString(std::move(sourceString));
|
||||
testBigString(sourceString);
|
||||
testBigString(newString);
|
||||
|
||||
// Reuse
|
||||
sourceString.assign(BigStringValue.data(), BigStringValue.length());
|
||||
testBigString(sourceString);
|
||||
|
||||
// Move assignment
|
||||
newString = std::move(sourceString);
|
||||
testBigString(sourceString);
|
||||
testBigString(newString);
|
||||
}
|
||||
|
||||
// Do not move
|
||||
BOOST_AUTO_TEST_CASE(DifferentPoolsMove)
|
||||
{
|
||||
AutoMemoryPool pool1(MemoryPool::createPool());
|
||||
AutoMemoryPool pool2(MemoryPool::createPool());
|
||||
string sourceString(*pool1, BigStringValue.data(), BigStringValue.length());
|
||||
|
||||
// Move c'tor
|
||||
string newString(*pool2, std::move(sourceString));
|
||||
testBigString(sourceString);
|
||||
testBigString(newString);
|
||||
|
||||
// Reuse
|
||||
sourceString.assign(BigStringValue.data(), BigStringValue.length());
|
||||
testBigString(sourceString);
|
||||
|
||||
// Move assignment
|
||||
newString = std::move(sourceString);
|
||||
testBigString(sourceString);
|
||||
testBigString(newString);
|
||||
}
|
||||
|
||||
// Do not move
|
||||
BOOST_AUTO_TEST_CASE(SmallStringMove)
|
||||
{
|
||||
string sourceString(SmallStringValue.data(), SmallStringValue.length());
|
||||
|
||||
// Move c'tor
|
||||
string newString(std::move(sourceString));
|
||||
testSmallString(sourceString);
|
||||
testSmallString(newString);
|
||||
|
||||
// Reuse
|
||||
sourceString.assign(SmallStringValue.data(), SmallStringValue.length());
|
||||
testSmallString(sourceString);
|
||||
|
||||
// Move assign
|
||||
newString = std::move(sourceString);
|
||||
testSmallString(sourceString);
|
||||
testSmallString(newString);
|
||||
}
|
||||
|
||||
BOOST_AUTO_TEST_SUITE_END() // CannotMoveTests
|
||||
|
||||
BOOST_AUTO_TEST_SUITE_END() // StringFunctionalTests
|
||||
BOOST_AUTO_TEST_SUITE_END() // StringSuite
|
3
src/common/tests/test.txt
Normal file
3
src/common/tests/test.txt
Normal file
@ -0,0 +1,3 @@
|
||||
char lbl[] = "0123456789";
|
||||
|
||||
//#define CHECK_FATAL_RANGE_EXCEPTION
|
Loading…
Reference in New Issue
Block a user