Skip to content

Commit 2d8c006

Browse files
authored
Implementation of move semantics for Firebird::string (#8059)
1 parent f1c4e00 commit 2d8c006

File tree

6 files changed

+804
-676
lines changed

6 files changed

+804
-676
lines changed

src/common/classes/alloc.h

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -232,6 +232,16 @@ friend class ExternalMemoryHandler;
232232
// The same routine, but more easily callable from the debugger
233233
void print_contents(const char* filename, unsigned flags = 0, const char* filter_path = 0) noexcept;
234234

235+
inline bool operator==(const MemoryPool& rhs) const
236+
{
237+
return pool == rhs.pool;
238+
}
239+
240+
inline bool operator!=(const MemoryPool& rhs) const
241+
{
242+
return !operator==(rhs);
243+
}
244+
235245
public:
236246
struct Finalizer
237247
{

src/common/classes/fb_string.cpp

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -396,6 +396,20 @@ extern "C" {
396396
shrinkBuffer();
397397
}
398398

399+
bool AbstractString::baseMove(AbstractString&& rhs)
400+
{
401+
if (getPool() == rhs.getPool() && rhs.inlineBuffer != rhs.stringBuffer)
402+
{
403+
stringBuffer = std::exchange(rhs.stringBuffer, rhs.inlineBuffer);
404+
stringLength = std::exchange(rhs.stringLength, 0);
405+
bufferSize = std::exchange(rhs.bufferSize, INLINE_BUFFER_SIZE);
406+
rhs.inlineBuffer[0] = '\0';
407+
return true;
408+
}
409+
410+
return false;
411+
}
412+
399413
void AbstractString::printf(const char* format,...)
400414
{
401415
va_list params;

src/common/classes/fb_string.h

Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,7 @@
3232
#include <stdio.h>
3333
#include <string.h>
3434
#include <stdarg.h>
35+
#include <utility>
3536

3637
#include "firebird.h"
3738
#include "fb_types.h"
@@ -203,6 +204,27 @@ namespace Firebird
203204
memcpy(stringBuffer, s, l);
204205
}
205206

207+
AbstractString(const size_type limit, AbstractString&& rhs) :
208+
max_length(static_cast<internal_size_type>(limit))
209+
{
210+
// We can move only string with default pool
211+
if (!baseMove(std::forward<AbstractString>(rhs)))
212+
{
213+
initialize(rhs.length());
214+
memcpy(stringBuffer, rhs.c_str(), stringLength);
215+
}
216+
}
217+
218+
AbstractString(const size_type limit, MemoryPool& p, AbstractString&& rhs)
219+
: AutoStorage(p), max_length(static_cast<internal_size_type>(limit))
220+
{
221+
if (!baseMove(std::forward<AbstractString>(rhs)))
222+
{
223+
initialize(rhs.length());
224+
memcpy(stringBuffer, rhs.c_str(), stringLength);
225+
}
226+
}
227+
206228
pointer modify()
207229
{
208230
return stringBuffer;
@@ -223,6 +245,8 @@ namespace Firebird
223245

224246
void baseTrim(const TrimType whereTrim, const_pointer toTrim);
225247

248+
bool baseMove(AbstractString&& rhs);
249+
226250
size_type getMaxLength() const
227251
{
228252
return max_length;
@@ -676,6 +700,10 @@ namespace Firebird
676700
AbstractString(Comparator::getMaxLength(), p, s, static_cast<size_type>(s ? strlen(s) : 0)) {}
677701
StringBase(MemoryPool& p, const char_type* s, size_type l) :
678702
AbstractString(Comparator::getMaxLength(), p, s, l) {}
703+
StringBase(StringType&& rhs) :
704+
AbstractString(Comparator::getMaxLength(), std::forward<AbstractString>(rhs)) {}
705+
StringBase(MemoryPool& p, StringType&& rhs) :
706+
AbstractString(Comparator::getMaxLength(), p, std::forward<AbstractString>(rhs)) {}
679707

680708
static size_type max_length()
681709
{
@@ -754,6 +782,25 @@ namespace Firebird
754782
{
755783
return add(&c, 1);
756784
}
785+
StringType& operator=(StringType&& rhs)
786+
{
787+
// baseMove do not clear the buffer so do it in this method
788+
char_type* backup = nullptr;
789+
if (stringBuffer != inlineBuffer)
790+
backup = stringBuffer;
791+
792+
if (baseMove(std::forward<AbstractString>(rhs)))
793+
{
794+
// The dynamic buffer has been replaced, so clear the old one
795+
delete[] backup;
796+
}
797+
else
798+
{
799+
// Cannot move, do the base assignment
800+
assign(rhs.c_str(), rhs.length());
801+
}
802+
return *this;
803+
}
757804

758805
StringBase<StringComparator> ToString() const
759806
{

0 commit comments

Comments
 (0)