diff --git a/source/backend/CarlaBackend.h b/source/backend/CarlaBackend.h index 14154c2eb..c8dc99374 100644 --- a/source/backend/CarlaBackend.h +++ b/source/backend/CarlaBackend.h @@ -1423,6 +1423,19 @@ typedef struct { */ const char* value; +#ifdef __cplusplus + /*! + * Check if valid. + */ + bool isValid() const noexcept + { + if (type == nullptr || type[0] == '\0') return false; + if (key == nullptr || key [0] == '\0') return false; + if (value == nullptr) return false; + return true; + } +#endif /* __cplusplus */ + } CustomData; /*! diff --git a/source/backend/engine/CarlaEngineGraph.cpp b/source/backend/engine/CarlaEngineGraph.cpp index fed0d606a..74535e7a4 100644 --- a/source/backend/engine/CarlaEngineGraph.cpp +++ b/source/backend/engine/CarlaEngineGraph.cpp @@ -114,10 +114,13 @@ const char* RackGraph::MIDI::getName(const bool isInput, const uint portId) cons { for (LinkedList::Itenerator it = isInput ? ins.begin() : outs.begin(); it.valid(); it.next()) { - const PortNameToId& port(it.getValue()); + static const PortNameToId portNameFallback = { 0, 0, { '\0' }, { '\0' } }; - if (port.port == portId) - return port.name; + const PortNameToId& portNameToId(it.getValue(portNameFallback)); + CARLA_SAFE_ASSERT_CONTINUE(portNameToId.group != 0); + + if (portNameToId.port == portId) + return portNameToId.name; } return nullptr; @@ -127,13 +130,16 @@ uint RackGraph::MIDI::getPortId(const bool isInput, const char portName[], bool* { for (LinkedList::Itenerator it = isInput ? ins.begin() : outs.begin(); it.valid(); it.next()) { - const PortNameToId& port(it.getValue()); + static const PortNameToId portNameFallback = { 0, 0, { '\0' }, { '\0' } }; + + const PortNameToId& portNameToId(it.getValue(portNameFallback)); + CARLA_SAFE_ASSERT_CONTINUE(portNameToId.group != 0); - if (std::strcmp(port.name, portName) == 0) + if (std::strncmp(portNameToId.name, portName, STR_MAX) == 0) { if (ok != nullptr) *ok = true; - return port.port; + return portNameToId.port; } } @@ -315,28 +321,31 @@ bool RackGraph::disconnect(CarlaEngine* const engine, const uint connectionId) n for (LinkedList::Itenerator it=connections.list.begin(); it.valid(); it.next()) { - const ConnectionToId& connection(it.getValue()); + static const ConnectionToId fallback = { 0, 0, 0, 0, 0 }; + + const ConnectionToId& connectionToId(it.getValue(fallback)); + CARLA_SAFE_ASSERT_CONTINUE(connectionToId.id != 0); - if (connection.id != connectionId) + if (connectionToId.id != connectionId) continue; uint otherGroup, otherPort, carlaPort; - if (connection.groupA == RACK_GRAPH_GROUP_CARLA) + if (connectionToId.groupA == RACK_GRAPH_GROUP_CARLA) { - CARLA_SAFE_ASSERT_RETURN(connection.groupB != RACK_GRAPH_GROUP_CARLA, false); + CARLA_SAFE_ASSERT_RETURN(connectionToId.groupB != RACK_GRAPH_GROUP_CARLA, false); - carlaPort = connection.portA; - otherGroup = connection.groupB; - otherPort = connection.portB; + carlaPort = connectionToId.portA; + otherGroup = connectionToId.groupB; + otherPort = connectionToId.portB; } else { - CARLA_SAFE_ASSERT_RETURN(connection.groupB == RACK_GRAPH_GROUP_CARLA, false); + CARLA_SAFE_ASSERT_RETURN(connectionToId.groupB == RACK_GRAPH_GROUP_CARLA, false); - carlaPort = connection.portB; - otherGroup = connection.groupA; - otherPort = connection.portA; + carlaPort = connectionToId.portB; + otherGroup = connectionToId.groupA; + otherPort = connectionToId.portA; } CARLA_SAFE_ASSERT_RETURN(carlaPort > RACK_GRAPH_CARLA_PORT_NULL && carlaPort < RACK_GRAPH_CARLA_PORT_MAX, false); @@ -387,7 +396,7 @@ bool RackGraph::disconnect(CarlaEngine* const engine, const uint connectionId) n return false; } - engine->callback(ENGINE_CALLBACK_PATCHBAY_CONNECTION_REMOVED, connection.id, 0, 0, 0.0f, nullptr); + engine->callback(ENGINE_CALLBACK_PATCHBAY_CONNECTION_REMOVED, connectionToId.id, 0, 0, 0.0f, nullptr); connections.list.remove(it); return true; @@ -424,25 +433,28 @@ const char* const* RackGraph::getConnections() const noexcept for (LinkedList::Itenerator it=connections.list.begin(); it.valid(); it.next()) { - const ConnectionToId& connection(it.getValue()); + static const ConnectionToId fallback = { 0, 0, 0, 0, 0 }; + + const ConnectionToId& connectionToId(it.getValue(fallback)); + CARLA_SAFE_ASSERT_CONTINUE(connectionToId.id != 0); uint otherGroup, otherPort, carlaPort; - if (connection.groupA == RACK_GRAPH_GROUP_CARLA) + if (connectionToId.groupA == RACK_GRAPH_GROUP_CARLA) { - CARLA_SAFE_ASSERT_CONTINUE(connection.groupB != RACK_GRAPH_GROUP_CARLA); + CARLA_SAFE_ASSERT_CONTINUE(connectionToId.groupB != RACK_GRAPH_GROUP_CARLA); - carlaPort = connection.portA; - otherGroup = connection.groupB; - otherPort = connection.portB; + carlaPort = connectionToId.portA; + otherGroup = connectionToId.groupB; + otherPort = connectionToId.portB; } else { - CARLA_SAFE_ASSERT_CONTINUE(connection.groupB == RACK_GRAPH_GROUP_CARLA); + CARLA_SAFE_ASSERT_CONTINUE(connectionToId.groupB == RACK_GRAPH_GROUP_CARLA); - carlaPort = connection.portB; - otherGroup = connection.groupA; - otherPort = connection.portA; + carlaPort = connectionToId.portB; + otherGroup = connectionToId.groupA; + otherPort = connectionToId.portA; } CARLA_SAFE_ASSERT_CONTINUE(carlaPort > RACK_GRAPH_CARLA_PORT_NULL && carlaPort < RACK_GRAPH_CARLA_PORT_MAX); @@ -679,7 +691,8 @@ void RackGraph::processHelper(CarlaEngine::ProtectedData* const data, const floa // connect input buffers for (LinkedList::Itenerator it = audio.connectedIn1.begin(); it.valid(); it.next()) { - const uint& port(it.getValue()); + const uint& port(it.getValue(0)); + CARLA_SAFE_ASSERT_CONTINUE(port != 0); CARLA_SAFE_ASSERT_CONTINUE(port < inputs); if (noConnections) @@ -700,7 +713,8 @@ void RackGraph::processHelper(CarlaEngine::ProtectedData* const data, const floa for (LinkedList::Itenerator it = audio.connectedIn2.begin(); it.valid(); it.next()) { - const uint& port(it.getValue()); + const uint& port(it.getValue(0)); + CARLA_SAFE_ASSERT_CONTINUE(port != 0); CARLA_SAFE_ASSERT_CONTINUE(port < inputs); if (noConnections) @@ -734,7 +748,8 @@ void RackGraph::processHelper(CarlaEngine::ProtectedData* const data, const floa { for (LinkedList::Itenerator it = audio.connectedOut1.begin(); it.valid(); it.next()) { - const uint& port(it.getValue()); + const uint& port(it.getValue(0)); + CARLA_SAFE_ASSERT_CONTINUE(port != 0); CARLA_SAFE_ASSERT_CONTINUE(port < outputs); FloatVectorOperations::add(outBuf[port], audio.outBuf[0], iframes); @@ -745,7 +760,8 @@ void RackGraph::processHelper(CarlaEngine::ProtectedData* const data, const floa { for (LinkedList::Itenerator it = audio.connectedOut2.begin(); it.valid(); it.next()) { - const uint& port(it.getValue()); + const uint& port(it.getValue(0)); + CARLA_SAFE_ASSERT_CONTINUE(port != 0); CARLA_SAFE_ASSERT_CONTINUE(port < outputs); FloatVectorOperations::add(outBuf[port], audio.outBuf[1], iframes); @@ -1317,24 +1333,27 @@ bool PatchbayGraph::disconnect(CarlaEngine* const engine, const uint connectionI for (LinkedList::Itenerator it=connections.list.begin(); it.valid(); it.next()) { - const ConnectionToId& connection(it.getValue()); + static const ConnectionToId fallback = { 0, 0, 0, 0, 0 }; + + const ConnectionToId& connectionToId(it.getValue(fallback)); + CARLA_SAFE_ASSERT_CONTINUE(connectionToId.id != 0); - if (connection.id != connectionId) + if (connectionToId.id != connectionId) continue; - uint adjustedPortA = connection.portA; - uint adjustedPortB = connection.portB; + uint adjustedPortA = connectionToId.portA; + uint adjustedPortB = connectionToId.portB; if (! adjustPatchbayPortIdForJuce(adjustedPortA)) return false; if (! adjustPatchbayPortIdForJuce(adjustedPortB)) return false; - if (! graph.removeConnection(connection.groupA, static_cast(adjustedPortA), - connection.groupB, static_cast(adjustedPortB))) + if (! graph.removeConnection(connectionToId.groupA, static_cast(adjustedPortA), + connectionToId.groupB, static_cast(adjustedPortB))) return false; - engine->callback(ENGINE_CALLBACK_PATCHBAY_CONNECTION_REMOVED, connection.id, 0, 0, 0.0f, nullptr); + engine->callback(ENGINE_CALLBACK_PATCHBAY_CONNECTION_REMOVED, connectionToId.id, 0, 0, 0.0f, nullptr); connections.list.remove(it); return true; @@ -1421,12 +1440,15 @@ const char* const* PatchbayGraph::getConnections() const for (LinkedList::Itenerator it=connections.list.begin(); it.valid(); it.next()) { - const ConnectionToId& connection(it.getValue()); + static const ConnectionToId fallback = { 0, 0, 0, 0, 0 }; + + const ConnectionToId& connectionToId(it.getValue(fallback)); + CARLA_SAFE_ASSERT_CONTINUE(connectionToId.id != 0); - AudioProcessorGraph::Node* const nodeA(graph.getNodeForId(connection.groupA)); + AudioProcessorGraph::Node* const nodeA(graph.getNodeForId(connectionToId.groupA)); CARLA_SAFE_ASSERT_CONTINUE(nodeA != nullptr); - AudioProcessorGraph::Node* const nodeB(graph.getNodeForId(connection.groupB)); + AudioProcessorGraph::Node* const nodeB(graph.getNodeForId(connectionToId.groupB)); CARLA_SAFE_ASSERT_CONTINUE(nodeB != nullptr); AudioProcessor* const procA(nodeA->getProcessor()); @@ -1435,10 +1457,10 @@ const char* const* PatchbayGraph::getConnections() const AudioProcessor* const procB(nodeB->getProcessor()); CARLA_SAFE_ASSERT_CONTINUE(procB != nullptr); - String fullPortNameA(getProcessorFullPortName(procA, connection.portA)); + String fullPortNameA(getProcessorFullPortName(procA, connectionToId.portA)); CARLA_SAFE_ASSERT_CONTINUE(fullPortNameA.isNotEmpty()); - String fullPortNameB(getProcessorFullPortName(procB, connection.portB)); + String fullPortNameB(getProcessorFullPortName(procB, connectionToId.portB)); CARLA_SAFE_ASSERT_CONTINUE(fullPortNameB.isNotEmpty()); connList.append(fullPortNameA.toRawUTF8()); diff --git a/source/backend/engine/CarlaEngineJack.cpp b/source/backend/engine/CarlaEngineJack.cpp index a5ef7842d..61dc82d4e 100644 --- a/source/backend/engine/CarlaEngineJack.cpp +++ b/source/backend/engine/CarlaEngineJack.cpp @@ -568,19 +568,25 @@ public: { for (LinkedList::Itenerator it = fAudioPorts.begin(); it.valid(); it.next()) { - CarlaEngineJackAudioPort* const port(it.getValue()); + CarlaEngineJackAudioPort* const port(it.getValue(nullptr)); + CARLA_SAFE_ASSERT_CONTINUE(port != nullptr); + port->invalidate(); } for (LinkedList::Itenerator it = fCVPorts.begin(); it.valid(); it.next()) { - CarlaEngineJackCVPort* const port(it.getValue()); + CarlaEngineJackCVPort* const port(it.getValue(nullptr)); + CARLA_SAFE_ASSERT_CONTINUE(port != nullptr); + port->invalidate(); } for (LinkedList::Itenerator it = fEventPorts.begin(); it.valid(); it.next()) { - CarlaEngineJackEventPort* const port(it.getValue()); + CarlaEngineJackEventPort* const port(it.getValue(nullptr)); + CARLA_SAFE_ASSERT_CONTINUE(port != nullptr); + port->invalidate(); } @@ -887,11 +893,11 @@ public: return; LinkedList newPlugins; - fNewGroups.spliceInsertInto(newPlugins); + fNewGroups.moveTo(newPlugins); for (LinkedList::Itenerator it = newPlugins.begin(); it.valid(); it.next()) { - const uint groupId(it.getValue()); + const uint groupId(it.getValue(0)); CARLA_SAFE_ASSERT_CONTINUE(groupId > 0); const char* const groupName(fUsedGroups.getGroupName(groupId)); @@ -1102,7 +1108,10 @@ public: for (LinkedList::Itenerator it = fUsedConnections.list.begin(); it.valid(); it.next()) { - const ConnectionToId& connectionToId(it.getValue()); + static const ConnectionToId fallback = { 0, 0, 0, 0, 0 }; + + const ConnectionToId& connectionToId(it.getValue(fallback)); + CARLA_SAFE_ASSERT_CONTINUE(connectionToId.id != 0); if (connectionToId.id == connectionId) { @@ -1596,7 +1605,10 @@ protected: { for (LinkedList::Itenerator it = fUsedConnections.list.begin(); it.valid(); it.next()) { - const ConnectionToId& connectionToId(it.getValue()); + static const ConnectionToId fallback = { 0, 0, 0, 0, 0 }; + + const ConnectionToId& connectionToId(it.getValue(fallback)); + CARLA_SAFE_ASSERT_CONTINUE(connectionToId.id != 0); if (connectionToId.groupA == portNameToIdA.group && connectionToId.portA == portNameToIdA.port && connectionToId.groupB == portNameToIdB.group && connectionToId.portB == portNameToIdB.port) @@ -1619,9 +1631,12 @@ protected: for (LinkedList::Itenerator it = fUsedGroups.list.begin(); it.valid(); it.next()) { - GroupNameToId& groupNameToId(it.getValue()); + static GroupNameToId groupNameFallback = { 0, { '\0' } }; + + GroupNameToId& groupNameToId(it.getValue(groupNameFallback)); + CARLA_SAFE_ASSERT_CONTINUE(groupNameToId.group != 0); - if (std::strcmp(groupNameToId.name, oldName) == 0) + if (std::strncmp(groupNameToId.name, oldName, STR_MAX) == 0) { groupNameToId.rename(newName); callback(ENGINE_CALLBACK_PATCHBAY_CLIENT_RENAMED, groupNameToId.group, 0, 0, 0.0f, groupNameToId.name); @@ -1655,9 +1670,12 @@ protected: for (LinkedList::Itenerator it = fUsedPorts.list.begin(); it.valid(); it.next()) { - PortNameToId& portNameToId(it.getValue()); + static PortNameToId portNameFallback = { 0, 0, { '\0' }, { '\0' } }; + + PortNameToId& portNameToId(it.getValue(portNameFallback)); + CARLA_SAFE_ASSERT_CONTINUE(portNameToId.group != 0); - if (std::strcmp(portNameToId.fullName, oldFullName) == 0) + if (std::strncmp(portNameToId.fullName, oldFullName, STR_MAX) == 0) { CARLA_SAFE_ASSERT_CONTINUE(portNameToId.group == groupId); diff --git a/source/backend/engine/CarlaEngineRtAudio.cpp b/source/backend/engine/CarlaEngineRtAudio.cpp index 042321985..d374dc1f3 100644 --- a/source/backend/engine/CarlaEngineRtAudio.cpp +++ b/source/backend/engine/CarlaEngineRtAudio.cpp @@ -343,7 +343,9 @@ public: for (LinkedList::Itenerator it = fMidiIns.begin(); it.valid(); it.next()) { - MidiInPort& inPort(it.getValue()); + static MidiInPort fallback = { nullptr, { '\0' } }; + + MidiInPort& inPort(it.getValue(fallback)); CARLA_SAFE_ASSERT_CONTINUE(inPort.port != nullptr); inPort.port->cancelCallback(); @@ -358,7 +360,9 @@ public: for (LinkedList::Itenerator it = fMidiOuts.begin(); it.valid(); it.next()) { - MidiOutPort& outPort(it.getValue()); + static MidiOutPort fallback = { nullptr, { '\0' } }; + + MidiOutPort& outPort(it.getValue(fallback)); CARLA_SAFE_ASSERT_CONTINUE(outPort.port != nullptr); outPort.port->closePort(); @@ -516,7 +520,8 @@ public: for (LinkedList::Itenerator it = graph->audio.connectedIn1.begin(); it.valid(); it.next()) { - const uint& portId(it.getValue()); + const uint& portId(it.getValue(0)); + CARLA_SAFE_ASSERT_CONTINUE(portId != 0); CARLA_SAFE_ASSERT_CONTINUE(portId < fAudioInCount); ConnectionToId connectionToId; @@ -531,7 +536,8 @@ public: for (LinkedList::Itenerator it = graph->audio.connectedIn2.begin(); it.valid(); it.next()) { - const uint& portId(it.getValue()); + const uint& portId(it.getValue(0)); + CARLA_SAFE_ASSERT_CONTINUE(portId != 0); CARLA_SAFE_ASSERT_CONTINUE(portId < fAudioInCount); ConnectionToId connectionToId; @@ -546,7 +552,8 @@ public: for (LinkedList::Itenerator it = graph->audio.connectedOut1.begin(); it.valid(); it.next()) { - const uint& portId(it.getValue()); + const uint& portId(it.getValue(0)); + CARLA_SAFE_ASSERT_CONTINUE(portId != 0); CARLA_SAFE_ASSERT_CONTINUE(portId < fAudioOutCount); ConnectionToId connectionToId; @@ -561,7 +568,8 @@ public: for (LinkedList::Itenerator it = graph->audio.connectedOut2.begin(); it.valid(); it.next()) { - const uint& portId(it.getValue()); + const uint& portId(it.getValue(0)); + CARLA_SAFE_ASSERT_CONTINUE(portId != 0); CARLA_SAFE_ASSERT_CONTINUE(portId < fAudioOutCount); ConnectionToId connectionToId; @@ -578,7 +586,10 @@ public: for (LinkedList::Itenerator it=fMidiIns.begin(); it.valid(); it.next()) { - const MidiInPort& inPort(it.getValue()); + static const MidiInPort fallback = { nullptr, { '\0' } }; + + const MidiInPort& inPort(it.getValue(fallback)); + CARLA_SAFE_ASSERT_CONTINUE(inPort.port != nullptr); const uint portId(graph->midi.getPortId(true, inPort.name)); CARLA_SAFE_ASSERT_CONTINUE(portId < graph->midi.ins.count()); @@ -597,7 +608,10 @@ public: for (LinkedList::Itenerator it=fMidiOuts.begin(); it.valid(); it.next()) { - const MidiOutPort& outPort(it.getValue()); + static const MidiOutPort fallback = { nullptr, { '\0' } }; + + const MidiOutPort& outPort(it.getValue(fallback)); + CARLA_SAFE_ASSERT_CONTINUE(outPort.port != nullptr); const uint portId(graph->midi.getPortId(false, outPort.name)); CARLA_SAFE_ASSERT_CONTINUE(portId < graph->midi.outs.count()); @@ -684,8 +698,12 @@ protected: for (LinkedList::Itenerator it = fMidiInEvents.data.begin(); it.valid(); it.next()) { - const RtMidiEvent& midiEvent(it.getValue()); - EngineEvent& engineEvent(pData->events.in[engineEventIndex++]); + static const RtMidiEvent fallback = { 0, 0, { 0 } }; + + const RtMidiEvent& midiEvent(it.getValue(fallback)); + CARLA_SAFE_ASSERT_CONTINUE(midiEvent.size > 0); + + EngineEvent& engineEvent(pData->events.in[engineEventIndex++]); if (midiEvent.time < pData->timeInfo.frame) { @@ -754,7 +772,9 @@ protected: for (LinkedList::Itenerator it=fMidiOuts.begin(); it.valid(); it.next()) { - MidiOutPort& outPort(it.getValue()); + static MidiOutPort fallback = { nullptr, { '\0' } }; + + MidiOutPort& outPort(it.getValue(fallback)); CARLA_SAFE_ASSERT_CONTINUE(outPort.port != nullptr); outPort.port->sendMessage(&fMidiOutVector); @@ -932,10 +952,12 @@ protected: for (LinkedList::Itenerator it=fMidiIns.begin(); it.valid(); it.next()) { - MidiInPort& inPort(it.getValue()); + static MidiInPort fallback = { nullptr, { '\0' } }; + + MidiInPort& inPort(it.getValue(fallback)); CARLA_SAFE_ASSERT_CONTINUE(inPort.port != nullptr); - if (std::strcmp(inPort.name, portName) != 0) + if (std::strncmp(inPort.name, portName, STR_MAX) != 0) continue; inPort.port->cancelCallback(); @@ -962,10 +984,12 @@ protected: for (LinkedList::Itenerator it=fMidiOuts.begin(); it.valid(); it.next()) { - MidiOutPort& outPort(it.getValue()); + static MidiOutPort fallback = { nullptr, { '\0' } }; + + MidiOutPort& outPort(it.getValue(fallback)); CARLA_SAFE_ASSERT_CONTINUE(outPort.port != nullptr); - if (std::strcmp(outPort.name, portName) != 0) + if (std::strncmp(outPort.name, portName, STR_MAX) != 0) continue; outPort.port->closePort(); @@ -1046,7 +1070,7 @@ private: void splice() { - dataPending.spliceAppendTo(data); + dataPending.moveTo(data, true /* append */); } }; diff --git a/source/backend/plugin/CarlaPlugin.cpp b/source/backend/plugin/CarlaPlugin.cpp index 6ef346d63..e1fd1b6a8 100644 --- a/source/backend/plugin/CarlaPlugin.cpp +++ b/source/backend/plugin/CarlaPlugin.cpp @@ -44,6 +44,8 @@ static const ParameterRanges kParameterRangesNull = { 0.0f, 0.0f, 1.0f, 0.01f, 0 static const MidiProgramData kMidiProgramDataNull = { 0, 0, nullptr }; static const CustomData kCustomDataNull = { nullptr, nullptr, nullptr }; +static const PluginPostRtEvent kPluginPostRtEventFallback = { kPluginPostRtEventNull, 0, 0, 0.0f }; + // ------------------------------------------------------------------- // ParamSymbol struct, needed for CarlaPlugin::loadStateSave() @@ -586,7 +588,8 @@ const CarlaStateSave& CarlaPlugin::getStateSave() for (LinkedList::Itenerator it = pData->custom.begin(); it.valid(); it.next()) { - const CustomData& cData(it.getValue()); + const CustomData& cData(it.getValue(kCustomDataNull)); + CARLA_SAFE_ASSERT_CONTINUE(cData.isValid()); CarlaStateSave::CustomData* stateCustomData(new CarlaStateSave::CustomData()); @@ -1194,28 +1197,25 @@ void CarlaPlugin::setCustomData(const char* const type, const char* const key, c // Check if we already have this key for (LinkedList::Itenerator it = pData->custom.begin(); it.valid(); it.next()) { - CustomData& cData(it.getValue()); - - CARLA_SAFE_ASSERT_CONTINUE(cData.type != nullptr && cData.type[0] != '\0'); - CARLA_SAFE_ASSERT_CONTINUE(cData.key != nullptr && cData.key[0] != '\0'); - CARLA_SAFE_ASSERT_CONTINUE(cData.value != nullptr); + CustomData& customData(it.getValue()); + CARLA_SAFE_ASSERT_CONTINUE(customData.isValid()); - if (std::strcmp(cData.key, key) == 0) + if (std::strcmp(customData.key, key) == 0) { - if (cData.value != nullptr) - delete[] cData.value; + if (customData.value != nullptr) + delete[] customData.value; - cData.value = carla_strdup(value); + customData.value = carla_strdup(value); return; } } // Otherwise store it - CustomData newData; - newData.type = carla_strdup(type); - newData.key = carla_strdup(key); - newData.value = carla_strdup(value); - pData->custom.append(newData); + CustomData customData; + customData.type = carla_strdup(type); + customData.key = carla_strdup(key); + customData.value = carla_strdup(value); + pData->custom.append(customData); } void CarlaPlugin::setChunkData(const void* const data, const std::size_t dataSize) @@ -1617,14 +1617,11 @@ void CarlaPlugin::updateOscData(const lo_address& source, const char* const url) for (LinkedList::Itenerator it = pData->custom.begin(); it.valid(); it.next()) { - const CustomData& cData(it.getValue()); - - CARLA_SAFE_ASSERT_CONTINUE(cData.type != nullptr && cData.type[0] != '\0'); - CARLA_SAFE_ASSERT_CONTINUE(cData.key != nullptr && cData.key[0] != '\0'); - CARLA_SAFE_ASSERT_CONTINUE(cData.value != nullptr); + const CustomData& customData(it.getValue(kCustomDataNull)); + CARLA_SAFE_ASSERT_CONTINUE(customData.isValid()); - if (std::strcmp(cData.type, CUSTOM_DATA_TYPE_STRING) == 0) - osc_send_configure(pData->oscData, cData.key, cData.value); + if (std::strcmp(customData.type, CUSTOM_DATA_TYPE_STRING) == 0) + osc_send_configure(pData->oscData, customData.key, customData.value); } if (pData->prog.current >= 0) @@ -1757,7 +1754,8 @@ void CarlaPlugin::postRtEventsRun() for (RtLinkedList::Itenerator it = pData->postRtEvents.data.begin(); it.valid(); it.next()) { - const PluginPostRtEvent& event(it.getValue()); + const PluginPostRtEvent& event(it.getValue(kPluginPostRtEventFallback)); + CARLA_SAFE_ASSERT_CONTINUE(event.type != kPluginPostRtEventNull); switch (event.type) { diff --git a/source/backend/plugin/CarlaPluginInternal.hpp b/source/backend/plugin/CarlaPluginInternal.hpp index 44c1a3577..c1d77b35d 100644 --- a/source/backend/plugin/CarlaPluginInternal.hpp +++ b/source/backend/plugin/CarlaPluginInternal.hpp @@ -22,12 +22,12 @@ #include "CarlaPluginThread.hpp" #include "CarlaLibUtils.hpp" -#include "CarlaMutex.hpp" #include "CarlaOscUtils.hpp" #include "CarlaStateUtils.hpp" -#include "CarlaString.hpp" #include "CarlaMIDI.h" +#include "CarlaMutex.hpp" +#include "CarlaString.hpp" #include "RtLinkedList.hpp" #include "juce_audio_basics.h" diff --git a/source/utils/CarlaPatchbayUtils.hpp b/source/utils/CarlaPatchbayUtils.hpp index 094cbf97d..50a329bcc 100644 --- a/source/utils/CarlaPatchbayUtils.hpp +++ b/source/utils/CarlaPatchbayUtils.hpp @@ -50,7 +50,7 @@ struct GroupNameToId { { if (groupNameToId.group != group) return false; - if (std::strcmp(groupNameToId.name, name) != 0) + if (std::strncmp(groupNameToId.name, name, STR_MAX) != 0) return false; return true; } @@ -81,9 +81,12 @@ struct PatchbayGroupList { for (LinkedList::Itenerator it = list.begin(); it.valid(); it.next()) { - const GroupNameToId& groupNameToId(it.getValue()); + static const GroupNameToId groupNameFallback = { 0, { '\0' } }; - if (std::strcmp(groupNameToId.name, groupName) == 0) + const GroupNameToId& groupNameToId(it.getValue(groupNameFallback)); + CARLA_SAFE_ASSERT_CONTINUE(groupNameToId.group != 0); + + if (std::strncmp(groupNameToId.name, groupName, STR_MAX) == 0) return groupNameToId.group; } @@ -96,7 +99,10 @@ struct PatchbayGroupList { for (LinkedList::Itenerator it = list.begin(); it.valid(); it.next()) { - const GroupNameToId& groupNameToId(it.getValue()); + static const GroupNameToId groupNameFallback = { 0, { '\0' } }; + + const GroupNameToId& groupNameToId(it.getValue(groupNameFallback)); + CARLA_SAFE_ASSERT_CONTINUE(groupNameToId.group != 0); if (groupNameToId.group == groupId) return groupNameToId.name; @@ -111,7 +117,7 @@ struct PatchbayGroupList { struct PortNameToId { uint group; uint port; - char name[STR_MAX+1]; // locally unique + char name[STR_MAX+1]; // locally unique (within the same group) char fullName[STR_MAX+1]; // globally unique void clear() noexcept @@ -142,9 +148,9 @@ struct PortNameToId { { if (portNameToId.group != group || portNameToId.port != port) return false; - if (std::strcmp(portNameToId.name, name) != 0) + if (std::strncmp(portNameToId.name, name, STR_MAX) != 0) return false; - if (std::strcmp(portNameToId.fullName, fullName) != 0) + if (std::strncmp(portNameToId.fullName, fullName, STR_MAX) != 0) return false; return true; } @@ -175,7 +181,10 @@ struct PatchbayPortList { for (LinkedList::Itenerator it = list.begin(); it.valid(); it.next()) { - const PortNameToId& portNameToId(it.getValue()); + static const PortNameToId portNameFallback = { 0, 0, { '\0' }, { '\0' } }; + + const PortNameToId& portNameToId(it.getValue(portNameFallback)); + CARLA_SAFE_ASSERT_CONTINUE(portNameToId.group != 0); if (portNameToId.group == groupId && portNameToId.port == portId) return portNameToId.fullName; @@ -192,9 +201,10 @@ struct PatchbayPortList { for (LinkedList::Itenerator it = list.begin(); it.valid(); it.next()) { - const PortNameToId& portNameToId(it.getValue()); + const PortNameToId& portNameToId(it.getValue(fallback)); + CARLA_SAFE_ASSERT_CONTINUE(portNameToId.group != 0); - if (std::strcmp(portNameToId.fullName, fullPortName) == 0) + if (std::strncmp(portNameToId.fullName, fullPortName, STR_MAX) == 0) return portNameToId; } diff --git a/source/utils/CarlaStateUtils.cpp b/source/utils/CarlaStateUtils.cpp index e38e12507..6f27049a8 100644 --- a/source/utils/CarlaStateUtils.cpp +++ b/source/utils/CarlaStateUtils.cpp @@ -162,6 +162,14 @@ CarlaStateSave::CustomData::~CustomData() noexcept } } +bool CarlaStateSave::CustomData::isValid() const noexcept +{ + if (type == nullptr || type[0] == '\0') return false; + if (key == nullptr || key [0] == '\0') return false; + if (value == nullptr) return false; + return true; +} + // ----------------------------------------------------------------------- // StateSave @@ -244,13 +252,13 @@ void CarlaStateSave::clear() noexcept for (ParameterItenerator it = parameters.begin(); it.valid(); it.next()) { - Parameter* const stateParameter(it.getValue()); + Parameter* const stateParameter(it.getValue(nullptr)); delete stateParameter; } for (CustomDataItenerator it = customData.begin(); it.valid(); it.next()) { - CustomData* const stateCustomData(it.getValue()); + CustomData* const stateCustomData(it.getValue(nullptr)); delete stateCustomData; } @@ -451,7 +459,10 @@ bool CarlaStateSave::fillFromXmlElement(const XmlElement* const xmlElement) stateCustomData->value = carla_strdup(cText.toRawUTF8()); //xmlSafeStringCharDup(cText, false); } - customData.append(stateCustomData); + if (stateCustomData->isValid()) + customData.append(stateCustomData); + else + carla_stderr("Reading CustomData property failed, missing data"); } // ------------------------------------------------------- @@ -559,7 +570,8 @@ String CarlaStateSave::toString() const for (ParameterItenerator it = parameters.begin(); it.valid(); it.next()) { - Parameter* const stateParameter(it.getValue()); + Parameter* const stateParameter(it.getValue(nullptr)); + CARLA_SAFE_ASSERT_CONTINUE(stateParameter != nullptr); String parameterXml("\n"" \n"); @@ -609,10 +621,9 @@ String CarlaStateSave::toString() const for (CustomDataItenerator it = customData.begin(); it.valid(); it.next()) { - CustomData* const stateCustomData(it.getValue()); - CARLA_SAFE_ASSERT_CONTINUE(stateCustomData->type != nullptr && stateCustomData->type[0] != '\0'); - CARLA_SAFE_ASSERT_CONTINUE(stateCustomData->key != nullptr && stateCustomData->key[0] != '\0'); - CARLA_SAFE_ASSERT_CONTINUE(stateCustomData->value != nullptr); + CustomData* const stateCustomData(it.getValue(nullptr)); + CARLA_SAFE_ASSERT_CONTINUE(stateCustomData != nullptr); + CARLA_SAFE_ASSERT_CONTINUE(stateCustomData->isValid()); String customDataXml("\n"" \n"); customDataXml << " " << xmlSafeString(stateCustomData->type, true) << "\n"; diff --git a/source/utils/CarlaStateUtils.hpp b/source/utils/CarlaStateUtils.hpp index 883098016..bdf0d357f 100644 --- a/source/utils/CarlaStateUtils.hpp +++ b/source/utils/CarlaStateUtils.hpp @@ -55,6 +55,7 @@ struct CarlaStateSave { CustomData() noexcept; ~CustomData() noexcept; + bool isValid() const noexcept; CARLA_DECLARE_NON_COPY_STRUCT(CustomData) }; diff --git a/source/utils/CarlaStringList.hpp b/source/utils/CarlaStringList.hpp index b670f23fa..fb19fb33e 100644 --- a/source/utils/CarlaStringList.hpp +++ b/source/utils/CarlaStringList.hpp @@ -136,7 +136,7 @@ protected: std::size_t i=0; for (LinkedList::Itenerator it = list.begin(); it.valid(); it.next(), ++i) { - tmpList[i] = carla_strdup_safe(it.getValue()); + tmpList[i] = carla_strdup_safe(it.getValue(nullptr)); CARLA_SAFE_ASSERT_BREAK(tmpList[i] != nullptr); } CARLA_SAFE_ASSERT(i == count); @@ -163,7 +163,7 @@ public: : LinkedList() { for (Itenerator it = list.begin(); it.valid(); it.next()) - LinkedList::append(carla_strdup_safe(it.getValue())); + LinkedList::append(carla_strdup_safe(it.getValue(nullptr))); } ~CarlaStringList() noexcept override @@ -177,7 +177,7 @@ public: { for (Itenerator it = begin(); it.valid(); it.next()) { - if (const char* const string = it.getValue()) + if (const char* const string = it.getValue(nullptr)) delete[] string; } @@ -246,7 +246,7 @@ public: void remove(Itenerator& it) noexcept { - if (const char* const string = it.getValue()) + if (const char* const string = it.getValue(nullptr)) delete[] string; LinkedList::remove(it); @@ -258,7 +258,7 @@ public: for (Itenerator it = begin(); it.valid(); it.next()) { - const char* const stringComp(it.getValue()); + const char* const stringComp(it.getValue(nullptr)); CARLA_SAFE_ASSERT_CONTINUE(stringComp != nullptr); if (std::strcmp(string, stringComp) != 0) @@ -278,7 +278,7 @@ public: for (Itenerator it = begin(); it.valid(); it.next()) { - const char* const stringComp(it.getValue()); + const char* const stringComp(it.getValue(nullptr)); CARLA_SAFE_ASSERT_CONTINUE(stringComp != nullptr); if (std::strcmp(string, stringComp) != 0) @@ -317,7 +317,7 @@ public: for (Itenerator it = list.begin(); it.valid(); it.next()) { - if (const char* const string = carla_strdup_safe(it.getValue())) + if (const char* const string = carla_strdup_safe(it.getValue(nullptr))) LinkedList::append(string); } diff --git a/source/utils/LinkedList.hpp b/source/utils/LinkedList.hpp index 6b5c2ba23..0e6b45503 100644 --- a/source/utils/LinkedList.hpp +++ b/source/utils/LinkedList.hpp @@ -86,8 +86,7 @@ public: class Itenerator { public: Itenerator(const ListHead& queue) noexcept - : fData(nullptr), - fEntry(queue.next), + : fEntry(queue.next), fEntry2(fEntry->next), kQueue(queue) { @@ -106,20 +105,31 @@ public: fEntry2 = (fEntry != nullptr) ? fEntry->next : nullptr; } - T& getValue() noexcept + T& getValue(T& fallback) const noexcept { - fData = list_entry(fEntry, Data, siblings); - return fData->value; + Data* const data(list_entry(fEntry, Data, siblings)); + CARLA_SAFE_ASSERT_RETURN(data != nullptr, fallback); + + return data->value; + } + + const T& getValue(const T& fallback) const noexcept + { + const Data* const data(list_entry_const(fEntry, Data, siblings)); + CARLA_SAFE_ASSERT_RETURN(data != nullptr, fallback); + + return data->value; } void setValue(const T& value) noexcept { - fData = list_entry(fEntry, Data, siblings); - fData->value = value; + Data* const data(list_entry(fEntry, Data, siblings)); + CARLA_SAFE_ASSERT_RETURN(data != nullptr,); + + data->value = value; } private: - Data* fData; ListHead* fEntry; ListHead* fEntry2; const ListHead& kQueue; @@ -137,12 +147,9 @@ public: if (fCount == 0) return; - ListHead* entry; - ListHead* entry2; - - for (entry = fQueue.next, entry2 = entry->next; entry != &fQueue; entry = entry2, entry2 = entry->next) + for (ListHead *entry = fQueue.next, *entry2 = entry->next; entry != &fQueue; entry = entry2, entry2 = entry->next) { - Data* const data = list_entry(entry, Data, siblings); + Data* const data(list_entry(entry, Data, siblings)); CARLA_SAFE_ASSERT_CONTINUE(data != nullptr); _deallocate(data); @@ -181,20 +188,18 @@ public: return _add(value, false, it.fEntry->prev); } - const T& getAt(const std::size_t index, const T& fallback) const noexcept + T getAt(const std::size_t index, T& fallback, const bool removeObj) noexcept { CARLA_SAFE_ASSERT_RETURN(fCount > 0 && index < fCount, fallback); std::size_t i = 0; - ListHead* entry; - ListHead* entry2; - for (entry = fQueue.next, entry2 = entry->next; entry != &fQueue; entry = entry2, entry2 = entry->next) + for (ListHead *entry = fQueue.next, *entry2 = entry->next; entry != &fQueue; entry = entry2, entry2 = entry->next) { if (index != i++) continue; - return _get(entry, fallback); + return _get(entry, fallback, removeObj); } return fallback; @@ -205,10 +210,8 @@ public: CARLA_SAFE_ASSERT_RETURN(fCount > 0 && index < fCount, fallback); std::size_t i = 0; - ListHead* entry; - ListHead* entry2; - for (entry = fQueue.next, entry2 = entry->next; entry != &fQueue; entry = entry2, entry2 = entry->next) + for (ListHead *entry = fQueue.next, *entry2 = entry->next; entry != &fQueue; entry = entry2, entry2 = entry->next) { if (index != i++) continue; @@ -219,20 +222,18 @@ public: return fallback; } - T getAt(const std::size_t index, T& fallback, const bool removeObj) noexcept + const T& getAt(const std::size_t index, const T& fallback) const noexcept { CARLA_SAFE_ASSERT_RETURN(fCount > 0 && index < fCount, fallback); std::size_t i = 0; - ListHead* entry; - ListHead* entry2; - for (entry = fQueue.next, entry2 = entry->next; entry != &fQueue; entry = entry2, entry2 = entry->next) + for (ListHead *entry = fQueue.next, *entry2 = entry->next; entry != &fQueue; entry = entry2, entry2 = entry->next) { if (index != i++) continue; - return _get(entry, fallback, removeObj); + return _get(entry, fallback); } return fallback; @@ -283,17 +284,16 @@ public: void remove(Itenerator& it) noexcept { CARLA_SAFE_ASSERT_RETURN(it.fEntry != nullptr,); - CARLA_SAFE_ASSERT_RETURN(it.fData != nullptr,); - _delete(it.fEntry, it.fData); + Data* const data(list_entry(it.fEntry, Data, siblings)); + CARLA_SAFE_ASSERT_RETURN(data != nullptr,); + + _delete(it.fEntry, data); } bool removeOne(const T& value) noexcept { - ListHead* entry; - ListHead* entry2; - - for (entry = fQueue.next, entry2 = entry->next; entry != &fQueue; entry = entry2, entry2 = entry->next) + for (ListHead *entry = fQueue.next, *entry2 = entry->next; entry != &fQueue; entry = entry2, entry2 = entry->next) { Data* const data = list_entry(entry, Data, siblings); CARLA_SAFE_ASSERT_CONTINUE(data != nullptr); @@ -311,10 +311,7 @@ public: void removeAll(const T& value) noexcept { - ListHead* entry; - ListHead* entry2; - - for (entry = fQueue.next, entry2 = entry->next; entry != &fQueue; entry = entry2, entry2 = entry->next) + for (ListHead *entry = fQueue.next, *entry2 = entry->next; entry != &fQueue; entry = entry2, entry2 = entry->next) { Data* const data = list_entry(entry, Data, siblings); CARLA_SAFE_ASSERT_CONTINUE(data != nullptr); @@ -326,25 +323,20 @@ public: } } - void spliceAppendTo(AbstractLinkedList& list) noexcept + // move data to a new list, and clear ourselves + void moveTo(AbstractLinkedList& list, const bool inTail = true) noexcept { - if (fQueue.next == &fQueue) - return; + CARLA_SAFE_ASSERT_RETURN(fCount > 0,); - __list_splice_tail(&fQueue, &list.fQueue); - list.fCount += fCount; - - _init(); - } + if (inTail) + __list_splice_tail(&fQueue, &list.fQueue); + else + __list_splice(&fQueue, &list.fQueue); - void spliceInsertInto(AbstractLinkedList& list) noexcept - { - if (fQueue.next == &fQueue) - return; - - __list_splice(&fQueue, &list.fQueue); + //! @a list gets our items list.fCount += fCount; + //! and we get nothing _init(); } @@ -365,59 +357,63 @@ private: fQueue.prev = &fQueue; } - void _createData(Data* const data, const T& value) noexcept + bool _add(const T& value, const bool inTail, ListHead* const queue) noexcept { - ++fCount; - data->value = value; - //std::memcpy(data->value, value, kDataSize); + return _add_internal(_allocate(), value, inTail, queue); } - bool _add(const T& value, const bool inTail, ListHead* const queue) noexcept + bool _add_internal(Data* const data, const T& value, const bool inTail, ListHead* const queue) noexcept { - if (Data* const data = _allocate()) + CARLA_SAFE_ASSERT_RETURN(data != nullptr, false); + CARLA_SAFE_ASSERT_RETURN(queue != nullptr, false); + CARLA_SAFE_ASSERT_RETURN(queue->prev != nullptr, false); + CARLA_SAFE_ASSERT_RETURN(queue->next != nullptr, false); + + data->value = value; + + ListHead* const siblings(&data->siblings); + + if (inTail) { - _createData(data, value); + siblings->prev = queue->prev; + siblings->next = queue; - if (inTail) - __list_add(data->siblings, queue->prev, queue); - else - __list_add(data->siblings, queue, queue->next); + queue->prev->next = siblings; + queue->prev = siblings; + } + else + { + siblings->prev = queue; + siblings->next = queue->next; - return true; + queue->next->prev = siblings; + queue->next = siblings; } - return false; + ++fCount; + return true; } void _delete(ListHead* const entry, Data* const data) noexcept { - __list_del(entry->prev, entry->next); - entry->next = nullptr; - entry->prev = nullptr; + CARLA_SAFE_ASSERT_RETURN(entry != nullptr,); + CARLA_SAFE_ASSERT_RETURN(entry->prev != nullptr,); + CARLA_SAFE_ASSERT_RETURN(entry->next != nullptr,); - _deallocate(data); --fCount; - } - - const T& _get(ListHead* const entry, const T& fallback) const noexcept - { - const Data* const data = list_entry_const(entry, Data, siblings); - CARLA_SAFE_ASSERT_RETURN(data != nullptr, fallback); - return data->value; - } + entry->next->prev = entry->prev; + entry->prev->next = entry->next; - T& _get(ListHead* const entry, T& fallback) const noexcept - { - Data* const data = list_entry(entry, Data, siblings); - CARLA_SAFE_ASSERT_RETURN(data != nullptr, fallback); + entry->next = nullptr; + entry->prev = nullptr; - return data->value; + _deallocate(data); } T _get(ListHead* const entry, T& fallback, const bool removeObj) noexcept { - Data* const data = list_entry(entry, Data, siblings); + Data* const data(list_entry(entry, Data, siblings)); CARLA_SAFE_ASSERT_RETURN(data != nullptr, fallback); if (! removeObj) @@ -430,25 +426,20 @@ private: return value; } - /* - * Insert a new entry between two known consecutive entries. - */ - static void __list_add(ListHead& newl, ListHead* const prev, ListHead* const next) noexcept + T& _get(ListHead* const entry, T& fallback) const noexcept { - next->prev = &newl; - newl.next = next; - newl.prev = prev; - prev->next = &newl; + Data* const data(list_entry(entry, Data, siblings)); + CARLA_SAFE_ASSERT_RETURN(data != nullptr, fallback); + + return data->value; } - /* - * Delete a list entry by making the prev/next entries - * point to each other. - */ - static void __list_del(ListHead* const prev, ListHead* const next) noexcept + const T& _get(ListHead* const entry, const T& fallback) const noexcept { - next->prev = prev; - prev->next = next; + const Data* const data(list_entry_const(entry, Data, siblings)); + CARLA_SAFE_ASSERT_RETURN(data != nullptr, fallback); + + return data->value; } static void __list_splice(ListHead* const list, ListHead* const head) noexcept @@ -500,8 +491,6 @@ protected: void _deallocate(typename AbstractLinkedList::Data* const dataPtr) noexcept override { - CARLA_SAFE_ASSERT_RETURN(dataPtr != nullptr,); - std::free(dataPtr); } diff --git a/source/utils/RtLinkedList.hpp b/source/utils/RtLinkedList.hpp index e956c41fb..5de124893 100644 --- a/source/utils/RtLinkedList.hpp +++ b/source/utils/RtLinkedList.hpp @@ -37,9 +37,9 @@ public: class Pool { public: - Pool(const size_t minPreallocated, const size_t maxPreallocated) noexcept - : fHandle(nullptr), - kDataSize(sizeof(typename AbstractLinkedList::Data)) + Pool(const std::size_t minPreallocated, const std::size_t maxPreallocated) noexcept + : kDataSize(sizeof(typename AbstractLinkedList::Data)), + fHandle(nullptr) { resize(minPreallocated, maxPreallocated); } @@ -65,10 +65,12 @@ public: void deallocate(void* const dataPtr) const noexcept { + CARLA_SAFE_ASSERT_RETURN(dataPtr != nullptr,); + rtsafe_memory_pool_deallocate(fHandle, dataPtr); } - void resize(const size_t minPreallocated, const size_t maxPreallocated) noexcept + void resize(const std::size_t minPreallocated, const std::size_t maxPreallocated) noexcept { if (fHandle != nullptr) { @@ -91,8 +93,9 @@ public: } private: + const std::size_t kDataSize; + mutable RtMemPool_Handle fHandle; - const size_t kDataSize; CARLA_PREVENT_HEAP_ALLOCATION CARLA_DECLARE_NON_COPY_CLASS(Pool) @@ -114,25 +117,19 @@ public: return _add_sleepy(value, false); } - void resize(const size_t minPreallocated, const size_t maxPreallocated) noexcept + void resize(const std::size_t minPreallocated, const std::size_t maxPreallocated) noexcept { + CARLA_SAFE_ASSERT(this->fCount == 0); this->clear(); fMemPool.resize(minPreallocated, maxPreallocated); } - void spliceAppendTo(RtLinkedList& list) noexcept - { - CARLA_SAFE_ASSERT_RETURN(fMemPool == list.fMemPool,); - - AbstractLinkedList::spliceAppendTo(list); - } - - void spliceInsertInto(RtLinkedList& list) noexcept + void moveTo(RtLinkedList& list, const bool inTail) noexcept { CARLA_SAFE_ASSERT_RETURN(fMemPool == list.fMemPool,); - AbstractLinkedList::spliceInsertInto(list); + AbstractLinkedList::moveTo(list, inTail); } protected: @@ -148,8 +145,6 @@ protected: void _deallocate(typename AbstractLinkedList::Data* const dataPtr) noexcept override { - CARLA_SAFE_ASSERT_RETURN(dataPtr != nullptr,); - fMemPool.deallocate(dataPtr); } @@ -158,19 +153,7 @@ private: bool _add_sleepy(const T& value, const bool inTail) noexcept { - if (typename AbstractLinkedList::Data* const data = _allocate_sleepy()) - { - this->_createData(data, value); - - if (inTail) - this->__list_add(data->siblings, this->fQueue.prev, &(this->fQueue)); - else - this->__list_add(data->siblings, &(this->fQueue), this->fQueue.next); - - return true; - } - - return false; + return this->_add_internal(_allocate_sleepy(), value, inTail, &this->fQueue); } CARLA_PREVENT_VIRTUAL_HEAP_ALLOCATION