diff --git a/source/backend/engine/CarlaEngine.cpp b/source/backend/engine/CarlaEngine.cpp index 0481b61ca..68938fb07 100644 --- a/source/backend/engine/CarlaEngine.cpp +++ b/source/backend/engine/CarlaEngine.cpp @@ -1537,43 +1537,47 @@ void CarlaEngine::setPluginPeaks(const uint pluginId, float const inPeaks[2], fl pluginData.outsPeak[1] = outPeaks[1]; } -void CarlaEngine::saveProjectInternal(juce::MemoryOutputStream& outStrm) const +void CarlaEngine::saveProjectInternal(juce::MemoryOutputStream& outStream) const { - outStrm << "\n"; - outStrm << "\n"; - outStrm << "\n"; + outStream << "\n"; + outStream << "\n"; + outStream << "\n"; const bool isPlugin(std::strcmp(getCurrentDriverName(), "Plugin") == 0); const EngineOptions& options(pData->options); + MemoryOutputStream outSettings(1024); + + // save appropriate engine settings - outStrm << " \n"; + outSettings << " \n"; //processMode //transportMode - outStrm << " " << bool2str(options.forceStereo) << "\n"; - outStrm << " " << bool2str(options.preferPluginBridges) << "\n"; - outStrm << " " << bool2str(options.preferUiBridges) << "\n"; - outStrm << " " << bool2str(options.uisAlwaysOnTop) << "\n"; + outSettings << " " << bool2str(options.forceStereo) << "\n"; + outSettings << " " << bool2str(options.preferPluginBridges) << "\n"; + outSettings << " " << bool2str(options.preferUiBridges) << "\n"; + outSettings << " " << bool2str(options.uisAlwaysOnTop) << "\n"; - outStrm << " " << String(options.maxParameters) << "\n"; - outStrm << " " << String(options.uiBridgesTimeout) << "\n"; + outSettings << " " << String(options.maxParameters) << "\n"; + outSettings << " " << String(options.uiBridgesTimeout) << "\n"; if (isPlugin) { - outStrm << " " << xmlSafeString(options.pathLADSPA, true) << "\n"; - outStrm << " " << xmlSafeString(options.pathDSSI, true) << "\n"; - outStrm << " " << xmlSafeString(options.pathLV2, true) << "\n"; - outStrm << " " << xmlSafeString(options.pathVST, true) << "\n"; - outStrm << " " << xmlSafeString(options.pathVST3, true) << "\n"; - outStrm << " " << xmlSafeString(options.pathAU, true) << "\n"; - outStrm << " " << xmlSafeString(options.pathGIG, true) << "\n"; - outStrm << " " << xmlSafeString(options.pathSF2, true) << "\n"; - outStrm << " " << xmlSafeString(options.pathSFZ, true) << "\n"; + outSettings << " " << xmlSafeString(options.pathLADSPA, true) << "\n"; + outSettings << " " << xmlSafeString(options.pathDSSI, true) << "\n"; + outSettings << " " << xmlSafeString(options.pathLV2, true) << "\n"; + outSettings << " " << xmlSafeString(options.pathVST, true) << "\n"; + outSettings << " " << xmlSafeString(options.pathVST3, true) << "\n"; + outSettings << " " << xmlSafeString(options.pathAU, true) << "\n"; + outSettings << " " << xmlSafeString(options.pathGIG, true) << "\n"; + outSettings << " " << xmlSafeString(options.pathSF2, true) << "\n"; + outSettings << " " << xmlSafeString(options.pathSFZ, true) << "\n"; } - outStrm << " \n"; + outSettings << " \n"; + outStream << outSettings; char strBuf[STR_MAX+1]; @@ -1583,17 +1587,20 @@ void CarlaEngine::saveProjectInternal(juce::MemoryOutputStream& outStrm) const if (plugin != nullptr && plugin->isEnabled()) { - outStrm << "\n"; + MemoryOutputStream outPlugin(4096); + + outPlugin << "\n"; strBuf[0] = '\0'; plugin->getRealName(strBuf); if (strBuf[0] != '\0') - outStrm << " \n"; + outPlugin << " \n"; - outStrm << " \n"; - outStrm << plugin->getStateSave().toString(); - outStrm << " \n"; + outPlugin << " \n"; + outPlugin << plugin->getStateSave().toString(); + outPlugin << " \n"; + outStream << outPlugin; } } @@ -1617,7 +1624,9 @@ void CarlaEngine::saveProjectInternal(juce::MemoryOutputStream& outStrm) const { if (const char* const* const patchbayConns = getPatchbayConnections()) { - outStrm << "\n \n"; + MemoryOutputStream outPatchbay(2048); + + outPatchbay << "\n \n"; for (int i=0; patchbayConns[i] != nullptr && patchbayConns[i+1] != nullptr; ++i, ++i ) { @@ -1627,18 +1636,19 @@ void CarlaEngine::saveProjectInternal(juce::MemoryOutputStream& outStrm) const CARLA_SAFE_ASSERT_CONTINUE(connSource != nullptr && connSource[0] != '\0'); CARLA_SAFE_ASSERT_CONTINUE(connTarget != nullptr && connTarget[0] != '\0'); - outStrm << " \n"; - outStrm << " " << connSource << "\n"; - outStrm << " " << connTarget << "\n"; - outStrm << " \n"; + outPatchbay << " \n"; + outPatchbay << " " << connSource << "\n"; + outPatchbay << " " << connTarget << "\n"; + outPatchbay << " \n"; } - outStrm << " \n"; + outPatchbay << " \n"; + outStream << outPatchbay; } } #endif - outStrm << "\n"; + outStream << "\n"; } bool CarlaEngine::loadProjectInternal(juce::XmlDocument& xmlDoc) diff --git a/source/utils/CarlaStateUtils.cpp b/source/utils/CarlaStateUtils.cpp index 721867f98..923c88dc8 100644 --- a/source/utils/CarlaStateUtils.cpp +++ b/source/utils/CarlaStateUtils.cpp @@ -21,6 +21,8 @@ #include "CarlaMathUtils.hpp" #include "CarlaMIDI.h" +#include + using juce::String; using juce::XmlElement; @@ -50,6 +52,51 @@ static String getNewLineSplittedString(const String& string) return newString; } +// ----------------------------------------------------------------------- +// xmlSafeStringFast + +/* Based on some code by James Kanze from stackoverflow + * https://stackoverflow.com/questions/7724011/in-c-whats-the-fastest-way-to-replace-all-occurrences-of-a-substring-within */ + +static std::string replaceStdString(const std::string& original, const std::string& before, const std::string& after) +{ + std::string::const_iterator current = original.begin(), end = original.end(), next; + std::string retval; + + for (; (next = std::search(current, end, before.begin(), before.end())) != end;) + { + retval.append(current, next); + retval.append(after); + current = next + static_cast(before.size()); + } + retval.append(current, next); + return retval; +} + +static std::string xmlSafeStringFast(const char* const cstring, const bool toXml) +{ + std::string string(cstring); + + if (toXml) + { + string = replaceStdString(string, "&","&"); + string = replaceStdString(string, "<","<"); + string = replaceStdString(string, ">",">"); + string = replaceStdString(string, "'","'"); + string = replaceStdString(string, "\"","""); + } + else + { + string = replaceStdString(string, "<","<"); + string = replaceStdString(string, ">",">"); + string = replaceStdString(string, "'","'"); + string = replaceStdString(string, ""","\""); + string = replaceStdString(string, "&","&"); + } + + return string; +} + // ----------------------------------------------------------------------- // xmlSafeStringCharDup @@ -577,13 +624,13 @@ String StateSave::toString() const if (std::strcmp(stateCustomData->type, CUSTOM_DATA_TYPE_CHUNK) == 0 || std::strlen(stateCustomData->value) >= 128) { customDataXml << " \n"; - customDataXml << xmlSafeString(stateCustomData->value, true); + customDataXml << xmlSafeStringFast(stateCustomData->value, true); customDataXml << "\n \n"; } else { customDataXml << " "; - customDataXml << xmlSafeString(stateCustomData->value, true); + customDataXml << xmlSafeStringFast(stateCustomData->value, true); customDataXml << "\n"; }