Browse Source

Split carla classes from utils; add print test

tags/1.9.4
falkTX 12 years ago
parent
commit
2aef20ecf4
14 changed files with 951 additions and 770 deletions
  1. +0
    -4
      source/Makefile.mk
  2. +3
    -0
      source/backend/engine/carla_engine.pro
  3. +41
    -18
      source/includes/carla_defines.hpp
  4. +1
    -3
      source/tests/CarlaString.cpp
  5. +6
    -4
      source/tests/Makefile
  6. +27
    -0
      source/tests/Print.cpp
  7. +2
    -2
      source/tests/RtList.cpp
  8. +1
    -3
      source/tests/Thread.cpp
  9. +12
    -11
      source/utils/carla_backend_utils.hpp
  10. +5
    -5
      source/utils/carla_juce_utils.hpp
  11. +112
    -0
      source/utils/carla_mutex.hpp
  12. +412
    -0
      source/utils/carla_string.hpp
  13. +253
    -0
      source/utils/carla_thread.hpp
  14. +76
    -720
      source/utils/carla_utils.hpp

+ 0
- 4
source/Makefile.mk View File

@@ -35,10 +35,6 @@ BUILD_C_FLAGS = $(BASE_FLAGS) -std=c99 $(CFLAGS)
BUILD_CXX_FLAGS = $(BASE_FLAGS) -std=c++0x $(CXXFLAGS)
LINK_FLAGS = $(LDFLAGS)

ifneq ($(DEBUG),true)
BUILD_CXX_FLAGS += -DQT_NO_DEBUG -DQT_NO_DEBUG_STREAM -DQT_NO_DEBUG_OUTPUT
endif

# --------------------------------------------------------------
# Modify to enable/disable specific features



+ 3
- 0
source/backend/engine/carla_engine.pro View File

@@ -51,6 +51,9 @@ HEADERS += \
HEADERS += \
../../includes/carla_defines.hpp \
../../includes/carla_midi.h \
../../utils/carla_mutex.hpp \
../../utils/carla_string.hpp \
../../utils/carla_thread.hpp \
../../utils/carla_utils.hpp \
../../utils/carla_backend_utils.hpp \
../../utils/carla_juce_utils.hpp \


+ 41
- 18
source/includes/carla_defines.hpp View File

@@ -18,15 +18,38 @@
#ifndef __CARLA_DEFINES_HPP__
#define __CARLA_DEFINES_HPP__

#include <QtCore/Qt>
// Check OS
#if defined(__APPLE__)
# define CARLA_OS_MAC
#elif defined(__HAIKU__)
# define CARLA_OS_HAIKU
#elif defined(__linux__) || defined(__linux) || defined(QTCREATOR_TEST)
# define CARLA_OS_LINUX
#elif defined(WIN64) || defined(_WIN64) || defined(__WIN64__)
# define CARLA_OS_WIN64
#elif defined(WIN32) || defined(_WIN32) || defined(__WIN32__)
# define CARLA_OS_WIN32
#else
# warning Unsupported platform!
#endif

// If the compiler can't do C++11 lambdas, it most likely doesn't know about nullptr either
#ifndef Q_COMPILER_LAMBDA
# define nullptr (0)
#if defined(CARLA_OS_WIN32) || defined(CARLA_OS_WIN64)
# define CARLA_OS_WIN
#elif ! defined(CARLA_OS_HAIKU)
# define CARLA_OS_UNIX
#endif

// Check for C++11 support
#if defined(HAVE_CPP11_SUPPORT) || defined(QTCREATOR_TEST)
# define CARLA_CPP11_SUPPORT
#elif defined(__GNUC__) && defined(__GXX_EXPERIMENTAL_CXX0X__)
# if (__GNUC__ * 100 + __GNUC_MINOR__) >= 405
# define CARLA_CPP11_SUPPORT
# endif
#endif

// Common includes
#ifdef Q_OS_WIN
#ifdef CARLA_OS_WIN
# include <winsock2.h>
# include <windows.h>
#else
@@ -36,13 +59,13 @@
# endif
#endif

// Define various string format types, needed for qDebug/Warning/Critical sections
#if defined(Q_OS_WIN64)
// Define various string format types
#if defined(CARLA_OS_WIN64)
# define P_INT64 "%I64i"
# define P_INTPTR "%I64i"
# define P_UINTPTR "%I64x"
# define P_SIZE "%I64u"
#elif defined(Q_OS_WIN32)
#elif defined(CARLA_OS_WIN32)
# define P_INT64 "%I64i"
# define P_INTPTR "%i"
# define P_UINTPTR "%x"
@@ -60,14 +83,14 @@
#endif

// Define BINARY_NATIVE
#if defined(Q_OS_HAIKU) || defined(Q_OS_UNIX)
#if defined(CARLA_OS_HAIKU) || defined(CARLA_OS_UNIX)
# ifdef __LP64__
# define BINARY_NATIVE BINARY_POSIX64
# else
# define BINARY_NATIVE BINARY_POSIX32
# endif
#elif defined(Q_OS_WIN)
# ifdef Q_OS_WIN64
#elif defined(CARLA_OS_WIN)
# ifdef CARLA_OS_WIN64
# define BINARY_NATIVE BINARY_WIN64
# else
# define BINARY_NATIVE BINARY_WIN32
@@ -79,20 +102,20 @@

// Define CARLA_ASSERT*
#ifdef NDEBUG
# define CARLA_ASSERT(cond) ((!(cond)) ? carla_assert(#cond, __FILE__, __LINE__) : qt_noop())
# define CARLA_ASSERT_INT(cond, value) ((!(cond)) ? carla_assert_int(#cond, __FILE__, __LINE__, value) : qt_noop())
# define CARLA_ASSERT_INT2(cond, v1, v2) ((!(cond)) ? carla_assert_int2(#cond, __FILE__, __LINE__, v1, v2) : qt_noop())
# define CARLA_ASSERT(cond) ((!(cond)) ? carla_assert(#cond, __FILE__, __LINE__) : pass())
# define CARLA_ASSERT_INT(cond, value) ((!(cond)) ? carla_assert_int(#cond, __FILE__, __LINE__, value) : pass())
# define CARLA_ASSERT_INT2(cond, v1, v2) ((!(cond)) ? carla_assert_int2(#cond, __FILE__, __LINE__, v1, v2) : pass())
#else
# define CARLA_ASSERT(cond) Q_ASSERT(cond)
# define CARLA_ASSERT_INT(cond, value) Q_ASSERT(cond)
# define CARLA_ASSERT_INT2(cond, v1, v2) Q_ASSERT(cond)
# define CARLA_ASSERT(cond) assert(cond)
# define CARLA_ASSERT_INT(cond, value) assert(cond)
# define CARLA_ASSERT_INT2(cond, v1, v2) assert(cond)
#endif

