| @@ -35,10 +35,6 @@ BUILD_C_FLAGS = $(BASE_FLAGS) -std=c99 $(CFLAGS) | |||||
| BUILD_CXX_FLAGS = $(BASE_FLAGS) -std=c++0x $(CXXFLAGS) | BUILD_CXX_FLAGS = $(BASE_FLAGS) -std=c++0x $(CXXFLAGS) | ||||
| LINK_FLAGS = $(LDFLAGS) | 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 | # Modify to enable/disable specific features | ||||
| @@ -51,6 +51,9 @@ HEADERS += \ | |||||
| HEADERS += \ | HEADERS += \ | ||||
| ../../includes/carla_defines.hpp \ | ../../includes/carla_defines.hpp \ | ||||
| ../../includes/carla_midi.h \ | ../../includes/carla_midi.h \ | ||||
| ../../utils/carla_mutex.hpp \ | |||||
| ../../utils/carla_string.hpp \ | |||||
| ../../utils/carla_thread.hpp \ | |||||
| ../../utils/carla_utils.hpp \ | ../../utils/carla_utils.hpp \ | ||||
| ../../utils/carla_backend_utils.hpp \ | ../../utils/carla_backend_utils.hpp \ | ||||
| ../../utils/carla_juce_utils.hpp \ | ../../utils/carla_juce_utils.hpp \ | ||||
| @@ -18,15 +18,38 @@ | |||||
| #ifndef __CARLA_DEFINES_HPP__ | #ifndef __CARLA_DEFINES_HPP__ | ||||
| #define __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 | #endif | ||||
| // Common includes | // Common includes | ||||
| #ifdef Q_OS_WIN | |||||
| #ifdef CARLA_OS_WIN | |||||
| # include <winsock2.h> | # include <winsock2.h> | ||||
| # include <windows.h> | # include <windows.h> | ||||
| #else | #else | ||||
| @@ -36,13 +59,13 @@ | |||||
| # endif | # endif | ||||
| #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_INT64 "%I64i" | ||||
| # define P_INTPTR "%I64i" | # define P_INTPTR "%I64i" | ||||
| # define P_UINTPTR "%I64x" | # define P_UINTPTR "%I64x" | ||||
| # define P_SIZE "%I64u" | # define P_SIZE "%I64u" | ||||
| #elif defined(Q_OS_WIN32) | |||||
| #elif defined(CARLA_OS_WIN32) | |||||
| # define P_INT64 "%I64i" | # define P_INT64 "%I64i" | ||||
| # define P_INTPTR "%i" | # define P_INTPTR "%i" | ||||
| # define P_UINTPTR "%x" | # define P_UINTPTR "%x" | ||||
| @@ -60,14 +83,14 @@ | |||||
| #endif | #endif | ||||
| // Define BINARY_NATIVE | // Define BINARY_NATIVE | ||||
| #if defined(Q_OS_HAIKU) || defined(Q_OS_UNIX) | |||||
| #if defined(CARLA_OS_HAIKU) || defined(CARLA_OS_UNIX) | |||||
| # ifdef __LP64__ | # ifdef __LP64__ | ||||
| # define BINARY_NATIVE BINARY_POSIX64 | # define BINARY_NATIVE BINARY_POSIX64 | ||||
| # else | # else | ||||
| # define BINARY_NATIVE BINARY_POSIX32 | # define BINARY_NATIVE BINARY_POSIX32 | ||||
| # endif | # endif | ||||
| #elif defined(Q_OS_WIN) | |||||
| # ifdef Q_OS_WIN64 | |||||
| #elif defined(CARLA_OS_WIN) | |||||
| # ifdef CARLA_OS_WIN64 | |||||
| # define BINARY_NATIVE BINARY_WIN64 | # define BINARY_NATIVE BINARY_WIN64 | ||||
| # else | # else | ||||
| # define BINARY_NATIVE BINARY_WIN32 | # define BINARY_NATIVE BINARY_WIN32 | ||||
| @@ -79,20 +102,20 @@ | |||||
| // Define CARLA_ASSERT* | // Define CARLA_ASSERT* | ||||
| #ifdef NDEBUG | #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 | #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 | #endif | ||||
| // Define CARLA_EXPORT | // Define CARLA_EXPORT | ||||
| #ifdef BUILD_BRIDGE | #ifdef BUILD_BRIDGE | ||||
| # define CARLA_EXPORT extern "C" | # define CARLA_EXPORT extern "C" | ||||
| #else | #else | ||||
| # if defined(Q_OS_WIN) && ! defined(__WINE__) | |||||
| # if defined(CARLA_OS_WIN) && ! defined(__WINE__) | |||||
| # define CARLA_EXPORT extern "C" __declspec (dllexport) | # define CARLA_EXPORT extern "C" __declspec (dllexport) | ||||
| # else | # else | ||||
| # define CARLA_EXPORT extern "C" __attribute__ ((visibility("default"))) | # define CARLA_EXPORT extern "C" __attribute__ ((visibility("default"))) | ||||
| @@ -15,9 +15,7 @@ | |||||
| * For a full copy of the GNU General Public License see the GPL.txt file | * 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() | int main() | ||||
| { | { | ||||
| @@ -10,10 +10,8 @@ include ../Makefile.mk | |||||
| BUILD_CXX_FLAGS += -I../backend -I../includes -I../utils | BUILD_CXX_FLAGS += -I../backend -I../includes -I../utils | ||||
| # BUILD_CXX_FLAGS += -I/opt/mingw32/include | # 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 | all: $(TARGETS) RUN | ||||
| @@ -23,17 +21,21 @@ CarlaString: CarlaString.cpp | |||||
| $(CXX) $^ $(BUILD_CXX_FLAGS) $(LINK_FLAGS) -o $@ | $(CXX) $^ $(BUILD_CXX_FLAGS) $(LINK_FLAGS) -o $@ | ||||
| RtList: RtList.cpp ../libs/rtmempool.a | 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 | Thread: Thread.cpp | ||||
| $(CXX) $^ $(BUILD_CXX_FLAGS) $(LINK_FLAGS) -pthread -lpthread -o $@ | $(CXX) $^ $(BUILD_CXX_FLAGS) $(LINK_FLAGS) -pthread -lpthread -o $@ | ||||
| Print_: Print.cpp | |||||
| $(CXX) $^ $(BUILD_CXX_FLAGS) $(LINK_FLAGS) -o Print # $@ | |||||
| GL_: GL.cpp | 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) -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 # $@ | $(CXX) $^ $(BUILD_CXX_FLAGS) -I../backend/engine/plugin -I../libs/distrho-plugin-toolkit $(LINK_FLAGS) -lGL -lGLU -o GL # $@ | ||||
| RUN: $(TARGETS) | RUN: $(TARGETS) | ||||
| # ./CarlaString && ./RtList && ./Thread | # ./CarlaString && ./RtList && ./Thread | ||||
| # ./GL | # ./GL | ||||
| # -------------------------------------------------------------- | # -------------------------------------------------------------- | ||||
| @@ -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; | |||||
| } | |||||
| @@ -15,10 +15,10 @@ | |||||
| * For a full copy of the GNU General Public License see the GPL.txt file | * For a full copy of the GNU General Public License see the GPL.txt file | ||||
| */ | */ | ||||
| #include "carla_utils.hpp" | |||||
| #include "rt_list.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 MIN_RT_EVENTS = 152; | ||||
| const unsigned short MAX_RT_EVENTS = 512; | const unsigned short MAX_RT_EVENTS = 512; | ||||
| @@ -15,9 +15,7 @@ | |||||
| * For a full copy of the GNU General Public License see the GPL.txt file | * 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 | class MyThread : public CarlaThread | ||||
| { | { | ||||
| @@ -44,7 +44,7 @@ const char* BinaryType2Str(const BinaryType& type) | |||||
| return "BINARY_OTHER"; | return "BINARY_OTHER"; | ||||
| } | } | ||||
| qWarning("CarlaBackend::BinaryType2Str(%i) - invalid type", type); | |||||
| carla_stderr("CarlaBackend::BinaryType2Str(%i) - invalid type", type); | |||||
| return nullptr; | return nullptr; | ||||
| } | } | ||||
| @@ -73,7 +73,7 @@ const char* PluginType2Str(const PluginType& type) | |||||
| return "PLUGIN_SFZ"; | return "PLUGIN_SFZ"; | ||||
| } | } | ||||
| qWarning("CarlaBackend::PluginType2Str(%i) - invalid type", type); | |||||
| carla_stderr("CarlaBackend::PluginType2Str(%i) - invalid type", type); | |||||
| return nullptr; | return nullptr; | ||||
| } | } | ||||
| @@ -102,7 +102,7 @@ const char* PluginCategory2Str(const PluginCategory& category) | |||||
| return "PLUGIN_CATEGORY_OTHER"; | return "PLUGIN_CATEGORY_OTHER"; | ||||
| } | } | ||||
| qWarning("CarlaBackend::PluginCategory2Str(%i) - invalid category", category); | |||||
| carla_stderr("CarlaBackend::PluginCategory2Str(%i) - invalid category", category); | |||||
| return nullptr; | return nullptr; | ||||
| } | } | ||||
| @@ -129,7 +129,7 @@ const char* ParameterType2Str(const ParameterType& type) | |||||
| #endif | #endif | ||||
| } | } | ||||
| qWarning("CarlaBackend::ParameterType2Str(%i) - invalid type", type); | |||||
| carla_stderr("CarlaBackend::ParameterType2Str(%i) - invalid type", type); | |||||
| return nullptr; | return nullptr; | ||||
| } | } | ||||
| @@ -156,7 +156,7 @@ const char* InternalParametersIndex2Str(const InternalParametersIndex& index) | |||||
| return "PARAMETER_MAX"; | return "PARAMETER_MAX"; | ||||
| } | } | ||||
| qWarning("CarlaBackend::InternalParametersIndex2Str(%i) - invalid index", index); | |||||
| carla_stderr("CarlaBackend::InternalParametersIndex2Str(%i) - invalid index", index); | |||||
| return nullptr; | return nullptr; | ||||
| } | } | ||||
| @@ -225,7 +225,7 @@ const char* OptionsType2Str(const OptionsType& type) | |||||
| #endif | #endif | ||||
| } | } | ||||
| qWarning("CarlaBackend::OptionsType2Str(%i) - invalid type", type); | |||||
| carla_stderr("CarlaBackend::OptionsType2Str(%i) - invalid type", type); | |||||
| return nullptr; | return nullptr; | ||||
| } | } | ||||
| @@ -282,7 +282,7 @@ const char* CallbackType2Str(const CallbackType& type) | |||||
| return "CALLBACK_QUIT"; | return "CALLBACK_QUIT"; | ||||
| } | } | ||||
| qWarning("CarlaBackend::CallbackType2Str(%i) - invalid type", type); | |||||
| carla_stderr("CarlaBackend::CallbackType2Str(%i) - invalid type", type); | |||||
| return nullptr; | return nullptr; | ||||
| } | } | ||||
| @@ -303,7 +303,7 @@ const char* ProcessMode2Str(const ProcessMode& mode) | |||||
| return "PROCESS_MODE_BRIDGE"; | return "PROCESS_MODE_BRIDGE"; | ||||
| } | } | ||||
| qWarning("CarlaBackend::ProcessModeType2Str(%i) - invalid type", mode); | |||||
| carla_stderr("CarlaBackend::ProcessModeType2Str(%i) - invalid type", mode); | |||||
| return nullptr; | return nullptr; | ||||
| } | } | ||||
| @@ -312,7 +312,7 @@ const char* ProcessMode2Str(const ProcessMode& mode) | |||||
| static inline | static inline | ||||
| uintptr_t getAddressFromPointer(void* ptr) | uintptr_t getAddressFromPointer(void* ptr) | ||||
| { | { | ||||
| qDebug("CarlaBackend::getAddressFromPointer(%p)", ptr); | |||||
| carla_debug("CarlaBackend::getAddressFromPointer(%p)", ptr); | |||||
| CARLA_ASSERT(ptr != nullptr); | CARLA_ASSERT(ptr != nullptr); | ||||
| uintptr_t* addr = (uintptr_t*)&ptr; | uintptr_t* addr = (uintptr_t*)&ptr; | ||||
| @@ -333,7 +333,7 @@ void* getPointerFromAddress(uintptr_t& addr) | |||||
| static inline | static inline | ||||
| const char* getPluginTypeString(const PluginType& type) | const char* getPluginTypeString(const PluginType& type) | ||||
| { | { | ||||
| qDebug("CarlaBackend::getPluginTypeString(%s)", PluginType2Str(type)); | |||||
| carla_debug("CarlaBackend::getPluginTypeString(%s)", PluginType2Str(type)); | |||||
| switch (type) | switch (type) | ||||
| { | { | ||||
| @@ -357,6 +357,7 @@ const char* getPluginTypeString(const PluginType& type) | |||||
| return "SFZ"; | return "SFZ"; | ||||
| } | } | ||||
| carla_stderr("CarlaBackend::getPluginTypeString(%i) - invalid type", type); | |||||
| return "NONE"; | return "NONE"; | ||||
| } | } | ||||
| @@ -365,7 +366,7 @@ const char* getPluginTypeString(const PluginType& type) | |||||
| static inline | static inline | ||||
| PluginCategory getPluginCategoryFromName(const char* const name) | PluginCategory getPluginCategoryFromName(const char* const name) | ||||
| { | { | ||||
| qDebug("CarlaBackend::getPluginCategoryFromName(\"%s\")", name); | |||||
| carla_debug("CarlaBackend::getPluginCategoryFromName(\"%s\")", name); | |||||
| CARLA_ASSERT(name); | CARLA_ASSERT(name); | ||||
| if (! name) | if (! name) | ||||
| @@ -19,9 +19,9 @@ | |||||
| #ifndef __CARLA_JUCE_UTILS_HPP__ | #ifndef __CARLA_JUCE_UTILS_HPP__ | ||||
| #define __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) \ | #define CARLA_DECLARE_NON_COPYABLE(className) \ | ||||
| className (const className&);\ | className (const className&);\ | ||||
| @@ -82,7 +82,7 @@ public: | |||||
| { | { | ||||
| if (--(getCounter().numObjects) < 0) | 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 | /** 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. | created.. That indicates that you're deleting some dangling pointers. | ||||
| @@ -113,7 +113,7 @@ private: | |||||
| { | { | ||||
| if (numObjects > 0) | 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 | /** 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. | the 'OwnerClass' template parameter - the name should have been printed by the line above. | ||||
| @@ -313,7 +313,7 @@ private: | |||||
| return this; | 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 | /* 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). | would let you do so by implicitly casting the source to its raw object pointer). | ||||
| @@ -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__ | |||||
| @@ -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__ | |||||
| @@ -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__ | |||||
| @@ -18,47 +18,101 @@ | |||||
| #ifndef __CARLA_UTILS_HPP__ | #ifndef __CARLA_UTILS_HPP__ | ||||
| #define __CARLA_UTILS_HPP__ | #define __CARLA_UTILS_HPP__ | ||||
| #include "carla_juce_utils.hpp" | |||||
| #include "carla_defines.hpp" | |||||
| #include <cassert> | |||||
| #include <cstdarg> | |||||
| #include <cstdio> | #include <cstdio> | ||||
| #include <cstdlib> | #include <cstdlib> | ||||
| #include <cstring> | #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> | # include <kernel/OS.h> | ||||
| #elif defined(Q_OS_LINUX) | |||||
| #elif defined(CARLA_OS_LINUX) | |||||
| # include <sys/prctl.h> | # include <sys/prctl.h> | ||||
| # include <linux/prctl.h> | # include <linux/prctl.h> | ||||
| #endif | #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* | // carla_assert* | ||||
| static inline | static inline | ||||
| void carla_assert(const char* const assertion, const char* const file, const int line) | 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 | static inline | ||||
| void carla_assert_int(const char* const assertion, const char* const file, const int line, const int value) | 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 | static inline | ||||
| void carla_assert_int2(const char* const assertion, const char* const file, const int line, const int v1, const int v2) | 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); | CARLA_ASSERT(secs > 0); | ||||
| #ifdef Q_OS_WIN | |||||
| #ifdef CARLA_OS_WIN | |||||
| Sleep(secs * 1000); | Sleep(secs * 1000); | ||||
| #else | #else | ||||
| sleep(secs); | sleep(secs); | ||||
| @@ -81,7 +135,7 @@ void carla_msleep(const unsigned int msecs) | |||||
| { | { | ||||
| CARLA_ASSERT(msecs > 0); | CARLA_ASSERT(msecs > 0); | ||||
| #ifdef Q_OS_WIN | |||||
| #ifdef CARLA_OS_WIN | |||||
| Sleep(msecs); | Sleep(msecs); | ||||
| #else | #else | ||||
| usleep(msecs * 1000); | usleep(msecs * 1000); | ||||
| @@ -93,7 +147,7 @@ void carla_usleep(const unsigned int usecs) | |||||
| { | { | ||||
| CARLA_ASSERT(usecs > 0); | CARLA_ASSERT(usecs > 0); | ||||
| #ifdef Q_OS_WIN | |||||
| #ifdef CARLA_OS_WIN | |||||
| Sleep(usecs / 1000); | Sleep(usecs / 1000); | ||||
| #else | #else | ||||
| usleep(usecs); | usleep(usecs); | ||||
| @@ -109,7 +163,7 @@ void carla_setenv(const char* const key, const char* const value) | |||||
| CARLA_ASSERT(key != nullptr); | CARLA_ASSERT(key != nullptr); | ||||
| CARLA_ASSERT(value != nullptr); | CARLA_ASSERT(value != nullptr); | ||||
| #ifdef Q_OS_WIN | |||||
| #ifdef CARLA_OS_WIN | |||||
| SetEnvironmentVariableA(key, value); | SetEnvironmentVariableA(key, value); | ||||
| #else | #else | ||||
| setenv(key, value, 1); | setenv(key, value, 1); | ||||
| @@ -124,13 +178,13 @@ void carla_setprocname(const char* const name) | |||||
| { | { | ||||
| CARLA_ASSERT(name != nullptr); | 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) | if ((thread_id this_thread = find_thread(nullptr)) != B_NAME_NOT_FOUND) | ||||
| rename_thread(this_thread, name); | rename_thread(this_thread, name); | ||||
| #elif defined(Q_OS_LINUX) | |||||
| #elif defined(CARLA_OS_LINUX) | |||||
| prctl(PR_SET_NAME, name); | prctl(PR_SET_NAME, name); | ||||
| #else | #else | ||||
| qWarning("carla_setprocname(\"%s\") - unsupported on this platform", name); | |||||
| carla_stderr("carla_setprocname(\"%s\") - unsupported on this platform", name); | |||||
| #endif | #endif | ||||
| } | } | ||||
| @@ -226,704 +280,6 @@ void carla_zeroStruct(T& structure) | |||||
| std::memset(&structure, 0, sizeof(T)); | 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__ | #endif // __CARLA_UTILS_HPP__ | ||||