| @@ -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; | |||
| /*! | |||
| @@ -114,10 +114,13 @@ const char* RackGraph::MIDI::getName(const bool isInput, const uint portId) cons | |||
| { | |||
| for (LinkedList<PortNameToId>::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<PortNameToId>::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<ConnectionToId>::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<ConnectionToId>::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<uint>::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<uint>::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<uint>::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<uint>::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<ConnectionToId>::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<int>(adjustedPortA), | |||
| connection.groupB, static_cast<int>(adjustedPortB))) | |||
| if (! graph.removeConnection(connectionToId.groupA, static_cast<int>(adjustedPortA), | |||
| connectionToId.groupB, static_cast<int>(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<ConnectionToId>::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()); | |||
| @@ -568,19 +568,25 @@ public: | |||
| { | |||
| for (LinkedList<CarlaEngineJackAudioPort*>::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<CarlaEngineJackCVPort*>::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<CarlaEngineJackEventPort*>::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<uint> newPlugins; | |||
| fNewGroups.spliceInsertInto(newPlugins); | |||
| fNewGroups.moveTo(newPlugins); | |||
| for (LinkedList<uint>::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<ConnectionToId>::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<ConnectionToId>::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<GroupNameToId>::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<PortNameToId>::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); | |||
| @@ -343,7 +343,9 @@ public: | |||
| for (LinkedList<MidiInPort>::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<MidiOutPort>::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<uint>::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<uint>::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<uint>::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<uint>::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<MidiInPort>::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<MidiOutPort>::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<RtMidiEvent>::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<MidiOutPort>::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<MidiInPort>::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<MidiOutPort>::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 */); | |||
| } | |||
| }; | |||
| @@ -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<CustomData>::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<CustomData>::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<CustomData>::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<PluginPostRtEvent>::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) | |||
| { | |||
| @@ -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" | |||
| @@ -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<GroupNameToId>::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<GroupNameToId>::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<PortNameToId>::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<PortNameToId>::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; | |||
| } | |||
| @@ -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"" <Parameter>\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"" <CustomData>\n"); | |||
| customDataXml << " <Type>" << xmlSafeString(stateCustomData->type, true) << "</Type>\n"; | |||
| @@ -55,6 +55,7 @@ struct CarlaStateSave { | |||
| CustomData() noexcept; | |||
| ~CustomData() noexcept; | |||
| bool isValid() const noexcept; | |||
| CARLA_DECLARE_NON_COPY_STRUCT(CustomData) | |||
| }; | |||
| @@ -136,7 +136,7 @@ protected: | |||
| std::size_t i=0; | |||
| for (LinkedList<const char*>::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<const char*>() | |||
| { | |||
| for (Itenerator it = list.begin(); it.valid(); it.next()) | |||
| LinkedList<const char*>::append(carla_strdup_safe(it.getValue())); | |||
| LinkedList<const char*>::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<const char*>::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<const char*>::append(string); | |||
| } | |||
| @@ -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<T>& list) noexcept | |||
| // move data to a new list, and clear ourselves | |||
| void moveTo(AbstractLinkedList<T>& 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<T>& 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<T>::Data* const dataPtr) noexcept override | |||
| { | |||
| CARLA_SAFE_ASSERT_RETURN(dataPtr != nullptr,); | |||
| std::free(dataPtr); | |||
| } | |||
| @@ -37,9 +37,9 @@ public: | |||
| class Pool | |||
| { | |||
| public: | |||
| Pool(const size_t minPreallocated, const size_t maxPreallocated) noexcept | |||
| : fHandle(nullptr), | |||
| kDataSize(sizeof(typename AbstractLinkedList<T>::Data)) | |||
| Pool(const std::size_t minPreallocated, const std::size_t maxPreallocated) noexcept | |||
| : kDataSize(sizeof(typename AbstractLinkedList<T>::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<T>& list) noexcept | |||
| { | |||
| CARLA_SAFE_ASSERT_RETURN(fMemPool == list.fMemPool,); | |||
| AbstractLinkedList<T>::spliceAppendTo(list); | |||
| } | |||
| void spliceInsertInto(RtLinkedList<T>& list) noexcept | |||
| void moveTo(RtLinkedList<T>& list, const bool inTail) noexcept | |||
| { | |||
| CARLA_SAFE_ASSERT_RETURN(fMemPool == list.fMemPool,); | |||
| AbstractLinkedList<T>::spliceInsertInto(list); | |||
| AbstractLinkedList<T>::moveTo(list, inTail); | |||
| } | |||
| protected: | |||
| @@ -148,8 +145,6 @@ protected: | |||
| void _deallocate(typename AbstractLinkedList<T>::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<T>::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 | |||