// Define CARLA_EXPORT
#ifdef BUILD_BRIDGE
# define CARLA_EXPORT extern "C"
#else
# if defined(Q_OS_WIN) && ! defined(__WINE__)
# if defined(CARLA_OS_WIN) && ! defined(__WINE__)
# define CARLA_EXPORT extern "C" __declspec (dllexport)
# else
# define CARLA_EXPORT extern "C" __attribute__ ((visibility("default")))


+ 1
- 3
source/tests/CarlaString.cpp View File

@@ -15,9 +15,7 @@
* For a full copy of the GNU General Public License see the GPL.txt file
*/

#include "carla_utils.hpp"

#include <cassert>
#include "carla_string.hpp"

int main()
{


+ 6
- 4
source/tests/Makefile View File

@@ -10,10 +10,8 @@ include ../Makefile.mk

BUILD_CXX_FLAGS += -I../backend -I../includes -I../utils
# BUILD_CXX_FLAGS += -I/opt/mingw32/include
BUILD_CXX_FLAGS += $(shell pkg-config --cflags QtCore)
LINK_FLAGS += $(shell pkg-config --libs QtCore)

TARGETS = CarlaString RtList Thread GL_
TARGETS = CarlaString RtList Thread Print_

all: $(TARGETS) RUN

@@ -23,17 +21,21 @@ CarlaString: CarlaString.cpp
$(CXX) $^ $(BUILD_CXX_FLAGS) $(LINK_FLAGS) -o $@

RtList: RtList.cpp ../libs/rtmempool.a
$(CXX) $^ $(BUILD_CXX_FLAGS) $(LINK_FLAGS) -o $@
$(CXX) $^ $(BUILD_CXX_FLAGS) $(LINK_FLAGS) -pthread -lpthread -o $@

Thread: Thread.cpp
$(CXX) $^ $(BUILD_CXX_FLAGS) $(LINK_FLAGS) -pthread -lpthread -o $@

Print_: Print.cpp
$(CXX) $^ $(BUILD_CXX_FLAGS) $(LINK_FLAGS) -o Print # $@

GL_: GL.cpp
# $(CXX) $^ $(BUILD_CXX_FLAGS) -I../backend/engine/plugin -I../libs/distrho-plugin-toolkit $(LINK_FLAGS) -lgdi32 -lopengl32 -lole32 -luuid -lws2_32 -o GL # $@
$(CXX) $^ $(BUILD_CXX_FLAGS) -I../backend/engine/plugin -I../libs/distrho-plugin-toolkit $(LINK_FLAGS) -lGL -lGLU -o GL # $@

RUN: $(TARGETS)
# ./CarlaString && ./RtList && ./Thread
./Print
# ./GL

# --------------------------------------------------------------


+ 27
- 0
source/tests/Print.cpp View File

@@ -0,0 +1,27 @@
/*
* Carla Tests
* Copyright (C) 2013 Filipe Coelho <falktx@falktx.com>
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License as
* published by the Free Software Foundation; either version 2 of
* the License, or any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* For a full copy of the GNU General Public License see the GPL.txt file
*/

#include "carla_utils.hpp"

int main()
{
carla_debug("DEBUG");
carla_stdout("STDOUT");
carla_stderr("STDERR");
carla_stderr2("STDERR2");
return 0;
}

+ 2
- 2
source/tests/RtList.cpp View File

@@ -15,10 +15,10 @@
* For a full copy of the GNU General Public License see the GPL.txt file
*/

#include "carla_utils.hpp"
#include "rt_list.hpp"

#include <cassert>
#include "carla_string.hpp"
#include "carla_mutex.hpp"

const unsigned short MIN_RT_EVENTS = 152;
const unsigned short MAX_RT_EVENTS = 512;


+ 1
- 3
source/tests/Thread.cpp View File

@@ -15,9 +15,7 @@
* For a full copy of the GNU General Public License see the GPL.txt file
*/

#include "carla_utils.hpp"

#include <cassert>
#include "carla_thread.hpp"

class MyThread : public CarlaThread
{


+ 12
- 11
source/utils/carla_backend_utils.hpp View File

@@ -44,7 +44,7 @@ const char* BinaryType2Str(const BinaryType& type)
return "BINARY_OTHER";
}

qWarning("CarlaBackend::BinaryType2Str(%i) - invalid type", type);
carla_stderr("CarlaBackend::BinaryType2Str(%i) - invalid type", type);
return nullptr;
}

@@ -73,7 +73,7 @@ const char* PluginType2Str(const PluginType& type)
return "PLUGIN_SFZ";
}

qWarning("CarlaBackend::PluginType2Str(%i) - invalid type", type);
carla_stderr("CarlaBackend::PluginType2Str(%i) - invalid type", type);
return nullptr;
}

@@ -102,7 +102,7 @@ const char* PluginCategory2Str(const PluginCategory& category)
return "PLUGIN_CATEGORY_OTHER";
}

qWarning("CarlaBackend::PluginCategory2Str(%i) - invalid category", category);
carla_stderr("CarlaBackend::PluginCategory2Str(%i) - invalid category", category);
return nullptr;
}

@@ -129,7 +129,7 @@ const char* ParameterType2Str(const ParameterType& type)
#endif
}

qWarning("CarlaBackend::ParameterType2Str(%i) - invalid type", type);
carla_stderr("CarlaBackend::ParameterType2Str(%i) - invalid type", type);
return nullptr;
}

@@ -156,7 +156,7 @@ const char* InternalParametersIndex2Str(const InternalParametersIndex& index)
return "PARAMETER_MAX";
}

