Browse Source

Optimize CarlaString; make it fully noexcept safe

tags/1.9.4
falkTX 11 years ago
parent
commit
14524770d2
2 changed files with 101 additions and 68 deletions
  1. +1
    -1
      source/tests/Makefile
  2. +100
    -67
      source/utils/CarlaString.hpp

+ 1
- 1
source/tests/Makefile View File

@@ -56,7 +56,7 @@ ansi-pedantic-test_cxx11: ansi-pedantic-test.c ../backend/Carla*.h

CarlaString: CarlaString.cpp ../utils/CarlaString.hpp
$(CXX) $< $(PEDANTIC_CXX_FLAGS) -o $@
valgrind ./$@
valgrind --leak-check=full ./$@

Engine: Engine.cpp
$(CXX) $< \


+ 100
- 67
source/utils/CarlaString.hpp View File

@@ -38,16 +38,15 @@ public:
/*
* Empty string.
*/
explicit CarlaString()
explicit CarlaString() noexcept
{
_init();
_dup(nullptr);
}

/*
* Simple character.
*/
explicit CarlaString(const char c)
explicit CarlaString(const char c) noexcept
{
char ch[2];
ch[0] = c;
@@ -60,7 +59,7 @@ public:
/*
* Simple char string.
*/
explicit CarlaString(char* const strBuf)
explicit CarlaString(char* const strBuf) noexcept
{
_init();
_dup(strBuf);
@@ -69,7 +68,7 @@ public:
/*
* Simple const char string.
*/
explicit CarlaString(const char* const strBuf)
explicit CarlaString(const char* const strBuf) noexcept
{
_init();
_dup(strBuf);
@@ -78,7 +77,7 @@ public:
/*
* Integer.
*/
explicit CarlaString(const int value)
explicit CarlaString(const int value) noexcept
{
char strBuf[0xff+1];
carla_zeroChar(strBuf, 0xff+1);
@@ -91,7 +90,7 @@ public:
/*
* Unsigned integer, possibly in hexadecimal.
*/
explicit CarlaString(const unsigned int value, const bool hexadecimal = false)
explicit CarlaString(const uint value, const bool hexadecimal = false) noexcept
{
char strBuf[0xff+1];
carla_zeroChar(strBuf, 0xff+1);
@@ -104,7 +103,7 @@ public:
/*
* Long integer.
*/
explicit CarlaString(const long int value)
explicit CarlaString(const long value) noexcept
{
char strBuf[0xff+1];
carla_zeroChar(strBuf, 0xff+1);
@@ -117,7 +116,7 @@ public:
/*
* Long unsigned integer, possibly hexadecimal.
*/
explicit CarlaString(const unsigned long int value, const bool hexadecimal = false)
explicit CarlaString(const ulong value, const bool hexadecimal = false) noexcept
{
char strBuf[0xff+1];
carla_zeroChar(strBuf, 0xff+1);
@@ -130,7 +129,7 @@ public:
/*
* Long long integer.
*/
explicit CarlaString(const long long int value)
explicit CarlaString(const long long value) noexcept
{
char strBuf[0xff+1];
carla_zeroChar(strBuf, 0xff+1);
@@ -143,7 +142,7 @@ public:
/*
* Long long unsigned integer, possibly hexadecimal.
*/
explicit CarlaString(const unsigned long long int value, const bool hexadecimal = false)
explicit CarlaString(const unsigned long long value, const bool hexadecimal = false) noexcept
{
char strBuf[0xff+1];
carla_zeroChar(strBuf, 0xff+1);
@@ -156,7 +155,7 @@ public:
/*
* Single-precision floating point number.
*/
explicit CarlaString(const float value)
explicit CarlaString(const float value) noexcept
{
char strBuf[0xff+1];
carla_zeroChar(strBuf, 0xff+1);
@@ -169,7 +168,7 @@ public:
/*
* Double-precision floating point number.
*/
explicit CarlaString(const double value)
explicit CarlaString(const double value) noexcept
{
char strBuf[0xff+1];
carla_zeroChar(strBuf, 0xff+1);
@@ -185,7 +184,7 @@ public:
/*
* Create string from another string.
*/
CarlaString(const CarlaString& str)
CarlaString(const CarlaString& str) noexcept
{
_init();
_dup(str.fBuffer);
@@ -197,11 +196,17 @@ public:
/*
* Destructor.
*/
~CarlaString()
~CarlaString() noexcept
{
CARLA_SAFE_ASSERT_RETURN(fBuffer != nullptr,);

delete[] fBuffer;
if (fBuffer == _null())
return;

try {
delete[] fBuffer;
} catch(...) {}

fBuffer = nullptr;
}

@@ -235,7 +240,7 @@ public:
/*
* Check if the string contains another string, optionally ignoring case.
*/
bool contains(const char* const strBuf, const bool ignoreCase = false) const
bool contains(const char* const strBuf, const bool ignoreCase = false) const noexcept
{
CARLA_SAFE_ASSERT_RETURN(strBuf != nullptr, false);

@@ -245,6 +250,11 @@ public:
return (strcasestr(fBuffer, strBuf) != nullptr);
#else
CarlaString tmp1(fBuffer), tmp2(strBuf);

// memory allocation failed or empty string(s)
if (tmp1.fBuffer == _null() || tmp2.fBuffer == _null())
return false;

tmp1.toLower();
tmp2.toLower();
return (std::strstr((const char*)tmp1, (const char*)tmp2) != nullptr);
@@ -257,7 +267,7 @@ public:
/*
* Overloaded function.
*/
bool contains(const CarlaString& str, const bool ignoreCase = false) const
bool contains(const CarlaString& str, const bool ignoreCase = false) const noexcept
{
return contains(str.fBuffer, ignoreCase);
}
@@ -297,6 +307,14 @@ public:
return (std::strncmp(fBuffer, prefix, prefixLen) == 0);
}

/*
* Check if the string starts with the string 'prefix'.
*/
bool startsWith(const CarlaString& prefix) const noexcept
{
return startsWith(prefix.fBuffer);
}

/*
* Check if the string ends with the character 'c'.
*/
@@ -322,6 +340,14 @@ public:
return (std::strncmp(fBuffer + (fBufferLen-suffixLen), suffix, suffixLen) == 0);
}

/*
* Check if the string ends with the string 'suffix'.
*/
bool endsWith(const CarlaString& suffix) const noexcept
{
return endsWith(suffix.fBuffer);
}

/*
* Find the first occurrence of character 'c' in the string.
* Returns "length()" if the character is not found.
@@ -467,8 +493,6 @@ public:
{
if (fBuffer[i] == before)
fBuffer[i] = after;
else if (fBuffer[i] == '\0')
break;
}
}

@@ -535,38 +559,40 @@ public:
}

/*
* Return a duplicate string buffer.
* Direct access to the string buffer (read-only).
*/
const char* dup() const
const char* buffer() const noexcept
{
return carla_strdup(fBuffer);
return fBuffer;
}

/*
* Direct access to the string buffer.
* Return a duplicate string buffer.
*/
const char* getBuffer() const noexcept
const char* dup() const
{
return fBuffer;
return carla_strdup(fBuffer);
}

// -------------------------------------------------------------------
// public operators

#if 0
operator const char*() const noexcept
{
return fBuffer;
}
#endif

char& operator[](const size_t pos) const noexcept
{
if (pos < fBufferLen)
return fBuffer[pos];

static char rfallback;
rfallback = '\0';
static char fallback;
fallback = '\0';
carla_safe_assert("pos < fBufferLen", __FILE__, __LINE__);
return rfallback;
return fallback;
}

bool operator==(const char* const strBuf) const noexcept
@@ -589,19 +615,19 @@ public:
return !operator==(str.fBuffer);
}

CarlaString& operator=(const char* const strBuf)
CarlaString& operator=(const char* const strBuf) noexcept
{
_dup(strBuf);

return *this;
}

CarlaString& operator=(const CarlaString& str)
CarlaString& operator=(const CarlaString& str) noexcept
{
return operator=(str.fBuffer);
}

CarlaString& operator+=(const char* const strBuf)
CarlaString& operator+=(const char* const strBuf) noexcept
{
if (strBuf == nullptr)
return *this;
@@ -617,12 +643,12 @@ public:
return *this;
}

CarlaString& operator+=(const CarlaString& str)
CarlaString& operator+=(const CarlaString& str) noexcept
{
return operator+=(str.fBuffer);
}

CarlaString operator+(const char* const strBuf)
CarlaString operator+(const char* const strBuf) noexcept
{
const size_t newBufSize = fBufferLen + ((strBuf != nullptr) ? std::strlen(strBuf) : 0) + 1;
char newBuf[newBufSize];
@@ -635,7 +661,7 @@ public:
return CarlaString(newBuf);
}

CarlaString operator+(const CarlaString& str)
CarlaString operator+(const CarlaString& str) noexcept
{
return operator+(str.fBuffer);
}
@@ -645,7 +671,16 @@ public:
private:
char* fBuffer; // the actual string buffer
size_t fBufferLen; // string length
bool fFirstInit; // true when first initiated

/*
* Static null string.
* Prevents excessive allocations for empty strings.
*/
static char* _null() noexcept
{
static char sNull = '\0';
return &sNull;
}

/*
* Shared init function.
@@ -653,9 +688,8 @@ private:
*/
void _init() noexcept
{
fBuffer = nullptr;
fBuffer = _null();
fBufferLen = 0;
fFirstInit = true;
}

/*
@@ -663,51 +697,50 @@ private:
* Called whenever the string needs to be allocated.
*
* Notes:
* - Allocates string only if first initiated, or if 'strBuf' is not null and new string contents are different
* - Allocates string only if 'strBuf' is not null and new string contents are different
* - If 'strBuf' is null 'size' must be 0
*/
void _dup(const char* const strBuf, const size_t size = 0)
void _dup(const char* const strBuf, const size_t size = 0) noexcept
{
if (strBuf != nullptr)
{
// don't recreate string if contents match
if (fFirstInit || std::strcmp(fBuffer, strBuf) != 0)
if (std::strcmp(fBuffer, strBuf) == 0)
return;

if (fBuffer != _null())
{
if (! fFirstInit)
{
CARLA_SAFE_ASSERT(fBuffer != nullptr);
try {
delete[] fBuffer;
}
} catch(...) {}
}

fBufferLen = (size > 0) ? size : std::strlen(strBuf);
fBuffer = new char[fBufferLen+1];
fBufferLen = (size > 0) ? size : std::strlen(strBuf);

std::strcpy(fBuffer, strBuf);
try {
fBuffer = new char[fBufferLen+1];
}
catch(...) {
_init();
return;
}

fBuffer[fBufferLen] = '\0';
std::strcpy(fBuffer, strBuf);

fFirstInit = false;
}
fBuffer[fBufferLen] = '\0';
}
else
{
CARLA_SAFE_ASSERT(size == 0);

// don't recreate null string
if (fFirstInit || fBufferLen != 0)
{
if (! fFirstInit)
{
CARLA_SAFE_ASSERT(fBuffer != nullptr);
delete[] fBuffer;
}
if (fBuffer == _null())
return;

fBufferLen = 0;
fBuffer = new char[1];
fBuffer[0] = '\0';
CARLA_SAFE_ASSERT(fBuffer != nullptr);
delete[] fBuffer;

fFirstInit = false;
}
_init();
}
}

@@ -718,9 +751,9 @@ private:
// -----------------------------------------------------------------------

static inline
CarlaString operator+(const CarlaString& strBefore, const char* const strBufAfter)
CarlaString operator+(const CarlaString& strBefore, const char* const strBufAfter) noexcept
{
const char* const strBufBefore = (const char*)strBefore;
const char* const strBufBefore = strBefore.buffer();
const size_t newBufSize = strBefore.length() + ((strBufAfter != nullptr) ? std::strlen(strBufAfter) : 0) + 1;
char newBuf[newBufSize];

@@ -731,9 +764,9 @@ CarlaString operator+(const CarlaString& strBefore, const char* const strBufAfte
}

static inline
CarlaString operator+(const char* const strBufBefore, const CarlaString& strAfter)
CarlaString operator+(const char* const strBufBefore, const CarlaString& strAfter) noexcept
{
const char* const strBufAfter = (const char*)strAfter;
const char* const strBufAfter = strAfter.buffer();
const size_t newBufSize = ((strBufBefore != nullptr) ? std::strlen(strBufBefore) : 0) + strAfter.length() + 1;
char newBuf[newBufSize];



Loading…
Cancel
Save