qWarning("CarlaBackend::InternalParametersIndex2Str(%i) - invalid index", index);
carla_stderr("CarlaBackend::InternalParametersIndex2Str(%i) - invalid index", index);
return nullptr;
}

@@ -225,7 +225,7 @@ const char* OptionsType2Str(const OptionsType& type)
#endif
}

qWarning("CarlaBackend::OptionsType2Str(%i) - invalid type", type);
carla_stderr("CarlaBackend::OptionsType2Str(%i) - invalid type", type);
return nullptr;
}

@@ -282,7 +282,7 @@ const char* CallbackType2Str(const CallbackType& type)
return "CALLBACK_QUIT";
}

qWarning("CarlaBackend::CallbackType2Str(%i) - invalid type", type);
carla_stderr("CarlaBackend::CallbackType2Str(%i) - invalid type", type);
return nullptr;
}

@@ -303,7 +303,7 @@ const char* ProcessMode2Str(const ProcessMode& mode)
return "PROCESS_MODE_BRIDGE";
}

qWarning("CarlaBackend::ProcessModeType2Str(%i) - invalid type", mode);
carla_stderr("CarlaBackend::ProcessModeType2Str(%i) - invalid type", mode);
return nullptr;
}

@@ -312,7 +312,7 @@ const char* ProcessMode2Str(const ProcessMode& mode)
static inline
uintptr_t getAddressFromPointer(void* ptr)
{
qDebug("CarlaBackend::getAddressFromPointer(%p)", ptr);
carla_debug("CarlaBackend::getAddressFromPointer(%p)", ptr);
CARLA_ASSERT(ptr != nullptr);

uintptr_t* addr = (uintptr_t*)&ptr;
@@ -333,7 +333,7 @@ void* getPointerFromAddress(uintptr_t& addr)
static inline
const char* getPluginTypeString(const PluginType& type)
{
qDebug("CarlaBackend::getPluginTypeString(%s)", PluginType2Str(type));
carla_debug("CarlaBackend::getPluginTypeString(%s)", PluginType2Str(type));

switch (type)
{
@@ -357,6 +357,7 @@ const char* getPluginTypeString(const PluginType& type)
return "SFZ";
}

carla_stderr("CarlaBackend::getPluginTypeString(%i) - invalid type", type);
return "NONE";
}

@@ -365,7 +366,7 @@ const char* getPluginTypeString(const PluginType& type)
static inline
PluginCategory getPluginCategoryFromName(const char* const name)
{
qDebug("CarlaBackend::getPluginCategoryFromName(\"%s\")", name);
carla_debug("CarlaBackend::getPluginCategoryFromName(\"%s\")", name);
CARLA_ASSERT(name);

if (! name)


+ 5
- 5
source/utils/carla_juce_utils.hpp View File

@@ -19,9 +19,9 @@
#ifndef __CARLA_JUCE_UTILS_HPP__
#define __CARLA_JUCE_UTILS_HPP__

#include "carla_defines.hpp"
#include "carla_utils.hpp"

#include <cassert>
#include <algorithm>

#define CARLA_DECLARE_NON_COPYABLE(className) \
className (const className&);\
@@ -82,7 +82,7 @@ public:
{
if (--(getCounter().numObjects) < 0)
{
qWarning("*** Dangling pointer deletion! Class: '%s'", getLeakedObjectClassName());
carla_stderr("*** Dangling pointer deletion! Class: '%s'", getLeakedObjectClassName());

/** If you hit this, then you've managed to delete more instances of this class than you've
created.. That indicates that you're deleting some dangling pointers.
@@ -113,7 +113,7 @@ private:
{
if (numObjects > 0)
{
qWarning("*** Leaked objects detected: %i instance(s) of class '%s'", numObjects, getLeakedObjectClassName());
carla_stderr("*** Leaked objects detected: %i instance(s) of class '%s'", numObjects, getLeakedObjectClassName());

/** If you hit this, then you've leaked one or more objects of the type specified by
the 'OwnerClass' template parameter - the name should have been printed by the line above.
@@ -313,7 +313,7 @@ private:
return this;
}

#if ! defined(Q_CC_MSVC) // (MSVC can't deal with multiple copy constructors)
#if ! defined(CARLA_CC_MSVC) // (MSVC can't deal with multiple copy constructors)
/* These are private to stop people accidentally copying a const ScopedPointer (the compiler
would let you do so by implicitly casting the source to its raw object pointer).



+ 112
- 0
source/utils/carla_mutex.hpp View File

@@ -0,0 +1,112 @@
/*
* Carla common utils
* Copyright (C) 2011-2013 Filipe Coelho <falktx@falktx.com>
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License as
* published by the Free Software Foundation; either version 2 of
* the License, or any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* For a full copy of the GNU General Public License see the GPL.txt file
*/

#ifndef __CARLA_MUTEX_HPP__
#define __CARLA_MUTEX_HPP__

#include "carla_juce_utils.hpp"

// #define CPP11_MUTEX

#ifdef CPP11_MUTEX
# include <mutex>
#else
# include <pthread.h>
#endif

// -------------------------------------------------
// CarlaMutex class

class CarlaMutex
{
public:
CarlaMutex()
{
#ifndef CPP11_MUTEX
pthread_mutex_init(&pmutex, nullptr);
#endif
}

~CarlaMutex()
{
#ifndef CPP11_MUTEX
pthread_mutex_destroy(&pmutex);
#endif
}

void lock()
{
#ifdef CPP11_MUTEX
cmutex.lock();
#else
pthread_mutex_lock(&pmutex);
#endif
}

bool tryLock()
{
#ifdef CPP11_MUTEX
return cmutex.try_lock();
#else
return (pthread_mutex_trylock(&pmutex) == 0);
#endif
}

void unlock()
{
#ifdef CPP11_MUTEX
cmutex.unlock();
#else
pthread_mutex_unlock(&pmutex);
#endif
}

class ScopedLocker
{
public:
ScopedLocker(CarlaMutex* const mutex)
: fMutex(mutex)
{
fMutex->lock();
}

~ScopedLocker()
{
fMutex->unlock();
}

private:
CarlaMutex* const fMutex;

CARLA_PREVENT_HEAP_ALLOCATION
CARLA_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR(ScopedLocker)
};

private:
#ifdef CPP11_MUTEX
std::mutex cmutex;
#else
pthread_mutex_t pmutex;
#endif

CARLA_PREVENT_HEAP_ALLOCATION
CARLA_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR(CarlaMutex)
};

// -------------------------------------------------

#endif // __CARLA_MUTEX_HPP__

+ 412
- 0
source/utils/carla_string.hpp View File

@@ -0,0 +1,412 @@
/*
* Carla common utils
* Copyright (C) 2011-2013 Filipe Coelho <falktx@falktx.com>
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License as
* published by the Free Software Foundation; either version 2 of
* the License, or any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* For a full copy of the GNU General Public License see the GPL.txt file
*/

#ifndef __CARLA_STRING_HPP__
#define __CARLA_STRING_HPP__

#include "carla_juce_utils.hpp"

// -------------------------------------------------
// CarlaString class

class CarlaString
{
public:
// ---------------------------------------------
// constructors (no explicit conversions allowed)

explicit CarlaString()
{
_init();
_dup(nullptr);
}

explicit CarlaString(char* const strBuf)
{
_init();
_dup(strBuf);
}

explicit CarlaString(const char* const strBuf)
{
_init();
_dup(strBuf);
}

explicit CarlaString(const int value)
{
const size_t strBufSize = std::abs(value/10) + 3;
char strBuf[strBufSize];
std::snprintf(strBuf, strBufSize, "%d", value);

_init();
_dup(strBuf, strBufSize);
}

explicit CarlaString(const unsigned int value, const bool hexadecimal = false)
{
const size_t strBufSize = value/10 + 2 + (hexadecimal ? 2 : 0);
char strBuf[strBufSize];
std::snprintf(strBuf, strBufSize, hexadecimal ? "0x%x" : "%u", value);

_init();
_dup(strBuf, strBufSize);
}

explicit CarlaString(const long int value)
{
const size_t strBufSize = std::abs(value/10) + 3;
char strBuf[strBufSize];
std::snprintf(strBuf, strBufSize, "%ld", value);

_init();
_dup(strBuf, strBufSize);
}

explicit CarlaString(const unsigned long int value, const bool hexadecimal = false)
{
const size_t strBufSize = value/10 + 2 + (hexadecimal ? 2 : 0);
char strBuf[strBufSize];
std::snprintf(strBuf, strBufSize, hexadecimal ? "0x%lx" : "%lu", value);

_init();
_dup(strBuf, strBufSize);
}

explicit CarlaString(const float value)
{
char strBuf[0xff];
std::snprintf(strBuf, 0xff, "%f", value);

_init();
_dup(strBuf);
}

explicit CarlaString(const double value)
{
char strBuf[0xff];
std::snprintf(strBuf, 0xff, "%g", value);

_init();
_dup(strBuf);
}

// ---------------------------------------------
// non-explicit constructor

CarlaString(const CarlaString& str)
{
_init();
_dup(str.buffer);
}

// ---------------------------------------------
// deconstructor

~CarlaString()
{
CARLA_ASSERT(buffer);

delete[] buffer;
}

// ---------------------------------------------
// public methods

size_t length() const
{
return bufferLen;
}

bool isEmpty() const
{
return (bufferLen == 0);
}

bool isNotEmpty() const
{
return (bufferLen != 0);
}

#if __USE_GNU
bool contains(const char* const strBuf, const bool ignoreCase = false) const
{
if (strBuf == nullptr)
return false;

if (ignoreCase)
return (strcasestr(buffer, strBuf) != nullptr);
else
return (std::strstr(buffer, strBuf) != nullptr);
}

bool contains(const CarlaString& str, const bool ignoreCase = false) const
{
return contains(str.buffer, ignoreCase);
}
#else
bool contains(const char* const strBuf) const
{
if (strBuf == nullptr)
return false;

return (std::strstr(buffer, strBuf) != nullptr);
}

bool contains(const CarlaString& str) const
{
return contains(str.buffer);
}
#endif

bool isDigit(const size_t pos) const
{
if (pos >= bufferLen)
return false;

return (buffer[pos] >= '0' && buffer[pos] <= '9');
}

void clear()
{
truncate(0);
}

void replace(const char before, const char after)
{
if (after == '\0')
return;

for (size_t i=0; i < bufferLen; i++)
{
if (buffer[i] == before)
buffer[i] = after;
else if (buffer[i] == '\0')
break;
}
}

void truncate(const size_t n)
{
if (n >= bufferLen)
return;

for (size_t i=n; i < bufferLen; i++)
buffer[i] = '\0';

bufferLen = n;
}

void toBasic()
{
for (size_t i=0; i < bufferLen; i++)
{
if (buffer[i] >= '0' && buffer[i] <= '9')
continue;
if (buffer[i] >= 'A' && buffer[i] <= 'Z')
continue;
if (buffer[i] >= 'a' && buffer[i] <= 'z')
continue;
if (buffer[i] == '_')
continue;

buffer[i] = '_';
}
}

void toLower()
{
static const char charDiff = 'a' - 'A';

for (size_t i=0; i < bufferLen; i++)
{
if (buffer[i] >= 'A' && buffer[i] <= 'Z')
buffer[i] += charDiff;
}
}

void toUpper()
{
static const char charDiff = 'a' - 'A';

for (size_t i=0; i < bufferLen; i++)
{
if (buffer[i] >= 'a' && buffer[i] <= 'z')
buffer[i] -= charDiff;
}
}

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

operator const char*() const
{
return buffer;
}

char& operator[](const size_t pos)
{
return buffer[pos];
}

bool operator==(const char* const strBuf) const
{
return (strBuf != nullptr && std::strcmp(buffer, strBuf) == 0);
}

bool operator==(const CarlaString& str) const
{
return operator==(str.buffer);
}

bool operator!=(const char* const strBuf) const
{
return !operator==(strBuf);
}

bool operator!=(const CarlaString& str) const
{
return !operator==(str.buffer);
}

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

return *this;
}

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

CarlaString& operator+=(const char* const strBuf)
{
const size_t newBufSize = bufferLen + ((strBuf != nullptr) ? std::strlen(strBuf) : 0) + 1;
char newBuf[newBufSize];

std::strcpy(newBuf, buffer);
std::strcat(newBuf, strBuf);

_dup(newBuf, newBufSize-1);

return *this;
}

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

CarlaString operator+(const char* const strBuf)
{
const size_t newBufSize = bufferLen + ((strBuf != nullptr) ? std::strlen(strBuf) : 0) + 1;
char newBuf[newBufSize];

std::strcpy(newBuf, buffer);
std::strcat(newBuf, strBuf);

return CarlaString(newBuf);
}

CarlaString operator+(const CarlaString& str)
{
return operator+(str.buffer);
}

// ---------------------------------------------

private:
char* buffer;
size_t bufferLen;
bool firstInit;

void _init()
{
buffer = nullptr;
bufferLen = 0;
firstInit = true;
}

// allocate string strBuf if not null
// size > 0 only if strBuf is valid
void _dup(const char* const strBuf, const size_t size = 0)
{
if (strBuf != nullptr)
{
// don't recreate string if contents match
if (firstInit || std::strcmp(buffer, strBuf) != 0)
{
if (! firstInit)
{
CARLA_ASSERT(buffer);
delete[] buffer;
}

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

std::strcpy(buffer, strBuf);

buffer[bufferLen] = '\0';

firstInit = false;
}
}
else
{
CARLA_ASSERT(size == 0);

// don't recreate null string
if (firstInit || bufferLen != 0)
{
if (! firstInit)
{
CARLA_ASSERT(buffer);
delete[] buffer;
}

bufferLen = 0;
buffer = new char[1];
buffer[0] = '\0';

firstInit = false;
}
}
}

CARLA_LEAK_DETECTOR(CarlaString)
CARLA_PREVENT_HEAP_ALLOCATION
};

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

std::strcpy(newBuf, strBufBefore);
std::strcat(newBuf, strBufAfter);

return CarlaString(newBuf);
}

// -------------------------------------------------

#endif // __CARLA_UTILS_HPP__

+ 253
- 0
source/utils/carla_thread.hpp View File

@@ -0,0 +1,253 @@
/*
* Carla common utils
* Copyright (C) 2011-2013 Filipe Coelho <falktx@falktx.com>
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License as
* published by the Free Software Foundation; either version 2 of
* the License, or any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* For a full copy of the GNU General Public License see the GPL.txt file
*/

#ifndef __CARLA_THREAD_HPP__
#define __CARLA_THREAD_HPP__

#include "carla_juce_utils.hpp"

// #define CPP11_MUTEX

#ifdef CPP11_THREAD
# include <thread>
#else
# include <pthread.h>
#endif

// -------------------------------------------------
// CarlaThread class

class CarlaThread
{
public:
CarlaThread()
: fStarted(false),
fFinished(false)
{
#ifdef CPP11_MUTEX
cthread = nullptr;
#else
_zero();
pthread_attr_init(&pthreadAttr);
pthread_attr_setdetachstate(&pthreadAttr, PTHREAD_CREATE_JOINABLE);
#endif
}

~CarlaThread()
{
CARLA_ASSERT(! isRunning());

if (isRunning())
terminate();

#ifdef CPP11_MUTEX
if (cthread != nullptr)
{
cthread->join();
delete cthread;
}
#else
if (! _isNull())
pthread_join(pthreadId, nullptr);

pthread_attr_destroy(&pthreadAttr);
#endif
}

bool start()
{
CARLA_ASSERT(! isRunning());

if (isRunning())
return false;

fStarted = false;
fFinished = false;

#ifdef CPP11_MUTEX
CARLA_ASSERT(cthread == nullptr);

if (cthread != nullptr)
return false;

cthread = new std::thread(_cthreadRoutine, this);
CARLA_ASSERT(cthread->joinable());

return true;
#else
CARLA_ASSERT(_isNull());

if (! _isNull())
return false;

return (pthread_create(&pthreadId, &pthreadAttr, _pthreadRoutine, this) == 0);
#endif
}

bool stop(const unsigned int timeout = 0)
{
CARLA_ASSERT(isRunning());

if (! isRunning())
return true;

#ifdef CPP11_MUTEX
if (cthread == nullptr)
return true;
#else
if (_isNull())
return true;
#endif

if (timeout == 0)
{
#ifdef CPP11_MUTEX
cthread->join();
#else
pthread_join(pthreadId, nullptr);
#endif
}
else
{
for (unsigned int i=0; i < timeout && ! fFinished; i++)
carla_msleep(1);
}

if (! fFinished)
return false;

#ifdef CPP11_MUTEX
delete cthread;
cthread = nullptr;
#else
_zero();
#endif

return true;
}

void terminate()
{
CARLA_ASSERT(isRunning());

if (fFinished)
return;

#ifdef CPP11_MUTEX
if (cthread == nullptr)
return;
#else
if (_isNull())
return;
#endif

#ifdef CPP11_MUTEX
cthread->detach();
//cthread->join();
delete cthread;
cthread = nullptr;
#else
pthread_detach(pthreadId);
//pthread_join(pthreadId, nullptr);
pthread_cancel(pthreadId);
_zero();
#endif

fFinished = true;
}

bool isRunning()
{
return (fStarted && ! fFinished);
}

void waitForStarted(const unsigned int timeout = 0) // ms
{
if (fStarted)
return;

if (timeout == 0)
{
while (! fStarted) {}
}
else
{
for (unsigned int i=0; i < timeout && ! fStarted; i++)
carla_msleep(1);
}
}

void waitForFinished()
{
waitForStarted();
stop(0);
}

protected:
virtual void run() = 0;

private:
bool fStarted;
bool fFinished;

void handleRoutine()
{
fStarted = true;
run();
fFinished = true;
}

#ifdef CPP11_MUTEX
std::thread* cthread;

static void _cthreadRoutine(CarlaThread* const _this_)
{
_this_->handleRoutine();
}
#else
pthread_t pthreadId;
pthread_attr_t pthreadAttr;

static void* _pthreadRoutine(void* const _this_)
{
((CarlaThread*)_this_)->handleRoutine();
pthread_exit(nullptr);
return nullptr;
}

bool _isNull()
{
#ifdef CARLA_OS_WIN
return (pthreadId.p == nullptr);
#else
return (pthreadId == 0);
#endif
}

void _zero()
{
carla_zeroStruct<pthread_t>(pthreadId);
}
#endif

CARLA_PREVENT_HEAP_ALLOCATION
CARLA_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR(CarlaThread)
};

// -------------------------------------------------

#endif // __CARLA_THREAD_HPP__

+ 76
- 720
source/utils/carla_utils.hpp View File

@@ -18,47 +18,101 @@
#ifndef __CARLA_UTILS_HPP__
#define __CARLA_UTILS_HPP__

#include "carla_juce_utils.hpp"
#include "carla_defines.hpp"

#include <cassert>
#include <cstdarg>
#include <cstdio>
#include <cstdlib>
#include <cstring>

// #define CPP11_MUTEX

#ifdef CPP11_MUTEX
# include <mutex>
# include <thread>
#else
# include <pthread.h>
#endif

#if defined(Q_OS_HAIKU)
#if defined(CARLA_OS_HAIKU)
# include <kernel/OS.h>
#elif defined(Q_OS_LINUX)
#elif defined(CARLA_OS_LINUX)
# include <sys/prctl.h>
# include <linux/prctl.h>
#endif

// -------------------------------------------------
// misc functions

static inline
const char* bool2str(const bool yesNo)
{
return yesNo ? "true" : "false";
}

static inline
void pass() {}

// -------------------------------------------------
// string print functions

#ifndef DEBUG
# define carla_debug(...)
#else
static inline
void carla_debug(const char* const fmt, ...)
{
std::va_list args;
va_start(args, fmt);
std::fprintf(stdout, "\x1b[30;1m");
std::vfprintf(stdout, fmt, args);
std::fprintf(stdout, "\x1b[0m\n");
va_end(args);
}
#endif

static inline
void carla_stdout(const char* const fmt, ...)
{
std::va_list args;
va_start(args, fmt);
std::vfprintf(stdout, fmt, args);
std::fprintf(stdout, "\n");
va_end(args);
}

static inline
void carla_stderr(const char* const fmt, ...)
{
std::va_list args;
va_start(args, fmt);
std::vfprintf(stderr, fmt, args);
std::fprintf(stderr, "\n");
va_end(args);
}

static inline
void carla_stderr2(const char* const fmt, ...)
{
std::va_list args;
va_start(args, fmt);
std::fprintf(stderr, "\x1b[31m");
std::vfprintf(stderr, fmt, args);
std::fprintf(stderr, "\x1b[0m\n");
va_end(args);
}

// -------------------------------------------------
// carla_assert*

static inline
void carla_assert(const char* const assertion, const char* const file, const int line)
{
qCritical("Carla assertion failure: \"%s\" in file %s, line %i", assertion, file, line);
carla_stderr2("Carla assertion failure: \"%s\" in file %s, line %i", assertion, file, line);
}

static inline
void carla_assert_int(const char* const assertion, const char* const file, const int line, const int value)
{
qCritical("Carla assertion failure: \"%s\" in file %s, line %i, value %i", assertion, file, line, value);
carla_stderr2("Carla assertion failure: \"%s\" in file %s, line %i, value %i", assertion, file, line, value);
}

static inline
void carla_assert_int2(const char* const assertion, const char* const file, const int line, const int v1, const int v2)
{
qCritical("Carla assertion failure: \"%s\" in file %s, line %i, v1 %i, v2 %i", assertion, file, line, v1, v2);
carla_stderr2("Carla assertion failure: \"%s\" in file %s, line %i, v1 %i, v2 %i", assertion, file, line, v1, v2);
}

// -------------------------------------------------
@@ -69,7 +123,7 @@ void carla_sleep(const unsigned int secs)
{
CARLA_ASSERT(secs > 0);

#ifdef Q_OS_WIN
#ifdef CARLA_OS_WIN
Sleep(secs * 1000);
#else
sleep(secs);
@@ -81,7 +135,7 @@ void carla_msleep(const unsigned int msecs)
{
CARLA_ASSERT(msecs > 0);

#ifdef Q_OS_WIN
#ifdef CARLA_OS_WIN
Sleep(msecs);
#else
usleep(msecs * 1000);
@@ -93,7 +147,7 @@ void carla_usleep(const unsigned int usecs)
{
CARLA_ASSERT(usecs > 0);

#ifdef Q_OS_WIN
#ifdef CARLA_OS_WIN
Sleep(usecs / 1000);
#else
usleep(usecs);
@@ -109,7 +163,7 @@ void carla_setenv(const char* const key, const char* const value)
CARLA_ASSERT(key != nullptr);
CARLA_ASSERT(value != nullptr);

#ifdef Q_OS_WIN
#ifdef CARLA_OS_WIN
SetEnvironmentVariableA(key, value);
#else
setenv(key, value, 1);
@@ -124,13 +178,13 @@ void carla_setprocname(const char* const name)
{
CARLA_ASSERT(name != nullptr);

#if defined(Q_OS_HAIKU)
#if defined(CARLA_OS_HAIKU)
if ((thread_id this_thread = find_thread(nullptr)) != B_NAME_NOT_FOUND)
rename_thread(this_thread, name);
#elif defined(Q_OS_LINUX)
#elif defined(CARLA_OS_LINUX)
prctl(PR_SET_NAME, name);
#else
qWarning("carla_setprocname(\"%s\") - unsupported on this platform", name);
carla_stderr("carla_setprocname(\"%s\") - unsupported on this platform", name);
#endif
}

@@ -226,704 +280,6 @@ void carla_zeroStruct(T& structure)
std::memset(&structure, 0, sizeof(T));
}

// -------------------------------------------------
// other misc functions

static inline
const char* bool2str(const bool yesNo)
{
return yesNo ? "true" : "false";
}

static inline
void pass() {}

// -------------------------------------------------
// CarlaMutex class

class CarlaMutex
{
public:
CarlaMutex()
{
#ifndef CPP11_MUTEX
pthread_mutex_init(&pmutex, nullptr);
#endif
}

~CarlaMutex()
{
#ifndef CPP11_MUTEX
pthread_mutex_destroy(&pmutex);
#endif
}

void lock()
{
#ifdef CPP11_MUTEX
cmutex.lock();
#else
pthread_mutex_lock(&pmutex);
#endif
}

bool tryLock()
{
#ifdef CPP11_MUTEX
return cmutex.try_lock();
#else
return (pthread_mutex_trylock(&pmutex) == 0);
#endif
}

void unlock()
{
#ifdef CPP11_MUTEX
cmutex.unlock();
#else
pthread_mutex_unlock(&pmutex);
#endif
}

class ScopedLocker
{
public:
ScopedLocker(CarlaMutex* const mutex)
: fMutex(mutex)
{
fMutex->lock();
}

~ScopedLocker()
{
fMutex->unlock();
}

private:
CarlaMutex* const fMutex;

CARLA_PREVENT_HEAP_ALLOCATION
CARLA_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR(ScopedLocker)
};

private:
#ifdef CPP11_MUTEX
std::mutex cmutex;
#else
pthread_mutex_t pmutex;
#endif

CARLA_PREVENT_HEAP_ALLOCATION
CARLA_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR(CarlaMutex)
};

// -------------------------------------------------
// CarlaThread class

class CarlaThread
{
public:
CarlaThread()
: fStarted(false),
fFinished(false)
{
#ifdef CPP11_MUTEX
cthread = nullptr;
#else
_zero();
pthread_attr_init(&pthreadAttr);
pthread_attr_setdetachstate(&pthreadAttr, PTHREAD_CREATE_JOINABLE);
#endif
}

~CarlaThread()
{
CARLA_ASSERT(! isRunning());

if (isRunning())
terminate();

#ifdef CPP11_MUTEX
if (cthread != nullptr)
{
cthread->join();
delete cthread;
}
#else
if (! _isNull())
pthread_join(pthreadId, nullptr);

pthread_attr_destroy(&pthreadAttr);
#endif
}

bool start()
{
CARLA_ASSERT(! isRunning());

if (isRunning())
return false;

fStarted = false;
fFinished = false;

#ifdef CPP11_MUTEX
CARLA_ASSERT(cthread == nullptr);

if (cthread != nullptr)
return false;

cthread = new std::thread(_cthreadRoutine, this);
CARLA_ASSERT(cthread->joinable());

return true;
#else
CARLA_ASSERT(_isNull());

if (! _isNull())
return false;

return (pthread_create(&pthreadId, &pthreadAttr, _pthreadRoutine, this) == 0);
#endif
}

bool stop(const unsigned int timeout = 0)
{
CARLA_ASSERT(isRunning());

if (! isRunning())
return true;

#ifdef CPP11_MUTEX
if (cthread == nullptr)
return true;
#else
if (_isNull())
return true;
#endif

if (timeout == 0)
{
#ifdef CPP11_MUTEX
cthread->join();
#else
pthread_join(pthreadId, nullptr);
#endif
}
else
{
for (unsigned int i=0; i < timeout && ! fFinished; i++)
carla_msleep(1);
}

if (! fFinished)
return false;

#ifdef CPP11_MUTEX
delete cthread;
cthread = nullptr;
#else
_zero();
#endif

return true;
}

void terminate()
{
CARLA_ASSERT(isRunning());

if (fFinished)
return;

#ifdef CPP11_MUTEX
if (cthread == nullptr)
return;
#else
if (_isNull())
return;
#endif

#ifdef CPP11_MUTEX
cthread->detach();
//cthread->join();
delete cthread;
cthread = nullptr;
#else
pthread_detach(pthreadId);
//pthread_join(pthreadId, nullptr);
pthread_cancel(pthreadId);
_zero();
#endif

fFinished = true;
}

bool isRunning()
{
return (fStarted && ! fFinished);
}

void waitForStarted(const unsigned int timeout = 0) // ms
{
if (fStarted)
return;

if (timeout == 0)
{
while (! fStarted) {}
}
else
{
for (unsigned int i=0; i < timeout && ! fStarted; i++)
carla_msleep(1);
}
}

void waitForFinished()
{
waitForStarted();
stop(0);
}

protected:
virtual void run() = 0;

private:
bool fStarted;
bool fFinished;

void handleRoutine()
{
fStarted = true;
run();
fFinished = true;
}

#ifdef CPP11_MUTEX
std::thread* cthread;

static void _cthreadRoutine(CarlaThread* const _this_)
{
_this_->handleRoutine();
}
#else
pthread_t pthreadId;
pthread_attr_t pthreadAttr;

static void* _pthreadRoutine(void* const _this_)
{
((CarlaThread*)_this_)->handleRoutine();
pthread_exit(nullptr);
return nullptr;
}

bool _isNull()
{
#ifdef Q_OS_WIN
return pthreadId.p == nullptr;
#else
return pthreadId == 0;
#endif
}

void _zero()
{
carla_zeroStruct<pthread_t>(pthreadId);
}
#endif

CARLA_PREVENT_HEAP_ALLOCATION
CARLA_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR(CarlaThread)
};

// -------------------------------------------------
// CarlaString class

class CarlaString
{
public:
// ---------------------------------------------
// constructors (no explicit conversions allowed)

explicit CarlaString()
{
_init();
_dup(nullptr);
}

explicit CarlaString(char* const strBuf)
{
_init();
_dup(strBuf);
}

explicit CarlaString(const char* const strBuf)
{
_init();
_dup(strBuf);
}

explicit CarlaString(const int value)
{
const size_t strBufSize = std::abs(value/10) + 3;
char strBuf[strBufSize];
std::snprintf(strBuf, strBufSize, "%d", value);

_init();
_dup(strBuf, strBufSize);
}

explicit CarlaString(const unsigned int value, const bool hexadecimal = false)
{
const size_t strBufSize = value/10 + 2 + (hexadecimal ? 2 : 0);
char strBuf[strBufSize];
std::snprintf(strBuf, strBufSize, hexadecimal ? "0x%x" : "%u", value);

_init();
_dup(strBuf, strBufSize);
}

explicit CarlaString(const long int value)
{
const size_t strBufSize = std::abs(value/10) + 3;
char strBuf[strBufSize];
std::snprintf(strBuf, strBufSize, "%ld", value);

_init();
_dup(strBuf, strBufSize);
}

explicit CarlaString(const unsigned long int value, const bool hexadecimal = false)
{
const size_t strBufSize = value/10 + 2 + (hexadecimal ? 2 : 0);
char strBuf[strBufSize];
std::snprintf(strBuf, strBufSize, hexadecimal ? "0x%lx" : "%lu", value);

_init();
_dup(strBuf, strBufSize);
}

explicit CarlaString(const float value)
{
char strBuf[0xff];
std::snprintf(strBuf, 0xff, "%f", value);

_init();
_dup(strBuf);
}

explicit CarlaString(const double value)
{
char strBuf[0xff];
std::snprintf(strBuf, 0xff, "%g", value);

_init();
_dup(strBuf);
}

// ---------------------------------------------
// non-explicit constructor

CarlaString(const CarlaString& str)
{
_init();
_dup(str.buffer);
}

// ---------------------------------------------
// deconstructor

~CarlaString()
{
CARLA_ASSERT(buffer);

delete[] buffer;
}

// ---------------------------------------------
// public methods

size_t length() const
{
return bufferLen;
}

bool isEmpty() const
{
return (bufferLen == 0);
}

bool isNotEmpty() const
{
return (bufferLen != 0);
}

#if __USE_GNU
bool contains(const char* const strBuf, const bool ignoreCase = false) const
{
if (strBuf == nullptr)
return false;

if (ignoreCase)
return (strcasestr(buffer, strBuf) != nullptr);
else
return (std::strstr(buffer, strBuf) != nullptr);
}

bool contains(const CarlaString& str, const bool ignoreCase = false) const
{
return contains(str.buffer, ignoreCase);
}
#else
bool contains(const char* const strBuf) const
{
if (strBuf == nullptr)
return false;

return (std::strstr(buffer, strBuf) != nullptr);
}

bool contains(const CarlaString& str) const
{
return contains(str.buffer);
}
#endif

bool isDigit(const size_t pos) const
{
if (pos >= bufferLen)
return false;

return (buffer[pos] >= '0' && buffer[pos] <= '9');
}

void clear()
{
truncate(0);
}

void replace(const char before, const char after)
{
if (after == '\0')
return;

for (size_t i=0; i < bufferLen; i++)
{
if (buffer[i] == before)
buffer[i] = after;
else if (buffer[i] == '\0')
break;
}
}

void truncate(const size_t n)
{
if (n >= bufferLen)
return;

for (size_t i=n; i < bufferLen; i++)
buffer[i] = '\0';

bufferLen = n;
}

void toBasic()
{
for (size_t i=0; i < bufferLen; i++)
{
if (buffer[i] >= '0' && buffer[i] <= '9')
continue;
if (buffer[i] >= 'A' && buffer[i] <= 'Z')
continue;
if (buffer[i] >= 'a' && buffer[i] <= 'z')
continue;
if (buffer[i] == '_')
continue;

buffer[i] = '_';
}
}

void toLower()
{
static const char charDiff = 'a' - 'A';

for (size_t i=0; i < bufferLen; i++)
{
if (buffer[i] >= 'A' && buffer[i] <= 'Z')
buffer[i] += charDiff;
}
}

void toUpper()
{
static const char charDiff = 'a' - 'A';

for (size_t i=0; i < bufferLen; i++)
{
if (buffer[i] >= 'a' && buffer[i] <= 'z')
buffer[i] -= charDiff;
}
}

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

operator const char*() const
{
return buffer;
}

char& operator[](const size_t pos)
{
return buffer[pos];
}

bool operator==(const char* const strBuf) const
{
return (strBuf != nullptr && std::strcmp(buffer, strBuf) == 0);
}

bool operator==(const CarlaString& str) const
{
return operator==(str.buffer);
}

bool operator!=(const char* const strBuf) const
{
return !operator==(strBuf);
}

bool operator!=(const CarlaString& str) const
{
return !operator==(str.buffer);
}

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

return *this;
}

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

CarlaString& operator+=(const char* const strBuf)
{
const size_t newBufSize = bufferLen + ((strBuf != nullptr) ? std::strlen(strBuf) : 0) + 1;
char newBuf[newBufSize];

std::strcpy(newBuf, buffer);
std::strcat(newBuf, strBuf);

_dup(newBuf, newBufSize-1);

return *this;
}

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

CarlaString operator+(const char* const strBuf)
{
const size_t newBufSize = bufferLen + ((strBuf != nullptr) ? std::strlen(strBuf) : 0) + 1;
char newBuf[newBufSize];

std::strcpy(newBuf, buffer);
std::strcat(newBuf, strBuf);

return CarlaString(newBuf);
}

CarlaString operator+(const CarlaString& str)
{
return operator+(str.buffer);
}

// ---------------------------------------------

private:
char* buffer;
size_t bufferLen;
bool firstInit;

void _init()
{
buffer = nullptr;
bufferLen = 0;
firstInit = true;
}

// allocate string strBuf if not null
// size > 0 only if strBuf is valid
void _dup(const char* const strBuf, const size_t size = 0)
{
if (strBuf != nullptr)
{
// don't recreate string if contents match
if (firstInit || std::strcmp(buffer, strBuf) != 0)
{
if (! firstInit)
{
CARLA_ASSERT(buffer);
delete[] buffer;
}

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

std::strcpy(buffer, strBuf);

buffer[bufferLen] = '\0';

firstInit = false;
}
}
else
{
CARLA_ASSERT(size == 0);

// don't recreate null string
if (firstInit || bufferLen != 0)
{
if (! firstInit)
{
CARLA_ASSERT(buffer);
delete[] buffer;
}

bufferLen = 0;
buffer = new char[1];
buffer[0] = '\0';

firstInit = false;
}
}
}

CARLA_LEAK_DETECTOR(CarlaString)
CARLA_PREVENT_HEAP_ALLOCATION
};

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

std::strcpy(newBuf, strBufBefore);
std::strcat(newBuf, strBufAfter);

return CarlaString(newBuf);
}

// -------------------------------------------------

#endif // __CARLA_UTILS_HPP__

Loading…
Cancel
Save