| @@ -285,9 +285,7 @@ public: | |||||
| void getStateInformation (MemoryBlock& destData) override | void getStateInformation (MemoryBlock& destData) override | ||||
| { | { | ||||
| // Store an xml representation of our state. | // Store an xml representation of our state. | ||||
| std::unique_ptr<XmlElement> xmlState (state.copyState().createXml()); | |||||
| if (xmlState.get() != nullptr) | |||||
| if (auto xmlState = state.copyState().createXml()) | |||||
| copyXmlToBinary (*xmlState, destData); | copyXmlToBinary (*xmlState, destData); | ||||
| } | } | ||||
| @@ -230,8 +230,8 @@ public: | |||||
| //============================================================================== | //============================================================================== | ||||
| void getStateInformation (MemoryBlock& destData) override | void getStateInformation (MemoryBlock& destData) override | ||||
| { | { | ||||
| auto xml = std::unique_ptr<XmlElement> (parameters.state.createXml()); | |||||
| copyXmlToBinary (*xml, destData); | |||||
| if (auto xml = parameters.state.createXml()) | |||||
| copyXmlToBinary (*xml, destData); | |||||
| } | } | ||||
| void setStateInformation (const void* data, int sizeInBytes) override | void setStateInformation (const void* data, int sizeInBytes) override | ||||
| @@ -243,7 +243,7 @@ private: | |||||
| xml->addChildElement (xmlEvent); | xml->addChildElement (xmlEvent); | ||||
| } | } | ||||
| xml->writeToFile (savedEventsFile, {}); | |||||
| xml->writeTo (savedEventsFile, {}); | |||||
| } | } | ||||
| void restoreUnloggedEvents (std::deque<AnalyticsEvent>& restoredEventQueue) override | void restoreUnloggedEvents (std::deque<AnalyticsEvent>& restoredEventQueue) override | ||||
| @@ -69,10 +69,8 @@ static MemoryBlock valueTreeToMemoryBlock (const ValueTree& v) | |||||
| static String valueTreeToString (const ValueTree& v) | static String valueTreeToString (const ValueTree& v) | ||||
| { | { | ||||
| std::unique_ptr<XmlElement> xml (v.createXml()); | |||||
| if (xml.get() != nullptr) | |||||
| return xml->createDocument ({}, true, false); | |||||
| if (auto xml = v.createXml()) | |||||
| return xml->toString (XmlElement::TextFormat().singleLine().withoutHeader()); | |||||
| return {}; | return {}; | ||||
| } | } | ||||
| @@ -314,7 +314,7 @@ private: | |||||
| std::unique_ptr<XmlElement> openness; | std::unique_ptr<XmlElement> openness; | ||||
| if (rootItem.get() != nullptr) | if (rootItem.get() != nullptr) | ||||
| openness.reset (rootItem->getOpennessState()); | |||||
| openness = rootItem->getOpennessState(); | |||||
| createNewRootNode(); | createNewRootNode(); | ||||
| @@ -351,7 +351,7 @@ private: | |||||
| parsedXml.reset(); | parsedXml.reset(); | ||||
| XmlDocument doc (codeDocument.getAllContent()); | XmlDocument doc (codeDocument.getAllContent()); | ||||
| parsedXml.reset (doc.getDocumentElement()); | |||||
| parsedXml = doc.getDocumentElement(); | |||||
| if (parsedXml.get() == nullptr) | if (parsedXml.get() == nullptr) | ||||
| { | { | ||||
| @@ -242,7 +242,7 @@ Result FilterGraph::saveDocument (const File& file) | |||||
| { | { | ||||
| std::unique_ptr<XmlElement> xml (createXml()); | std::unique_ptr<XmlElement> xml (createXml()); | ||||
| if (! xml->writeToFile (file, {})) | |||||
| if (! xml->writeTo (file, {})) | |||||
| return Result::fail ("Couldn't write to the file"); | return Result::fail ("Couldn't write to the file"); | ||||
| return Result::ok(); | return Result::ok(); | ||||
| @@ -85,10 +85,8 @@ MainHostWindow::MainHostWindow() | |||||
| RuntimePermissions::request (RuntimePermissions::recordAudio, | RuntimePermissions::request (RuntimePermissions::recordAudio, | ||||
| [safeThis] (bool granted) mutable | [safeThis] (bool granted) mutable | ||||
| { | { | ||||
| std::unique_ptr<XmlElement> savedAudioState (getAppProperties().getUserSettings() | |||||
| ->getXmlValue ("audioDeviceState")); | |||||
| safeThis->deviceManager.initialise (granted ? 256 : 0, 256, savedAudioState.get(), true); | |||||
| auto savedState = getAppProperties().getUserSettings()->getXmlValue ("audioDeviceState"); | |||||
| safeThis->deviceManager.initialise (granted ? 256 : 0, 256, savedState.get(), true); | |||||
| }); | }); | ||||
| #if JUCE_IOS || JUCE_ANDROID | #if JUCE_IOS || JUCE_ANDROID | ||||
| @@ -110,9 +108,7 @@ MainHostWindow::MainHostWindow() | |||||
| InternalPluginFormat internalFormat; | InternalPluginFormat internalFormat; | ||||
| internalFormat.getAllTypes (internalTypes); | internalFormat.getAllTypes (internalTypes); | ||||
| std::unique_ptr<XmlElement> savedPluginList (getAppProperties().getUserSettings()->getXmlValue ("pluginList")); | |||||
| if (savedPluginList != nullptr) | |||||
| if (auto savedPluginList = getAppProperties().getUserSettings()->getXmlValue ("pluginList")) | |||||
| knownPluginList.recreateFromXml (*savedPluginList); | knownPluginList.recreateFromXml (*savedPluginList); | ||||
| for (auto* t : internalTypes) | for (auto* t : internalTypes) | ||||
| @@ -221,9 +217,7 @@ void MainHostWindow::changeListenerCallback (ChangeBroadcaster* changed) | |||||
| // save the plugin list every time it gets changed, so that if we're scanning | // save the plugin list every time it gets changed, so that if we're scanning | ||||
| // and it crashes, we've still saved the previous ones | // and it crashes, we've still saved the previous ones | ||||
| std::unique_ptr<XmlElement> savedPluginList (knownPluginList.createXml()); | |||||
| if (savedPluginList != nullptr) | |||||
| if (auto savedPluginList = std::unique_ptr<XmlElement> (knownPluginList.createXml())) | |||||
| { | { | ||||
| getAppProperties().getUserSettings()->setValue ("pluginList", savedPluginList.get()); | getAppProperties().getUserSettings()->setValue ("pluginList", savedPluginList.get()); | ||||
| getAppProperties().saveIfNeeded(); | getAppProperties().saveIfNeeded(); | ||||
| @@ -60,9 +60,7 @@ MainWindow::MainWindow() | |||||
| { | { | ||||
| commandManager.getKeyMappings()->resetToDefaultMappings(); | commandManager.getKeyMappings()->resetToDefaultMappings(); | ||||
| std::unique_ptr<XmlElement> keys (getGlobalProperties().getXmlValue ("keyMappings")); | |||||
| if (keys != nullptr) | |||||
| if (auto keys = getGlobalProperties().getXmlValue ("keyMappings")) | |||||
| commandManager.getKeyMappings()->restoreFromXml (*keys); | commandManager.getKeyMappings()->restoreFromXml (*keys); | ||||
| addKeyListener (commandManager.getKeyMappings()); | addKeyListener (commandManager.getKeyMappings()); | ||||
| @@ -209,7 +209,7 @@ void ProjucerAnalyticsDestination::saveUnloggedEvents (const std::deque<Analytic | |||||
| xml->addChildElement (xmlEvent); | xml->addChildElement (xmlEvent); | ||||
| } | } | ||||
| xml->writeToFile (savedEventsFile, {}); | |||||
| xml->writeTo (savedEventsFile, {}); | |||||
| } | } | ||||
| void ProjucerAnalyticsDestination::restoreUnloggedEvents (std::deque<AnalyticsEvent>& restoredEventQueue) | void ProjucerAnalyticsDestination::restoreUnloggedEvents (std::deque<AnalyticsEvent>& restoredEventQueue) | ||||
| @@ -609,7 +609,7 @@ void JucerDocumentEditor::saveLastSelectedTab() const | |||||
| { | { | ||||
| auto& projectProps = project->getStoredProperties(); | auto& projectProps = project->getStoredProperties(); | ||||
| std::unique_ptr<XmlElement> root (projectProps.getXmlValue ("GUIComponentsLastTab")); | |||||
| auto root = projectProps.getXmlValue ("GUIComponentsLastTab"); | |||||
| if (root == nullptr) | if (root == nullptr) | ||||
| root.reset (new XmlElement ("FILES")); | root.reset (new XmlElement ("FILES")); | ||||
| @@ -631,20 +631,10 @@ void JucerDocumentEditor::saveLastSelectedTab() const | |||||
| void JucerDocumentEditor::restoreLastSelectedTab() | void JucerDocumentEditor::restoreLastSelectedTab() | ||||
| { | { | ||||
| if (document != nullptr) | if (document != nullptr) | ||||
| { | |||||
| if (auto* project = document->getCppDocument().getProject()) | if (auto* project = document->getCppDocument().getProject()) | ||||
| { | |||||
| std::unique_ptr<XmlElement> root (project->getStoredProperties().getXmlValue ("GUIComponentsLastTab")); | |||||
| if (root != nullptr) | |||||
| { | |||||
| auto* child = root->getChildByName (document->getCppFile().getFileName()); | |||||
| if (child != nullptr) | |||||
| if (auto root = project->getStoredProperties().getXmlValue ("GUIComponentsLastTab")) | |||||
| if (auto child = root->getChildByName (document->getCppFile().getFileName())) | |||||
| tabbedComponent.setCurrentTabIndex (child->getIntAttribute ("tab")); | tabbedComponent.setCurrentTabIndex (child->getIntAttribute ("tab")); | ||||
| } | |||||
| } | |||||
| } | |||||
| } | } | ||||
| //============================================================================== | //============================================================================== | ||||
| @@ -109,7 +109,7 @@ public: | |||||
| void updateList() | void updateList() | ||||
| { | { | ||||
| std::unique_ptr<XmlElement> state (propsPanel->getOpennessState()); | |||||
| auto state = propsPanel->getOpennessState(); | |||||
| clear(); | clear(); | ||||
| @@ -254,19 +254,19 @@ void ComponentLayout::copySelectedToClipboard() | |||||
| for (int i = 0; i < components.size(); ++i) | for (int i = 0; i < components.size(); ++i) | ||||
| { | { | ||||
| Component* const c = components.getUnchecked(i); | |||||
| auto c = components.getUnchecked(i); | |||||
| if (selected.isSelected (c)) | if (selected.isSelected (c)) | ||||
| { | { | ||||
| if (ComponentTypeHandler* const type = ComponentTypeHandler::getHandlerFor (*c)) | |||||
| if (auto type = ComponentTypeHandler::getHandlerFor (*c)) | |||||
| { | { | ||||
| XmlElement* const e = type->createXmlFor (c, this); | |||||
| auto e = type->createXmlFor (c, this); | |||||
| clip.addChildElement (e); | clip.addChildElement (e); | ||||
| } | } | ||||
| } | } | ||||
| } | } | ||||
| SystemClipboard::copyTextToClipboard (clip.createDocument ("", false, false)); | |||||
| SystemClipboard::copyTextToClipboard (clip.toString()); | |||||
| } | } | ||||
| void ComponentLayout::paste() | void ComponentLayout::paste() | ||||
| @@ -426,7 +426,7 @@ void JucerDocument::fillInGeneratedCode (GeneratedCode& code) const | |||||
| std::unique_ptr<XmlElement> e (createXml()); | std::unique_ptr<XmlElement> e (createXml()); | ||||
| jassert (e != nullptr); | jassert (e != nullptr); | ||||
| code.jucerMetadata = e->createDocument ("", false, false); | |||||
| code.jucerMetadata = e->toString (XmlElement::TextFormat().withoutHeader()); | |||||
| resources.fillInGeneratedCode (code); | resources.fillInGeneratedCode (code); | ||||
| @@ -621,7 +621,7 @@ void JucerDocument::extractCustomPaintSnippetsFromCppFile (const String& cppCont | |||||
| applyCustomPaintSnippets (customPaintSnippets); | applyCustomPaintSnippets (customPaintSnippets); | ||||
| } | } | ||||
| XmlElement* JucerDocument::pullMetaDataFromCppFile (const String& cpp) | |||||
| std::unique_ptr<XmlElement> JucerDocument::pullMetaDataFromCppFile (const String& cpp) | |||||
| { | { | ||||
| auto lines = StringArray::fromLines (cpp); | auto lines = StringArray::fromLines (cpp); | ||||
| @@ -43,7 +43,7 @@ public: | |||||
| ~JucerDocument() override; | ~JucerDocument() override; | ||||
| static bool isValidJucerCppFile (const File&); | static bool isValidJucerCppFile (const File&); | ||||
| static XmlElement* pullMetaDataFromCppFile (const String& cpp); | |||||
| static std::unique_ptr<XmlElement> pullMetaDataFromCppFile (const String& cpp); | |||||
| static JucerDocument* createForCppFile (Project*, const File&); | static JucerDocument* createForCppFile (Project*, const File&); | ||||
| void changed(); | void changed(); | ||||
| @@ -297,7 +297,7 @@ void PaintRoutine::copySelectedToClipboard() | |||||
| if (selectedElements.isSelected (pe)) | if (selectedElements.isSelected (pe)) | ||||
| clip.addChildElement (pe->createXml()); | clip.addChildElement (pe->createXml()); | ||||
| SystemClipboard::copyTextToClipboard (clip.createDocument ("", false, false)); | |||||
| SystemClipboard::copyTextToClipboard (clip.toString()); | |||||
| } | } | ||||
| void PaintRoutine::paste() | void PaintRoutine::paste() | ||||
| @@ -293,9 +293,7 @@ LicenseState LicenseController::licenseStateFromOldSettings (XmlElement* license | |||||
| LicenseState LicenseController::licenseStateFromSettings (PropertiesFile& props) | LicenseState LicenseController::licenseStateFromSettings (PropertiesFile& props) | ||||
| { | { | ||||
| std::unique_ptr<XmlElement> licenseXml (props.getXmlValue ("license")); | |||||
| if (licenseXml != nullptr) | |||||
| if (auto licenseXml = props.getXmlValue ("license")) | |||||
| { | { | ||||
| // this is here for backwards compatibility with old-style settings files using XML text elements | // this is here for backwards compatibility with old-style settings files using XML text elements | ||||
| if (licenseXml->getChildElementAllSubText ("type", {}) != String()) | if (licenseXml->getChildElementAllSubText ("type", {}) != String()) | ||||
| @@ -315,9 +315,7 @@ void ProjectContentComponent::reloadLastOpenDocuments() | |||||
| { | { | ||||
| if (project != nullptr) | if (project != nullptr) | ||||
| { | { | ||||
| std::unique_ptr<XmlElement> xml (project->getStoredProperties().getXmlValue ("lastDocs")); | |||||
| if (xml != nullptr) | |||||
| if (auto xml = project->getStoredProperties().getXmlValue ("lastDocs")) | |||||
| { | { | ||||
| recentDocumentList.restoreFromXML (*project, *xml); | recentDocumentList.restoreFromXML (*project, *xml); | ||||
| showDocument (recentDocumentList.getCurrentDocument(), true); | showDocument (recentDocumentList.getCurrentDocument(), true); | ||||
| @@ -697,18 +697,15 @@ void Project::moveTemporaryDirectory (const File& newParentDirectory) | |||||
| bool Project::saveProjectRootToFile() | bool Project::saveProjectRootToFile() | ||||
| { | { | ||||
| std::unique_ptr<XmlElement> xml (projectRoot.createXml()); | |||||
| if (xml == nullptr) | |||||
| if (auto xml = projectRoot.createXml()) | |||||
| { | { | ||||
| jassertfalse; | |||||
| return false; | |||||
| MemoryOutputStream mo; | |||||
| xml->writeTo (mo, {}); | |||||
| return FileHelpers::overwriteFileWithNewDataIfDifferent (getFile(), mo); | |||||
| } | } | ||||
| MemoryOutputStream mo; | |||||
| xml->writeToStream (mo, {}); | |||||
| return FileHelpers::overwriteFileWithNewDataIfDifferent (getFile(), mo); | |||||
| jassertfalse; | |||||
| return false; | |||||
| } | } | ||||
| //============================================================================== | //============================================================================== | ||||
| @@ -1510,9 +1510,9 @@ private: | |||||
| } | } | ||||
| //============================================================================== | //============================================================================== | ||||
| XmlElement* createManifestXML() const | |||||
| std::unique_ptr<XmlElement> createManifestXML() const | |||||
| { | { | ||||
| auto* manifest = createManifestElement(); | |||||
| auto manifest = createManifestElement(); | |||||
| createSupportsScreensElement (*manifest); | createSupportsScreensElement (*manifest); | ||||
| createPermissionElements (*manifest); | createPermissionElements (*manifest); | ||||
| @@ -1532,12 +1532,12 @@ private: | |||||
| return manifest; | return manifest; | ||||
| } | } | ||||
| XmlElement* createManifestElement() const | |||||
| std::unique_ptr<XmlElement> createManifestElement() const | |||||
| { | { | ||||
| auto* manifest = XmlDocument::parse (androidManifestCustomXmlElements.get()); | |||||
| auto manifest = XmlDocument::parse (androidManifestCustomXmlElements.get()); | |||||
| if (manifest == nullptr) | if (manifest == nullptr) | ||||
| manifest = new XmlElement ("manifest"); | |||||
| manifest = std::make_unique<XmlElement> ("manifest"); | |||||
| setAttributeIfNotPresent (*manifest, "xmlns:android", "http://schemas.android.com/apk/res/android"); | setAttributeIfNotPresent (*manifest, "xmlns:android", "http://schemas.android.com/apk/res/android"); | ||||
| setAttributeIfNotPresent (*manifest, "android:versionCode", androidVersionCode.get()); | setAttributeIfNotPresent (*manifest, "android:versionCode", androidVersionCode.get()); | ||||
| @@ -1014,9 +1014,8 @@ private: | |||||
| { | { | ||||
| auto plistFile = exporter.getTargetFolder().getChildFile (targetAttributes["INFOPLIST_FILE"]); | auto plistFile = exporter.getTargetFolder().getChildFile (targetAttributes["INFOPLIST_FILE"]); | ||||
| XmlDocument infoPlistData (plistFile); | XmlDocument infoPlistData (plistFile); | ||||
| std::unique_ptr<XmlElement> plist (infoPlistData.getDocumentElement()); | |||||
| if (plist != nullptr) | |||||
| if (auto plist = std::unique_ptr<XmlElement> (infoPlistData.getDocumentElement())) | |||||
| { | { | ||||
| if (auto* dict = plist->getChildByName ("dict")) | if (auto* dict = plist->getChildByName ("dict")) | ||||
| { | { | ||||
| @@ -1039,7 +1038,11 @@ private: | |||||
| } | } | ||||
| auto updatedPlist = getTargetFolder().getChildFile (config.getName() + "-" + plistFile.getFileName()); | auto updatedPlist = getTargetFolder().getChildFile (config.getName() + "-" + plistFile.getFileName()); | ||||
| plist->writeToFile (updatedPlist, "<!DOCTYPE plist PUBLIC \"-//Apple//DTD PLIST 1.0//EN\" \"http://www.apple.com/DTDs/PropertyList-1.0.dtd\">"); | |||||
| XmlElement::TextFormat format; | |||||
| format.dtd = "<!DOCTYPE plist PUBLIC \"-//Apple//DTD PLIST 1.0//EN\" \"http://www.apple.com/DTDs/PropertyList-1.0.dtd\">"; | |||||
| plist->writeTo (updatedPlist, format); | |||||
| targetAttributes.set ("INFOPLIST_FILE", ("${CMAKE_CURRENT_SOURCE_DIR}/" + updatedPlist.getFileName()).quoted()); | targetAttributes.set ("INFOPLIST_FILE", ("${CMAKE_CURRENT_SOURCE_DIR}/" + updatedPlist.getFileName()).quoted()); | ||||
| } | } | ||||
| else | else | ||||
| @@ -1607,8 +1607,9 @@ public: | |||||
| dict->addChildElement (new XmlElement (e)); | dict->addChildElement (new XmlElement (e)); | ||||
| MemoryOutputStream mo; | MemoryOutputStream mo; | ||||
| plist->writeToStream (mo, "<!DOCTYPE plist PUBLIC \"-//Apple//DTD PLIST 1.0//EN\" \"http://www.apple.com/DTDs/PropertyList-1.0.dtd\">"); | |||||
| XmlElement::TextFormat format; | |||||
| format.dtd = "<!DOCTYPE plist PUBLIC \"-//Apple//DTD PLIST 1.0//EN\" \"http://www.apple.com/DTDs/PropertyList-1.0.dtd\">"; | |||||
| plist->writeTo (mo, format); | |||||
| overwriteFileIfDifferentOrThrow (infoPlistFile, mo); | overwriteFileIfDifferentOrThrow (infoPlistFile, mo); | ||||
| } | } | ||||
| @@ -443,14 +443,16 @@ protected: | |||||
| throw SaveError ("Can't create folder: " + dirToCreate.getFullPathName()); | throw SaveError ("Can't create folder: " + dirToCreate.getFullPathName()); | ||||
| } | } | ||||
| static void writeXmlOrThrow (const XmlElement& xml, const File& file, const String& encoding, int maxCharsPerLine, bool useUnixNewLines = false) | |||||
| static void writeXmlOrThrow (const XmlElement& xml, const File& file, const String& encoding, | |||||
| int maxCharsPerLine, bool useUnixNewLines = false) | |||||
| { | { | ||||
| MemoryOutputStream mo; | |||||
| XmlElement::TextFormat format; | |||||
| format.customEncoding = encoding; | |||||
| format.lineWrapLength = maxCharsPerLine; | |||||
| format.newLineChars = useUnixNewLines ? "\r\n" : "\n"; | |||||
| if (useUnixNewLines) | |||||
| mo.setNewLineString ("\n"); | |||||
| xml.writeToStream (mo, String(), false, true, encoding, maxCharsPerLine); | |||||
| MemoryOutputStream mo (8192); | |||||
| xml.writeTo (mo, format); | |||||
| overwriteFileIfDifferentOrThrow (file, mo); | overwriteFileIfDifferentOrThrow (file, mo); | ||||
| } | } | ||||
| @@ -314,8 +314,8 @@ private: | |||||
| { | { | ||||
| static const char* filesToKeep[] = { ".svn", ".cvs", "CMakeLists.txt" }; | static const char* filesToKeep[] = { ".svn", ".cvs", "CMakeLists.txt" }; | ||||
| for (int i = 0; i < numElementsInArray (filesToKeep); ++i) | |||||
| if (filename == filesToKeep[i]) | |||||
| for (auto* f : filesToKeep) | |||||
| if (filename == f) | |||||
| return true; | return true; | ||||
| return false; | return false; | ||||
| @@ -323,25 +323,27 @@ private: | |||||
| void writeMainProjectFile() | void writeMainProjectFile() | ||||
| { | { | ||||
| std::unique_ptr<XmlElement> xml (project.getProjectRoot().createXml()); | |||||
| jassert (xml != nullptr); | |||||
| if (xml != nullptr) | |||||
| if (auto xml = project.getProjectRoot().createXml()) | |||||
| { | { | ||||
| MemoryOutputStream mo; | |||||
| mo.setNewLineString (projectLineFeed); | |||||
| XmlElement::TextFormat format; | |||||
| format.newLineChars = projectLineFeed.toRawUTF8(); | |||||
| xml->writeToStream (mo, String()); | |||||
| MemoryOutputStream mo (8192); | |||||
| xml->writeTo (mo, format); | |||||
| replaceFileIfDifferent (projectFile, mo); | replaceFileIfDifferent (projectFile, mo); | ||||
| } | } | ||||
| else | |||||
| { | |||||
| jassertfalse; | |||||
| } | |||||
| } | } | ||||
| static int findLongestModuleName (const OwnedArray<LibraryModule>& modules) | static int findLongestModuleName (const OwnedArray<LibraryModule>& modules) | ||||
| { | { | ||||
| int longest = 0; | int longest = 0; | ||||
| for (int i = modules.size(); --i >= 0;) | |||||
| longest = jmax (longest, modules.getUnchecked(i)->getID().length()); | |||||
| for (auto& m : modules) | |||||
| longest = jmax (longest, m->getID().length()); | |||||
| return longest; | return longest; | ||||
| } | } | ||||
| @@ -352,8 +354,8 @@ private: | |||||
| { | { | ||||
| StringArray userContent; | StringArray userContent; | ||||
| bool foundCodeSection = false; | bool foundCodeSection = false; | ||||
| auto lines = StringArray::fromLines (getAppConfigFile().loadFileAsString()); | auto lines = StringArray::fromLines (getAppConfigFile().loadFileAsString()); | ||||
| for (int i = 0; i < lines.size(); ++i) | for (int i = 0; i < lines.size(); ++i) | ||||
| { | { | ||||
| if (lines[i].contains ("[BEGIN_USER_CODE_SECTION]")) | if (lines[i].contains ("[BEGIN_USER_CODE_SECTION]")) | ||||
| @@ -385,7 +387,7 @@ private: | |||||
| return; | return; | ||||
| } | } | ||||
| for (LibraryModule** moduleIter = modules.begin(); moduleIter != modules.end(); ++moduleIter) | |||||
| for (auto moduleIter = modules.begin(); moduleIter != modules.end(); ++moduleIter) | |||||
| { | { | ||||
| if (auto* module = *moduleIter) | if (auto* module = *moduleIter) | ||||
| { | { | ||||
| @@ -463,18 +465,14 @@ private: | |||||
| auto longestName = findLongestModuleName (modules); | auto longestName = findLongestModuleName (modules); | ||||
| for (int k = 0; k < modules.size(); ++k) | |||||
| { | |||||
| auto* m = modules.getUnchecked(k); | |||||
| for (auto& m : modules) | |||||
| out << "#define JUCE_MODULE_AVAILABLE_" << m->getID() | out << "#define JUCE_MODULE_AVAILABLE_" << m->getID() | ||||
| << String::repeatedString (" ", longestName + 5 - m->getID().length()) << " 1" << newLine; | << String::repeatedString (" ", longestName + 5 - m->getID().length()) << " 1" << newLine; | ||||
| } | |||||
| out << newLine << "#define JUCE_GLOBAL_MODULE_SETTINGS_INCLUDED 1" << newLine; | out << newLine << "#define JUCE_GLOBAL_MODULE_SETTINGS_INCLUDED 1" << newLine; | ||||
| for (int j = 0; j < modules.size(); ++j) | |||||
| for (auto& m : modules) | |||||
| { | { | ||||
| auto* m = modules.getUnchecked(j); | |||||
| OwnedArray<Project::ConfigFlag> flags; | OwnedArray<Project::ConfigFlag> flags; | ||||
| m->getConfigFlags (project, flags); | m->getConfigFlags (project, flags); | ||||
| @@ -619,6 +617,7 @@ private: | |||||
| if (resourceFile.getNumFiles() > 0) | if (resourceFile.getNumFiles() > 0) | ||||
| { | { | ||||
| auto dataNamespace = project.getBinaryDataNamespaceString().trim(); | auto dataNamespace = project.getBinaryDataNamespaceString().trim(); | ||||
| if (dataNamespace.isEmpty()) | if (dataNamespace.isEmpty()) | ||||
| dataNamespace = "BinaryData"; | dataNamespace = "BinaryData"; | ||||
| @@ -627,6 +626,7 @@ private: | |||||
| Array<File> binaryDataFiles; | Array<File> binaryDataFiles; | ||||
| auto maxSize = project.getMaxBinaryFileSize(); | auto maxSize = project.getMaxBinaryFileSize(); | ||||
| if (maxSize <= 0) | if (maxSize <= 0) | ||||
| maxSize = 10 * 1024 * 1024; | maxSize = 10 * 1024 * 1024; | ||||
| @@ -636,10 +636,8 @@ private: | |||||
| { | { | ||||
| hasBinaryData = true; | hasBinaryData = true; | ||||
| for (int i = 0; i < binaryDataFiles.size(); ++i) | |||||
| for (auto& f : binaryDataFiles) | |||||
| { | { | ||||
| auto& f = binaryDataFiles.getReference(i); | |||||
| filesCreated.add (f); | filesCreated.add (f); | ||||
| generatedFilesGroup.addFileRetainingSortOrder (f, ! f.hasFileExtension (".h")); | generatedFilesGroup.addFileRetainingSortOrder (f, ! f.hasFileExtension (".h")); | ||||
| } | } | ||||
| @@ -138,8 +138,10 @@ bool AppearanceSettings::readFromFile (const File& file) | |||||
| bool AppearanceSettings::writeToFile (const File& file) const | bool AppearanceSettings::writeToFile (const File& file) const | ||||
| { | { | ||||
| const std::unique_ptr<XmlElement> xml (settings.createXml()); | |||||
| return xml != nullptr && xml->writeToFile (file, String()); | |||||
| if (auto xml = settings.createXml()) | |||||
| return xml->writeTo (file, {}); | |||||
| return false; | |||||
| } | } | ||||
| Font AppearanceSettings::getDefaultCodeFont() | Font AppearanceSettings::getDefaultCodeFont() | ||||
| @@ -136,14 +136,10 @@ void StoredSettings::reload() | |||||
| propertyFiles.clear(); | propertyFiles.clear(); | ||||
| propertyFiles.add (createPropsFile ("Projucer", false)); | propertyFiles.add (createPropsFile ("Projucer", false)); | ||||
| std::unique_ptr<XmlElement> projectDefaultsXml (propertyFiles.getFirst()->getXmlValue ("PROJECT_DEFAULT_SETTINGS")); | |||||
| if (projectDefaultsXml != nullptr) | |||||
| if (auto projectDefaultsXml = propertyFiles.getFirst()->getXmlValue ("PROJECT_DEFAULT_SETTINGS")) | |||||
| projectDefaults = ValueTree::fromXml (*projectDefaultsXml); | projectDefaults = ValueTree::fromXml (*projectDefaultsXml); | ||||
| std::unique_ptr<XmlElement> fallbackPathsXml (propertyFiles.getFirst()->getXmlValue ("FALLBACK_PATHS")); | |||||
| if (fallbackPathsXml != nullptr) | |||||
| if (auto fallbackPathsXml = propertyFiles.getFirst()->getXmlValue ("FALLBACK_PATHS")) | |||||
| fallbackPaths = ValueTree::fromXml (*fallbackPathsXml); | fallbackPaths = ValueTree::fromXml (*fallbackPathsXml); | ||||
| // recent files... | // recent files... | ||||
| @@ -146,10 +146,9 @@ Result PIPGenerator::createJucerFile() | |||||
| auto outputFile = outputDirectory.getChildFile (metadata[Ids::name].toString() + ".jucer"); | auto outputFile = outputDirectory.getChildFile (metadata[Ids::name].toString() + ".jucer"); | ||||
| std::unique_ptr<XmlElement> xml (root.createXml()); | |||||
| if (xml->writeToFile (outputFile, {})) | |||||
| return Result::ok(); | |||||
| if (auto xml = root.createXml()) | |||||
| if (xml->writeTo (outputFile, {})) | |||||
| return Result::ok(); | |||||
| return Result::fail ("Failed to create .jucer file in " + outputDirectory.getFullPathName()); | return Result::fail ("Failed to create .jucer file in " + outputDirectory.getFullPathName()); | ||||
| } | } | ||||
| @@ -37,14 +37,12 @@ void TreePanelBase::setRoot (JucerTreeViewBase* root) | |||||
| if (project != nullptr) | if (project != nullptr) | ||||
| { | { | ||||
| const std::unique_ptr<XmlElement> treeOpenness (project->getStoredProperties() | |||||
| .getXmlValue (opennessStateKey)); | |||||
| if (treeOpenness != nullptr) | |||||
| if (auto treeOpenness = project->getStoredProperties().getXmlValue (opennessStateKey)) | |||||
| { | { | ||||
| tree.restoreOpennessState (*treeOpenness, true); | tree.restoreOpennessState (*treeOpenness, true); | ||||
| for (int i = tree.getNumSelectedItems(); --i >= 0;) | for (int i = tree.getNumSelectedItems(); --i >= 0;) | ||||
| if (JucerTreeViewBase* item = dynamic_cast<JucerTreeViewBase*> (tree.getSelectedItem (i))) | |||||
| if (auto item = dynamic_cast<JucerTreeViewBase*> (tree.getSelectedItem (i))) | |||||
| item->cancelDelayedSelectionTimer(); | item->cancelDelayedSelectionTimer(); | ||||
| } | } | ||||
| } | } | ||||
| @@ -314,7 +314,7 @@ public: | |||||
| if (settings != nullptr) | if (settings != nullptr) | ||||
| { | { | ||||
| savedState.reset (settings->getXmlValue ("audioSetup")); | |||||
| savedState = settings->getXmlValue ("audioSetup"); | |||||
| #if ! (JUCE_IOS || JUCE_ANDROID) | #if ! (JUCE_IOS || JUCE_ANDROID) | ||||
| shouldMuteInput.setValue (settings->getBoolValue ("shouldMuteInput", true)); | shouldMuteInput.setValue (settings->getBoolValue ("shouldMuteInput", true)); | ||||
| @@ -1105,7 +1105,7 @@ void AudioProcessor::copyXmlToBinary (const XmlElement& xml, juce::MemoryBlock& | |||||
| MemoryOutputStream out (destData, false); | MemoryOutputStream out (destData, false); | ||||
| out.writeInt (magicXmlNumber); | out.writeInt (magicXmlNumber); | ||||
| out.writeInt (0); | out.writeInt (0); | ||||
| xml.writeToStream (out, String(), true, false); | |||||
| xml.writeTo (out, XmlElement::TextFormat().singleLine()); | |||||
| out.writeByte (0); | out.writeByte (0); | ||||
| } | } | ||||
| @@ -1114,10 +1114,9 @@ void AudioProcessor::copyXmlToBinary (const XmlElement& xml, juce::MemoryBlock& | |||||
| = ByteOrder::swapIfBigEndian ((uint32) destData.getSize() - 9); | = ByteOrder::swapIfBigEndian ((uint32) destData.getSize() - 9); | ||||
| } | } | ||||
| XmlElement* AudioProcessor::getXmlFromBinary (const void* data, const int sizeInBytes) | |||||
| std::unique_ptr<XmlElement> AudioProcessor::getXmlFromBinary (const void* data, const int sizeInBytes) | |||||
| { | { | ||||
| if (sizeInBytes > 8 | |||||
| && ByteOrder::littleEndianInt (data) == magicXmlNumber) | |||||
| if (sizeInBytes > 8 && ByteOrder::littleEndianInt (data) == magicXmlNumber) | |||||
| { | { | ||||
| auto stringLength = (int) ByteOrder::littleEndianInt (addBytesToPointer (data, 4)); | auto stringLength = (int) ByteOrder::littleEndianInt (addBytesToPointer (data, 4)); | ||||
| @@ -1126,7 +1125,7 @@ XmlElement* AudioProcessor::getXmlFromBinary (const void* data, const int sizeIn | |||||
| jmin ((sizeInBytes - 8), stringLength))); | jmin ((sizeInBytes - 8), stringLength))); | ||||
| } | } | ||||
| return nullptr; | |||||
| return {}; | |||||
| } | } | ||||
| bool AudioProcessor::canApplyBusCountChange (bool isInput, bool isAdding, | bool AudioProcessor::canApplyBusCountChange (bool isInput, bool isAdding, | ||||
| @@ -1477,11 +1477,9 @@ public: | |||||
| juce::MemoryBlock& destData); | juce::MemoryBlock& destData); | ||||
| /** Retrieves an XML element that was stored as binary with the copyXmlToBinary() method. | /** Retrieves an XML element that was stored as binary with the copyXmlToBinary() method. | ||||
| This might return nullptr if the data's unsuitable or corrupted. Otherwise it will return | |||||
| an XmlElement object that the caller must delete when no longer needed. | |||||
| This might return nullptr if the data's unsuitable or corrupted. | |||||
| */ | */ | ||||
| static XmlElement* getXmlFromBinary (const void* data, int sizeInBytes); | |||||
| static std::unique_ptr<XmlElement> getXmlFromBinary (const void* data, int sizeInBytes); | |||||
| /** @internal */ | /** @internal */ | ||||
| static void JUCE_CALLTYPE setTypeOfNextNewPlugin (WrapperType); | static void JUCE_CALLTYPE setTypeOfNextNewPlugin (WrapperType); | ||||
| @@ -23,7 +23,7 @@ | |||||
| namespace juce | namespace juce | ||||
| { | { | ||||
| PropertySet::PropertySet (const bool ignoreCaseOfKeyNames) | |||||
| PropertySet::PropertySet (bool ignoreCaseOfKeyNames) | |||||
| : properties (ignoreCaseOfKeyNames), | : properties (ignoreCaseOfKeyNames), | ||||
| fallbackProperties (nullptr), | fallbackProperties (nullptr), | ||||
| ignoreCaseOfKeys (ignoreCaseOfKeyNames) | ignoreCaseOfKeys (ignoreCaseOfKeyNames) | ||||
| @@ -65,8 +65,7 @@ void PropertySet::clear() | |||||
| String PropertySet::getValue (StringRef keyName, const String& defaultValue) const noexcept | String PropertySet::getValue (StringRef keyName, const String& defaultValue) const noexcept | ||||
| { | { | ||||
| const ScopedLock sl (lock); | const ScopedLock sl (lock); | ||||
| const int index = properties.getAllKeys().indexOf (keyName, ignoreCaseOfKeys); | |||||
| auto index = properties.getAllKeys().indexOf (keyName, ignoreCaseOfKeys); | |||||
| if (index >= 0) | if (index >= 0) | ||||
| return properties.getAllValues() [index]; | return properties.getAllValues() [index]; | ||||
| @@ -75,10 +74,10 @@ String PropertySet::getValue (StringRef keyName, const String& defaultValue) con | |||||
| : defaultValue; | : defaultValue; | ||||
| } | } | ||||
| int PropertySet::getIntValue (StringRef keyName, const int defaultValue) const noexcept | |||||
| int PropertySet::getIntValue (StringRef keyName, int defaultValue) const noexcept | |||||
| { | { | ||||
| const ScopedLock sl (lock); | const ScopedLock sl (lock); | ||||
| const int index = properties.getAllKeys().indexOf (keyName, ignoreCaseOfKeys); | |||||
| auto index = properties.getAllKeys().indexOf (keyName, ignoreCaseOfKeys); | |||||
| if (index >= 0) | if (index >= 0) | ||||
| return properties.getAllValues() [index].getIntValue(); | return properties.getAllValues() [index].getIntValue(); | ||||
| @@ -87,10 +86,10 @@ int PropertySet::getIntValue (StringRef keyName, const int defaultValue) const n | |||||
| : defaultValue; | : defaultValue; | ||||
| } | } | ||||
| double PropertySet::getDoubleValue (StringRef keyName, const double defaultValue) const noexcept | |||||
| double PropertySet::getDoubleValue (StringRef keyName, double defaultValue) const noexcept | |||||
| { | { | ||||
| const ScopedLock sl (lock); | const ScopedLock sl (lock); | ||||
| const int index = properties.getAllKeys().indexOf (keyName, ignoreCaseOfKeys); | |||||
| auto index = properties.getAllKeys().indexOf (keyName, ignoreCaseOfKeys); | |||||
| if (index >= 0) | if (index >= 0) | ||||
| return properties.getAllValues()[index].getDoubleValue(); | return properties.getAllValues()[index].getDoubleValue(); | ||||
| @@ -99,10 +98,10 @@ double PropertySet::getDoubleValue (StringRef keyName, const double defaultValue | |||||
| : defaultValue; | : defaultValue; | ||||
| } | } | ||||
| bool PropertySet::getBoolValue (StringRef keyName, const bool defaultValue) const noexcept | |||||
| bool PropertySet::getBoolValue (StringRef keyName, bool defaultValue) const noexcept | |||||
| { | { | ||||
| const ScopedLock sl (lock); | const ScopedLock sl (lock); | ||||
| const int index = properties.getAllKeys().indexOf (keyName, ignoreCaseOfKeys); | |||||
| auto index = properties.getAllKeys().indexOf (keyName, ignoreCaseOfKeys); | |||||
| if (index >= 0) | if (index >= 0) | ||||
| return properties.getAllValues() [index].getIntValue() != 0; | return properties.getAllValues() [index].getIntValue() != 0; | ||||
| @@ -111,7 +110,7 @@ bool PropertySet::getBoolValue (StringRef keyName, const bool defaultValue) cons | |||||
| : defaultValue; | : defaultValue; | ||||
| } | } | ||||
| XmlElement* PropertySet::getXmlValue (StringRef keyName) const | |||||
| std::unique_ptr<XmlElement> PropertySet::getXmlValue (StringRef keyName) const | |||||
| { | { | ||||
| return XmlDocument::parse (getValue (keyName)); | return XmlDocument::parse (getValue (keyName)); | ||||
| } | } | ||||
| @@ -122,10 +121,9 @@ void PropertySet::setValue (const String& keyName, const var& v) | |||||
| if (keyName.isNotEmpty()) | if (keyName.isNotEmpty()) | ||||
| { | { | ||||
| const String value (v.toString()); | |||||
| auto value = v.toString(); | |||||
| const ScopedLock sl (lock); | const ScopedLock sl (lock); | ||||
| const int index = properties.getAllKeys().indexOf (keyName, ignoreCaseOfKeys); | |||||
| auto index = properties.getAllKeys().indexOf (keyName, ignoreCaseOfKeys); | |||||
| if (index < 0 || properties.getAllValues() [index] != value) | if (index < 0 || properties.getAllValues() [index] != value) | ||||
| { | { | ||||
| @@ -140,7 +138,7 @@ void PropertySet::removeValue (StringRef keyName) | |||||
| if (keyName.isNotEmpty()) | if (keyName.isNotEmpty()) | ||||
| { | { | ||||
| const ScopedLock sl (lock); | const ScopedLock sl (lock); | ||||
| const int index = properties.getAllKeys().indexOf (keyName, ignoreCaseOfKeys); | |||||
| auto index = properties.getAllKeys().indexOf (keyName, ignoreCaseOfKeys); | |||||
| if (index >= 0) | if (index >= 0) | ||||
| { | { | ||||
| @@ -150,10 +148,10 @@ void PropertySet::removeValue (StringRef keyName) | |||||
| } | } | ||||
| } | } | ||||
| void PropertySet::setValue (const String& keyName, const XmlElement* const xml) | |||||
| void PropertySet::setValue (const String& keyName, const XmlElement* xml) | |||||
| { | { | ||||
| setValue (keyName, xml == nullptr ? var() | setValue (keyName, xml == nullptr ? var() | ||||
| : var (xml->createDocument ("", true))); | |||||
| : var (xml->toString (XmlElement::TextFormat().singleLine().withoutHeader()))); | |||||
| } | } | ||||
| bool PropertySet::containsKey (StringRef keyName) const noexcept | bool PropertySet::containsKey (StringRef keyName) const noexcept | ||||
| @@ -177,14 +175,15 @@ void PropertySet::setFallbackPropertySet (PropertySet* fallbackProperties_) noex | |||||
| fallbackProperties = fallbackProperties_; | fallbackProperties = fallbackProperties_; | ||||
| } | } | ||||
| XmlElement* PropertySet::createXml (const String& nodeName) const | |||||
| std::unique_ptr<XmlElement> PropertySet::createXml (const String& nodeName) const | |||||
| { | { | ||||
| auto xml = std::make_unique<XmlElement> (nodeName); | |||||
| const ScopedLock sl (lock); | const ScopedLock sl (lock); | ||||
| XmlElement* const xml = new XmlElement (nodeName); | |||||
| for (int i = 0; i < properties.getAllKeys().size(); ++i) | for (int i = 0; i < properties.getAllKeys().size(); ++i) | ||||
| { | { | ||||
| XmlElement* const e = xml->createNewChildElement ("VALUE"); | |||||
| auto e = xml->createNewChildElement ("VALUE"); | |||||
| e->setAttribute ("name", properties.getAllKeys()[i]); | e->setAttribute ("name", properties.getAllKeys()[i]); | ||||
| e->setAttribute ("val", properties.getAllValues()[i]); | e->setAttribute ("val", properties.getAllValues()[i]); | ||||
| } | } | ||||
| @@ -113,7 +113,7 @@ public: | |||||
| @param keyName the name of the property to retrieve | @param keyName the name of the property to retrieve | ||||
| */ | */ | ||||
| XmlElement* getXmlValue (StringRef keyName) const; | |||||
| std::unique_ptr<XmlElement> getXmlValue (StringRef keyName) const; | |||||
| //============================================================================== | //============================================================================== | ||||
| /** Sets a named property. | /** Sets a named property. | ||||
| @@ -161,7 +161,7 @@ public: | |||||
| The string parameter is the tag name that should be used for the node. | The string parameter is the tag name that should be used for the node. | ||||
| @see restoreFromXml | @see restoreFromXml | ||||
| */ | */ | ||||
| XmlElement* createXml (const String& nodeName) const; | |||||
| std::unique_ptr<XmlElement> createXml (const String& nodeName) const; | |||||
| /** Reloads a set of properties that were previously stored as XML. | /** Reloads a set of properties that were previously stored as XML. | ||||
| The node passed in must have been created by the createXml() method. | The node passed in must have been created by the createXml() method. | ||||
| @@ -788,7 +788,7 @@ String URL::readEntireTextStream (bool usePostCommand) const | |||||
| return {}; | return {}; | ||||
| } | } | ||||
| XmlElement* URL::readEntireXmlStream (bool usePostCommand) const | |||||
| std::unique_ptr<XmlElement> URL::readEntireXmlStream (bool usePostCommand) const | |||||
| { | { | ||||
| return XmlDocument::parse (readEntireTextStream (usePostCommand)); | return XmlDocument::parse (readEntireTextStream (usePostCommand)); | ||||
| } | } | ||||
| @@ -797,14 +797,14 @@ XmlElement* URL::readEntireXmlStream (bool usePostCommand) const | |||||
| URL URL::withParameter (const String& parameterName, | URL URL::withParameter (const String& parameterName, | ||||
| const String& parameterValue) const | const String& parameterValue) const | ||||
| { | { | ||||
| URL u (*this); | |||||
| auto u = *this; | |||||
| u.addParameter (parameterName, parameterValue); | u.addParameter (parameterName, parameterValue); | ||||
| return u; | return u; | ||||
| } | } | ||||
| URL URL::withParameters (const StringPairArray& parametersToAdd) const | URL URL::withParameters (const StringPairArray& parametersToAdd) const | ||||
| { | { | ||||
| URL u (*this); | |||||
| auto u = *this; | |||||
| for (int i = 0; i < parametersToAdd.size(); ++i) | for (int i = 0; i < parametersToAdd.size(); ++i) | ||||
| u.addParameter (parametersToAdd.getAllKeys()[i], | u.addParameter (parametersToAdd.getAllKeys()[i], | ||||
| @@ -820,7 +820,7 @@ URL URL::withPOSTData (const String& newPostData) const | |||||
| URL URL::withPOSTData (const MemoryBlock& newPostData) const | URL URL::withPOSTData (const MemoryBlock& newPostData) const | ||||
| { | { | ||||
| URL u (*this); | |||||
| auto u = *this; | |||||
| u.postData = newPostData; | u.postData = newPostData; | ||||
| return u; | return u; | ||||
| } | } | ||||
| @@ -834,7 +834,7 @@ URL::Upload::Upload (const String& param, const String& name, | |||||
| URL URL::withUpload (Upload* const f) const | URL URL::withUpload (Upload* const f) const | ||||
| { | { | ||||
| URL u (*this); | |||||
| auto u = *this; | |||||
| for (int i = u.filesToUpload.size(); --i >= 0;) | for (int i = u.filesToUpload.size(); --i >= 0;) | ||||
| if (u.filesToUpload.getObjectPointerUnchecked(i)->parameterName == f->parameterName) | if (u.filesToUpload.getObjectPointerUnchecked(i)->parameterName == f->parameterName) | ||||
| @@ -487,7 +487,7 @@ public: | |||||
| @see readEntireBinaryStream, readEntireTextStream | @see readEntireBinaryStream, readEntireTextStream | ||||
| */ | */ | ||||
| XmlElement* readEntireXmlStream (bool usePostCommand = false) const; | |||||
| std::unique_ptr<XmlElement> readEntireXmlStream (bool usePostCommand = false) const; | |||||
| //============================================================================== | //============================================================================== | ||||
| /** Adds escape sequences to a string to encode any characters that aren't | /** Adds escape sequences to a string to encode any characters that aren't | ||||
| @@ -28,13 +28,13 @@ XmlDocument::XmlDocument (const File& file) : inputSource (new FileInputSource | |||||
| XmlDocument::~XmlDocument() {} | XmlDocument::~XmlDocument() {} | ||||
| XmlElement* XmlDocument::parse (const File& file) | |||||
| std::unique_ptr<XmlElement> XmlDocument::parse (const File& file) | |||||
| { | { | ||||
| XmlDocument doc (file); | XmlDocument doc (file); | ||||
| return doc.getDocumentElement(); | return doc.getDocumentElement(); | ||||
| } | } | ||||
| XmlElement* XmlDocument::parse (const String& xmlData) | |||||
| std::unique_ptr<XmlElement> XmlDocument::parse (const String& xmlData) | |||||
| { | { | ||||
| XmlDocument doc (xmlData); | XmlDocument doc (xmlData); | ||||
| return doc.getDocumentElement(); | return doc.getDocumentElement(); | ||||
| @@ -99,7 +99,7 @@ namespace XmlIdentifierChars | |||||
| } | } | ||||
| } | } | ||||
| XmlElement* XmlDocument::getDocumentElement (const bool onlyReadOuterDocumentElement) | |||||
| std::unique_ptr<XmlElement> XmlDocument::getDocumentElement (const bool onlyReadOuterDocumentElement) | |||||
| { | { | ||||
| if (originalText.isEmpty() && inputSource != nullptr) | if (originalText.isEmpty() && inputSource != nullptr) | ||||
| { | { | ||||
| @@ -176,8 +176,8 @@ juce_wchar XmlDocument::readNextChar() noexcept | |||||
| return c; | return c; | ||||
| } | } | ||||
| XmlElement* XmlDocument::parseDocumentElement (String::CharPointerType textToParse, | |||||
| const bool onlyReadOuterDocumentElement) | |||||
| std::unique_ptr<XmlElement> XmlDocument::parseDocumentElement (String::CharPointerType textToParse, | |||||
| bool onlyReadOuterDocumentElement) | |||||
| { | { | ||||
| input = textToParse; | input = textToParse; | ||||
| errorOccurred = false; | errorOccurred = false; | ||||
| @@ -202,10 +202,10 @@ XmlElement* XmlDocument::parseDocumentElement (String::CharPointerType textToPar | |||||
| std::unique_ptr<XmlElement> result (readNextElement (! onlyReadOuterDocumentElement)); | std::unique_ptr<XmlElement> result (readNextElement (! onlyReadOuterDocumentElement)); | ||||
| if (! errorOccurred) | if (! errorOccurred) | ||||
| return result.release(); | |||||
| return result; | |||||
| } | } | ||||
| return nullptr; | |||||
| return {}; | |||||
| } | } | ||||
| bool XmlDocument::parseHeader() | bool XmlDocument::parseHeader() | ||||
| @@ -100,7 +100,7 @@ public: | |||||
| there was an error. | there was an error. | ||||
| @see getLastParseError | @see getLastParseError | ||||
| */ | */ | ||||
| XmlElement* getDocumentElement (bool onlyReadOuterDocumentElement = false); | |||||
| std::unique_ptr<XmlElement> getDocumentElement (bool onlyReadOuterDocumentElement = false); | |||||
| /** Returns the parsing error that occurred the last time getDocumentElement was called. | /** Returns the parsing error that occurred the last time getDocumentElement was called. | ||||
| @@ -136,14 +136,14 @@ public: | |||||
| An even better shortcut is the juce::parseXML() function, which returns a std::unique_ptr<XmlElement>! | An even better shortcut is the juce::parseXML() function, which returns a std::unique_ptr<XmlElement>! | ||||
| @returns a new XmlElement which the caller will need to delete, or null if there was an error. | @returns a new XmlElement which the caller will need to delete, or null if there was an error. | ||||
| */ | */ | ||||
| static XmlElement* parse (const File& file); | |||||
| static std::unique_ptr<XmlElement> parse (const File& file); | |||||
| /** A handy static method that parses some XML data. | /** A handy static method that parses some XML data. | ||||
| This is a shortcut for creating an XmlDocument object and calling getDocumentElement() on it. | This is a shortcut for creating an XmlDocument object and calling getDocumentElement() on it. | ||||
| An even better shortcut is the juce::parseXML() function, which returns a std::unique_ptr<XmlElement>! | An even better shortcut is the juce::parseXML() function, which returns a std::unique_ptr<XmlElement>! | ||||
| @returns a new XmlElement which the caller will need to delete, or null if there was an error. | @returns a new XmlElement which the caller will need to delete, or null if there was an error. | ||||
| */ | */ | ||||
| static XmlElement* parse (const String& xmlData); | |||||
| static std::unique_ptr<XmlElement> parse (const String& xmlData); | |||||
| //============================================================================== | //============================================================================== | ||||
| @@ -156,7 +156,7 @@ private: | |||||
| bool needToLoadDTD = false, ignoreEmptyTextElements = true; | bool needToLoadDTD = false, ignoreEmptyTextElements = true; | ||||
| std::unique_ptr<InputSource> inputSource; | std::unique_ptr<InputSource> inputSource; | ||||
| XmlElement* parseDocumentElement (String::CharPointerType, bool outer); | |||||
| std::unique_ptr<XmlElement> parseDocumentElement (String::CharPointerType, bool outer); | |||||
| void setLastError (const String&, bool carryOn); | void setLastError (const String&, bool carryOn); | ||||
| bool parseHeader(); | bool parseHeader(); | ||||
| bool parseDTD(); | bool parseDTD(); | ||||
| @@ -167,50 +167,46 @@ XmlElement::~XmlElement() noexcept | |||||
| //============================================================================== | //============================================================================== | ||||
| namespace XmlOutputFunctions | namespace XmlOutputFunctions | ||||
| { | { | ||||
| #if 0 // (These functions are just used to generate the lookup table used below) | |||||
| bool isLegalXmlCharSlow (const juce_wchar character) noexcept | |||||
| namespace LegalCharLookupTable | |||||
| { | { | ||||
| if ((character >= 'a' && character <= 'z') | |||||
| || (character >= 'A' && character <= 'Z') | |||||
| || (character >= '0' && character <= '9')) | |||||
| return true; | |||||
| const char* t = " .,;:-()_+=?!'#@[]/\\*%~{}$|"; | |||||
| do | |||||
| template <int c> | |||||
| struct Bit | |||||
| { | { | ||||
| if (((juce_wchar) (uint8) *t) == character) | |||||
| return true; | |||||
| } | |||||
| while (*++t != 0); | |||||
| return false; | |||||
| } | |||||
| void generateLegalCharLookupTable() | |||||
| { | |||||
| uint8 n[32] = { 0 }; | |||||
| for (int i = 0; i < 256; ++i) | |||||
| if (isLegalXmlCharSlow (i)) | |||||
| n[i >> 3] |= (1 << (i & 7)); | |||||
| String s; | |||||
| for (int i = 0; i < 32; ++i) | |||||
| s << (int) n[i] << ", "; | |||||
| enum { v = ((c >= 'a' && c <= 'z') | |||||
| || (c >= 'A' && c <= 'Z') | |||||
| || (c >= '0' && c <= '9') | |||||
| || c == ' ' || c == '.' || c == ',' || c == ';' | |||||
| || c == ':' || c == '-' || c == '(' || c == ')' | |||||
| || c == '_' || c == '+' || c == '=' || c == '?' | |||||
| || c == '!' || c == '$' || c == '#' || c == '@' | |||||
| || c == '[' || c == ']' || c == '/' || c == '|' | |||||
| || c == '*' || c == '%' || c == '~' || c == '{' | |||||
| || c == '}' || c == '\'' || c == '\\') | |||||
| ? (1 << (c & 7)) : 0 }; | |||||
| }; | |||||
| template <int tableIndex> | |||||
| struct Byte | |||||
| { | |||||
| enum { v = Bit<tableIndex * 8 + 0>::v | Bit<tableIndex * 8 + 1>::v | |||||
| | Bit<tableIndex * 8 + 2>::v | Bit<tableIndex * 8 + 3>::v | |||||
| | Bit<tableIndex * 8 + 4>::v | Bit<tableIndex * 8 + 5>::v | |||||
| | Bit<tableIndex * 8 + 6>::v | Bit<tableIndex * 8 + 7>::v }; | |||||
| }; | |||||
| DBG (s); | |||||
| } | |||||
| #endif | |||||
| static bool isLegal (uint32 c) noexcept | |||||
| { | |||||
| static const unsigned char legalChars[] = { Byte< 0>::v, Byte< 1>::v, Byte< 2>::v, Byte< 3>::v, | |||||
| Byte< 4>::v, Byte< 5>::v, Byte< 6>::v, Byte< 7>::v, | |||||
| Byte< 8>::v, Byte< 9>::v, Byte<10>::v, Byte<11>::v, | |||||
| Byte<12>::v, Byte<13>::v, Byte<14>::v, Byte<15>::v }; | |||||
| static bool isLegalXmlChar (const uint32 c) noexcept | |||||
| { | |||||
| static const unsigned char legalChars[] = { 0, 0, 0, 0, 187, 255, 255, 175, 255, | |||||
| 255, 255, 191, 254, 255, 255, 127 }; | |||||
| return c < sizeof (legalChars) * 8 | |||||
| && (legalChars [c >> 3] & (1 << (c & 7))) != 0; | |||||
| return c < sizeof (legalChars) * 8 | |||||
| && (legalChars[c >> 3] & (1 << (c & 7))) != 0; | |||||
| } | |||||
| } | } | ||||
| static void escapeIllegalXmlChars (OutputStream& outputStream, const String& text, const bool changeNewLines) | |||||
| static void escapeIllegalXmlChars (OutputStream& outputStream, const String& text, bool changeNewLines) | |||||
| { | { | ||||
| auto t = text.getCharPointer(); | auto t = text.getCharPointer(); | ||||
| @@ -221,7 +217,7 @@ namespace XmlOutputFunctions | |||||
| if (character == 0) | if (character == 0) | ||||
| break; | break; | ||||
| if (isLegalXmlChar (character)) | |||||
| if (LegalCharLookupTable::isLegal (character)) | |||||
| { | { | ||||
| outputStream << (char) character; | outputStream << (char) character; | ||||
| } | } | ||||
| @@ -257,13 +253,12 @@ namespace XmlOutputFunctions | |||||
| } | } | ||||
| void XmlElement::writeElementAsText (OutputStream& outputStream, | void XmlElement::writeElementAsText (OutputStream& outputStream, | ||||
| const int indentationLevel, | |||||
| const int lineWrapLength) const | |||||
| int indentationLevel, | |||||
| int lineWrapLength, | |||||
| const char* newLineChars) const | |||||
| { | { | ||||
| using namespace XmlOutputFunctions; | |||||
| if (indentationLevel >= 0) | if (indentationLevel >= 0) | ||||
| writeSpaces (outputStream, (size_t) indentationLevel); | |||||
| XmlOutputFunctions::writeSpaces (outputStream, (size_t) indentationLevel); | |||||
| if (! isTextElement()) | if (! isTextElement()) | ||||
| { | { | ||||
| @@ -278,8 +273,8 @@ void XmlElement::writeElementAsText (OutputStream& outputStream, | |||||
| { | { | ||||
| if (lineLen > lineWrapLength && indentationLevel >= 0) | if (lineLen > lineWrapLength && indentationLevel >= 0) | ||||
| { | { | ||||
| outputStream << newLine; | |||||
| writeSpaces (outputStream, attIndent); | |||||
| outputStream << newLineChars; | |||||
| XmlOutputFunctions::writeSpaces (outputStream, attIndent); | |||||
| lineLen = 0; | lineLen = 0; | ||||
| } | } | ||||
| @@ -287,7 +282,7 @@ void XmlElement::writeElementAsText (OutputStream& outputStream, | |||||
| outputStream.writeByte (' '); | outputStream.writeByte (' '); | ||||
| outputStream << att->name; | outputStream << att->name; | ||||
| outputStream.write ("=\"", 2); | outputStream.write ("=\"", 2); | ||||
| escapeIllegalXmlChars (outputStream, att->value, true); | |||||
| XmlOutputFunctions::escapeIllegalXmlChars (outputStream, att->value, true); | |||||
| outputStream.writeByte ('"'); | outputStream.writeByte ('"'); | ||||
| lineLen += (int) (outputStream.getPosition() - startPos); | lineLen += (int) (outputStream.getPosition() - startPos); | ||||
| } | } | ||||
| @@ -302,24 +297,25 @@ void XmlElement::writeElementAsText (OutputStream& outputStream, | |||||
| { | { | ||||
| if (child->isTextElement()) | if (child->isTextElement()) | ||||
| { | { | ||||
| escapeIllegalXmlChars (outputStream, child->getText(), false); | |||||
| XmlOutputFunctions::escapeIllegalXmlChars (outputStream, child->getText(), false); | |||||
| lastWasTextNode = true; | lastWasTextNode = true; | ||||
| } | } | ||||
| else | else | ||||
| { | { | ||||
| if (indentationLevel >= 0 && ! lastWasTextNode) | if (indentationLevel >= 0 && ! lastWasTextNode) | ||||
| outputStream << newLine; | |||||
| outputStream << newLineChars; | |||||
| child->writeElementAsText (outputStream, | child->writeElementAsText (outputStream, | ||||
| lastWasTextNode ? 0 : (indentationLevel + (indentationLevel >= 0 ? 2 : 0)), lineWrapLength); | |||||
| lastWasTextNode ? 0 : (indentationLevel + (indentationLevel >= 0 ? 2 : 0)), lineWrapLength, | |||||
| newLineChars); | |||||
| lastWasTextNode = false; | lastWasTextNode = false; | ||||
| } | } | ||||
| } | } | ||||
| if (indentationLevel >= 0 && ! lastWasTextNode) | if (indentationLevel >= 0 && ! lastWasTextNode) | ||||
| { | { | ||||
| outputStream << newLine; | |||||
| writeSpaces (outputStream, (size_t) indentationLevel); | |||||
| outputStream << newLineChars; | |||||
| XmlOutputFunctions::writeSpaces (outputStream, (size_t) indentationLevel); | |||||
| } | } | ||||
| outputStream.write ("</", 2); | outputStream.write ("</", 2); | ||||
| @@ -333,58 +329,84 @@ void XmlElement::writeElementAsText (OutputStream& outputStream, | |||||
| } | } | ||||
| else | else | ||||
| { | { | ||||
| escapeIllegalXmlChars (outputStream, getText(), false); | |||||
| XmlOutputFunctions::escapeIllegalXmlChars (outputStream, getText(), false); | |||||
| } | } | ||||
| } | } | ||||
| String XmlElement::createDocument (StringRef dtdToUse, | |||||
| const bool allOnOneLine, | |||||
| const bool includeXmlHeader, | |||||
| StringRef encodingType, | |||||
| const int lineWrapLength) const | |||||
| XmlElement::TextFormat::TextFormat() {} | |||||
| XmlElement::TextFormat XmlElement::TextFormat::singleLine() const | |||||
| { | { | ||||
| MemoryOutputStream mem (2048); | |||||
| writeToStream (mem, dtdToUse, allOnOneLine, includeXmlHeader, encodingType, lineWrapLength); | |||||
| auto f = *this; | |||||
| f.newLineChars = nullptr; | |||||
| return f; | |||||
| } | |||||
| XmlElement::TextFormat XmlElement::TextFormat::withoutHeader() const | |||||
| { | |||||
| auto f = *this; | |||||
| f.addDefaultHeader = false; | |||||
| return f; | |||||
| } | |||||
| String XmlElement::toString (const TextFormat& options) const | |||||
| { | |||||
| MemoryOutputStream mem (2048); | |||||
| writeTo (mem, options); | |||||
| return mem.toUTF8(); | return mem.toUTF8(); | ||||
| } | } | ||||
| void XmlElement::writeToStream (OutputStream& output, StringRef dtdToUse, | |||||
| bool allOnOneLine, bool includeXmlHeader, | |||||
| StringRef encodingType, int lineWrapLength) const | |||||
| void XmlElement::writeTo (OutputStream& output, const TextFormat& options) const | |||||
| { | { | ||||
| using namespace XmlOutputFunctions; | |||||
| if (options.customHeader.isNotEmpty()) | |||||
| { | |||||
| output << options.customHeader; | |||||
| if (includeXmlHeader) | |||||
| if (options.newLineChars == nullptr) | |||||
| output.writeByte (' '); | |||||
| else | |||||
| output << options.newLineChars | |||||
| << options.newLineChars; | |||||
| } | |||||
| else if (options.addDefaultHeader) | |||||
| { | { | ||||
| output << "<?xml version=\"1.0\" encoding=\"" << encodingType << "\"?>"; | |||||
| output << "<?xml version=\"1.0\" encoding=\""; | |||||
| if (allOnOneLine) | |||||
| if (options.customEncoding.isNotEmpty()) | |||||
| output << options.customEncoding; | |||||
| else | |||||
| output << "UTF-8"; | |||||
| output << "\"?>"; | |||||
| if (options.newLineChars == nullptr) | |||||
| output.writeByte (' '); | output.writeByte (' '); | ||||
| else | else | ||||
| output << newLine << newLine; | |||||
| output << options.newLineChars | |||||
| << options.newLineChars; | |||||
| } | } | ||||
| if (dtdToUse.isNotEmpty()) | |||||
| if (options.dtd.isNotEmpty()) | |||||
| { | { | ||||
| output << dtdToUse; | |||||
| output << options.dtd; | |||||
| if (allOnOneLine) | |||||
| if (options.newLineChars == nullptr) | |||||
| output.writeByte (' '); | output.writeByte (' '); | ||||
| else | else | ||||
| output << newLine; | |||||
| output << options.newLineChars; | |||||
| } | } | ||||
| writeElementAsText (output, allOnOneLine ? -1 : 0, lineWrapLength); | |||||
| writeElementAsText (output, options.newLineChars == nullptr ? -1 : 0, | |||||
| options.lineWrapLength, | |||||
| options.newLineChars); | |||||
| if (! allOnOneLine) | |||||
| output << newLine; | |||||
| if (options.newLineChars != nullptr) | |||||
| output << options.newLineChars; | |||||
| } | } | ||||
| bool XmlElement::writeToFile (const File& file, StringRef dtdToUse, | |||||
| StringRef encodingType, int lineWrapLength) const | |||||
| bool XmlElement::writeTo (const File& destinationFile, const TextFormat& options) const | |||||
| { | { | ||||
| TemporaryFile tempFile (file); | |||||
| TemporaryFile tempFile (destinationFile); | |||||
| { | { | ||||
| FileOutputStream out (tempFile.getFile()); | FileOutputStream out (tempFile.getFile()); | ||||
| @@ -392,7 +414,7 @@ bool XmlElement::writeToFile (const File& file, StringRef dtdToUse, | |||||
| if (! out.openedOk()) | if (! out.openedOk()) | ||||
| return false; | return false; | ||||
| writeToStream (out, dtdToUse, false, true, encodingType, lineWrapLength); | |||||
| writeTo (out, options); | |||||
| out.flush(); // (called explicitly to force an fsync on posix) | out.flush(); // (called explicitly to force an fsync on posix) | ||||
| if (out.getStatus().failed()) | if (out.getStatus().failed()) | ||||
| @@ -402,6 +424,48 @@ bool XmlElement::writeToFile (const File& file, StringRef dtdToUse, | |||||
| return tempFile.overwriteTargetFileWithTemporary(); | return tempFile.overwriteTargetFileWithTemporary(); | ||||
| } | } | ||||
| String XmlElement::createDocument (StringRef dtdToUse, bool allOnOneLine, bool includeXmlHeader, | |||||
| StringRef encodingType, int lineWrapLength) const | |||||
| { | |||||
| TextFormat options; | |||||
| options.dtd = dtdToUse; | |||||
| options.customEncoding = encodingType; | |||||
| options.addDefaultHeader = includeXmlHeader; | |||||
| options.lineWrapLength = lineWrapLength; | |||||
| if (allOnOneLine) | |||||
| options.newLineChars = nullptr; | |||||
| return toString (options); | |||||
| } | |||||
| void XmlElement::writeToStream (OutputStream& output, StringRef dtdToUse, | |||||
| bool allOnOneLine, bool includeXmlHeader, | |||||
| StringRef encodingType, int lineWrapLength) const | |||||
| { | |||||
| TextFormat options; | |||||
| options.dtd = dtdToUse; | |||||
| options.customEncoding = encodingType; | |||||
| options.addDefaultHeader = includeXmlHeader; | |||||
| options.lineWrapLength = lineWrapLength; | |||||
| if (allOnOneLine) | |||||
| options.newLineChars = nullptr; | |||||
| writeTo (output, options); | |||||
| } | |||||
| bool XmlElement::writeToFile (const File& file, StringRef dtdToUse, | |||||
| StringRef encodingType, int lineWrapLength) const | |||||
| { | |||||
| TextFormat options; | |||||
| options.dtd = dtdToUse; | |||||
| options.customEncoding = encodingType; | |||||
| options.lineWrapLength = lineWrapLength; | |||||
| return writeTo (file, options); | |||||
| } | |||||
| //============================================================================== | //============================================================================== | ||||
| bool XmlElement::hasTagName (StringRef possibleTagName) const noexcept | bool XmlElement::hasTagName (StringRef possibleTagName) const noexcept | ||||
| { | { | ||||
| @@ -608,7 +672,7 @@ int XmlElement::getNumChildElements() const noexcept | |||||
| XmlElement* XmlElement::getChildElement (const int index) const noexcept | XmlElement* XmlElement::getChildElement (const int index) const noexcept | ||||
| { | { | ||||
| return firstChildElement [index].get(); | |||||
| return firstChildElement[index].get(); | |||||
| } | } | ||||
| XmlElement* XmlElement::getChildByName (StringRef childName) const noexcept | XmlElement* XmlElement::getChildByName (StringRef childName) const noexcept | ||||
| @@ -126,8 +126,8 @@ namespace juce | |||||
| animalsList.addChildElement (giraffe); | animalsList.addChildElement (giraffe); | ||||
| } | } | ||||
| // now we can turn the whole thing into a text document.. | |||||
| String myXmlDoc = animalsList.createDocument (String()); | |||||
| // now we can turn the whole thing into textual XML | |||||
| auto xmlString = animalsList.toString(); | |||||
| @endcode | @endcode | ||||
| @see XmlDocument | @see XmlDocument | ||||
| @@ -184,74 +184,37 @@ public: | |||||
| bool ignoreOrderOfAttributes) const noexcept; | bool ignoreOrderOfAttributes) const noexcept; | ||||
| //============================================================================== | //============================================================================== | ||||
| /** Returns an XML text document that represents this element. | |||||
| The string returned can be parsed to recreate the same XmlElement that | |||||
| was used to create it. | |||||
| @param dtdToUse the DTD to add to the document | |||||
| @param allOnOneLine if true, this means that the document will not contain any | |||||
| linefeeds, so it'll be smaller but not very easy to read. | |||||
| @param includeXmlHeader whether to add the "<?xml version..etc" line at the start of the | |||||
| document | |||||
| @param encodingType the character encoding format string to put into the xml | |||||
| header | |||||
| @param lineWrapLength the line length that will be used before items get placed on | |||||
| a new line. This isn't an absolute maximum length, it just | |||||
| determines how lists of attributes get broken up | |||||
| @see writeToStream, writeToFile | |||||
| */ | |||||
| String createDocument (StringRef dtdToUse, | |||||
| bool allOnOneLine = false, | |||||
| bool includeXmlHeader = true, | |||||
| StringRef encodingType = "UTF-8", | |||||
| int lineWrapLength = 60) const; | |||||
| struct TextFormat | |||||
| { | |||||
| TextFormat(); | |||||
| String dtd; /**< If supplied, this DTD will be added to the document. */ | |||||
| String customHeader; /**< If supplied, this header will be used (and customEncoding & addDefaultHeader will be ignored). */ | |||||
| String customEncoding; /**< If not empty and addDefaultHeader is true, this will be set as the encoding. Otherwise, a default of "UTF-8" will be used */ | |||||
| bool addDefaultHeader = true; /**< If true, a default header will be generated; otherwise just bare XML will be emitted. */ | |||||
| int lineWrapLength = 60; /**< A maximum line length before wrapping is done. (If allOnOneLine is true, this is ignored) */ | |||||
| const char* newLineChars = "\r\n"; /**< Allows the newline characters to be set. If you set this to nullptr, then the whole XML document will be placed on a single line. */ | |||||
| TextFormat singleLine() const; /**< returns a copy of this format with newLineChars set to nullptr. */ | |||||
| TextFormat withoutHeader() const; /**< returns a copy of this format with the addDefaultHeader flag set to false. */ | |||||
| }; | |||||
| /** Returns a text version of this XML element. | |||||
| If your intention is to write the XML to a file or stream, it's probably more efficient to | |||||
| use writeTo() instead of creating an intermediate string. | |||||
| @see writeTo | |||||
| */ | |||||
| String toString (const TextFormat& format = {}) const; | |||||
| /** Writes the document to a stream as UTF-8. | /** Writes the document to a stream as UTF-8. | ||||
| @see writeTo, toString | |||||
| */ | |||||
| void writeTo (OutputStream& output, const TextFormat& format = {}) const; | |||||
| @param output the stream to write to | |||||
| @param dtdToUse the DTD to add to the document | |||||
| @param allOnOneLine if true, this means that the document will not contain any | |||||
| linefeeds, so it'll be smaller but not very easy to read. | |||||
| @param includeXmlHeader whether to add the "<?xml version..etc" line at the start of the | |||||
| document | |||||
| @param encodingType the character encoding format string to put into the xml | |||||
| header | |||||
| @param lineWrapLength the line length that will be used before items get placed on | |||||
| a new line. This isn't an absolute maximum length, it just | |||||
| determines how lists of attributes get broken up | |||||
| @see writeToFile, createDocument | |||||
| */ | |||||
| void writeToStream (OutputStream& output, | |||||
| StringRef dtdToUse, | |||||
| bool allOnOneLine = false, | |||||
| bool includeXmlHeader = true, | |||||
| StringRef encodingType = "UTF-8", | |||||
| int lineWrapLength = 60) const; | |||||
| /** Writes the element to a file as an XML document. | |||||
| To improve safety in case something goes wrong while writing the file, this | |||||
| will actually write the document to a new temporary file in the same | |||||
| directory as the destination file, and if this succeeds, it will rename this | |||||
| new file as the destination file (overwriting any existing file that was there). | |||||
| @param destinationFile the file to write to. If this already exists, it will be | |||||
| overwritten. | |||||
| @param dtdToUse the DTD to add to the document | |||||
| @param encodingType the character encoding format string to put into the xml | |||||
| header | |||||
| @param lineWrapLength the line length that will be used before items get placed on | |||||
| a new line. This isn't an absolute maximum length, it just | |||||
| determines how lists of attributes get broken up | |||||
| @returns true if the file is written successfully; false if something goes wrong | |||||
| in the process | |||||
| @see createDocument | |||||
| */ | |||||
| bool writeToFile (const File& destinationFile, | |||||
| StringRef dtdToUse, | |||||
| StringRef encodingType = "UTF-8", | |||||
| int lineWrapLength = 60) const; | |||||
| /** Writes the document to a file as UTF-8. | |||||
| @see writeTo, toString | |||||
| */ | |||||
| bool writeTo (const File& destinationFile, const TextFormat& format = {}) const; | |||||
| //============================================================================== | //============================================================================== | ||||
| /** Returns this element's tag type name. | /** Returns this element's tag type name. | ||||
| @@ -728,6 +691,28 @@ public: | |||||
| /** Checks if a given string is a valid XML name */ | /** Checks if a given string is a valid XML name */ | ||||
| static bool isValidXmlName (StringRef possibleName) noexcept; | static bool isValidXmlName (StringRef possibleName) noexcept; | ||||
| //============================================================================== | |||||
| /** This has been deprecated in favour of the toString() method. */ | |||||
| JUCE_DEPRECATED (String createDocument (StringRef dtdToUse, | |||||
| bool allOnOneLine = false, | |||||
| bool includeXmlHeader = true, | |||||
| StringRef encodingType = "UTF-8", | |||||
| int lineWrapLength = 60) const); | |||||
| /** This has been deprecated in favour of the writeTo() method. */ | |||||
| JUCE_DEPRECATED (void writeToStream (OutputStream& output, | |||||
| StringRef dtdToUse, | |||||
| bool allOnOneLine = false, | |||||
| bool includeXmlHeader = true, | |||||
| StringRef encodingType = "UTF-8", | |||||
| int lineWrapLength = 60) const); | |||||
| /** This has been deprecated in favour of the writeTo() method. */ | |||||
| JUCE_DEPRECATED (bool writeToFile (const File& destinationFile, | |||||
| StringRef dtdToUse, | |||||
| StringRef encodingType = "UTF-8", | |||||
| int lineWrapLength = 60) const); | |||||
| //============================================================================== | //============================================================================== | ||||
| private: | private: | ||||
| struct XmlAttributeNode | struct XmlAttributeNode | ||||
| @@ -750,14 +735,13 @@ private: | |||||
| friend class LinkedListPointer<XmlElement>::Appender; | friend class LinkedListPointer<XmlElement>::Appender; | ||||
| friend class NamedValueSet; | friend class NamedValueSet; | ||||
| LinkedListPointer<XmlElement> nextListItem; | |||||
| LinkedListPointer<XmlElement> firstChildElement; | |||||
| LinkedListPointer<XmlElement> nextListItem, firstChildElement; | |||||
| LinkedListPointer<XmlAttributeNode> attributes; | LinkedListPointer<XmlAttributeNode> attributes; | ||||
| String tagName; | String tagName; | ||||
| XmlElement (int) noexcept; | XmlElement (int) noexcept; | ||||
| void copyChildrenAndAttributesFrom (const XmlElement&); | void copyChildrenAndAttributesFrom (const XmlElement&); | ||||
| void writeElementAsText (OutputStream&, int indentationLevel, int lineWrapLength) const; | |||||
| void writeElementAsText (OutputStream&, int, int, const char*) const; | |||||
| void getChildElementsAsArray (XmlElement**) const noexcept; | void getChildElementsAsArray (XmlElement**) const noexcept; | ||||
| void reorderChildElements (XmlElement**, int) noexcept; | void reorderChildElements (XmlElement**, int) noexcept; | ||||
| XmlAttributeNode* getAttribute (StringRef) const noexcept; | XmlAttributeNode* getAttribute (StringRef) const noexcept; | ||||
| @@ -187,32 +187,34 @@ bool PropertiesFile::save() | |||||
| bool PropertiesFile::loadAsXml() | bool PropertiesFile::loadAsXml() | ||||
| { | { | ||||
| XmlDocument parser (file); | XmlDocument parser (file); | ||||
| std::unique_ptr<XmlElement> doc (parser.getDocumentElement (true)); | |||||
| if (doc != nullptr && doc->hasTagName (PropertyFileConstants::fileTag)) | |||||
| if (auto doc = parser.getDocumentElement (true)) | |||||
| { | { | ||||
| doc.reset (parser.getDocumentElement()); | |||||
| if (doc != nullptr) | |||||
| if (doc->hasTagName (PropertyFileConstants::fileTag)) | |||||
| { | { | ||||
| forEachXmlChildElementWithTagName (*doc, e, PropertyFileConstants::valueTag) | |||||
| { | |||||
| auto name = e->getStringAttribute (PropertyFileConstants::nameAttribute); | |||||
| doc = parser.getDocumentElement(); | |||||
| if (name.isNotEmpty()) | |||||
| getAllProperties().set (name, | |||||
| e->getFirstChildElement() != nullptr | |||||
| ? e->getFirstChildElement()->createDocument ("", true) | |||||
| : e->getStringAttribute (PropertyFileConstants::valueAttribute)); | |||||
| if (doc != nullptr) | |||||
| { | |||||
| forEachXmlChildElementWithTagName (*doc, e, PropertyFileConstants::valueTag) | |||||
| { | |||||
| auto name = e->getStringAttribute (PropertyFileConstants::nameAttribute); | |||||
| if (name.isNotEmpty()) | |||||
| getAllProperties().set (name, | |||||
| e->getFirstChildElement() != nullptr | |||||
| ? e->getFirstChildElement()->toString (XmlElement::TextFormat().singleLine().withoutHeader()) | |||||
| : e->getStringAttribute (PropertyFileConstants::valueAttribute)); | |||||
| } | |||||
| return true; | |||||
| } | } | ||||
| return true; | |||||
| // must be a pretty broken XML file we're trying to parse here, | |||||
| // or a sign that this object needs an InterProcessLock, | |||||
| // or just a failure reading the file. This last reason is why | |||||
| // we don't jassertfalse here. | |||||
| } | } | ||||
| // must be a pretty broken XML file we're trying to parse here, | |||||
| // or a sign that this object needs an InterProcessLock, | |||||
| // or just a failure reading the file. This last reason is why | |||||
| // we don't jassertfalse here. | |||||
| } | } | ||||
| return false; | return false; | ||||
| @@ -229,8 +231,8 @@ bool PropertiesFile::saveAsXml() | |||||
| e->setAttribute (PropertyFileConstants::nameAttribute, props.getAllKeys() [i]); | e->setAttribute (PropertyFileConstants::nameAttribute, props.getAllKeys() [i]); | ||||
| // if the value seems to contain xml, store it as such.. | // if the value seems to contain xml, store it as such.. | ||||
| if (auto* childElement = XmlDocument::parse (props.getAllValues() [i])) | |||||
| e->addChildElement (childElement); | |||||
| if (auto childElement = XmlDocument::parse (props.getAllValues() [i])) | |||||
| e->addChildElement (childElement.release()); | |||||
| else | else | ||||
| e->setAttribute (PropertyFileConstants::valueAttribute, props.getAllValues() [i]); | e->setAttribute (PropertyFileConstants::valueAttribute, props.getAllValues() [i]); | ||||
| } | } | ||||
| @@ -240,7 +242,7 @@ bool PropertiesFile::saveAsXml() | |||||
| if (pl != nullptr && ! pl->isLocked()) | if (pl != nullptr && ! pl->isLocked()) | ||||
| return false; // locking failure.. | return false; // locking failure.. | ||||
| if (doc.writeToFile (file, {})) | |||||
| if (doc.writeTo (file, {})) | |||||
| { | { | ||||
| needsWriting = false; | needsWriting = false; | ||||
| return true; | return true; | ||||
| @@ -992,9 +992,9 @@ void ValueTree::sendPropertyChangeMessage (const Identifier& property) | |||||
| } | } | ||||
| //============================================================================== | //============================================================================== | ||||
| XmlElement* ValueTree::createXml() const | |||||
| std::unique_ptr<XmlElement> ValueTree::createXml() const | |||||
| { | { | ||||
| return object != nullptr ? object->createXml() : nullptr; | |||||
| return std::unique_ptr<XmlElement> (object != nullptr ? object->createXml() : nullptr); | |||||
| } | } | ||||
| ValueTree ValueTree::fromXml (const XmlElement& xml) | ValueTree ValueTree::fromXml (const XmlElement& xml) | ||||
| @@ -1015,12 +1015,10 @@ ValueTree ValueTree::fromXml (const XmlElement& xml) | |||||
| return {}; | return {}; | ||||
| } | } | ||||
| String ValueTree::toXmlString() const | |||||
| String ValueTree::toXmlString (const XmlElement::TextFormat& format) const | |||||
| { | { | ||||
| std::unique_ptr<XmlElement> xml (createXml()); | |||||
| if (xml != nullptr) | |||||
| return xml->createDocument ({}); | |||||
| if (auto xml = createXml()) | |||||
| return xml->toString (format); | |||||
| return {}; | return {}; | ||||
| } | } | ||||
| @@ -1188,8 +1186,8 @@ public: | |||||
| } | } | ||||
| expect (v1.isEquivalentTo (ValueTree::readFromGZIPData (zipped.getData(), zipped.getDataSize()))); | expect (v1.isEquivalentTo (ValueTree::readFromGZIPData (zipped.getData(), zipped.getDataSize()))); | ||||
| std::unique_ptr<XmlElement> xml1 (v1.createXml()); | |||||
| std::unique_ptr<XmlElement> xml2 (v2.createCopy().createXml()); | |||||
| auto xml1 = v1.createXml(); | |||||
| auto xml2 = v2.createCopy().createXml(); | |||||
| expect (xml1->isEquivalentTo (xml2.get(), false)); | expect (xml1->isEquivalentTo (xml2.get(), false)); | ||||
| auto v4 = v2.createCopy(); | auto v4 = v2.createCopy(); | ||||
| @@ -430,7 +430,7 @@ public: | |||||
| The caller must delete the object that is returned. | The caller must delete the object that is returned. | ||||
| @see fromXml, toXmlString | @see fromXml, toXmlString | ||||
| */ | */ | ||||
| XmlElement* createXml() const; | |||||
| std::unique_ptr<XmlElement> createXml() const; | |||||
| /** Tries to recreate a tree from its XML representation. | /** Tries to recreate a tree from its XML representation. | ||||
| This isn't designed to cope with random XML data - it should only be fed XML that was created | This isn't designed to cope with random XML data - it should only be fed XML that was created | ||||
| @@ -442,7 +442,7 @@ public: | |||||
| This is quite handy for debugging purposes, as it provides a quick way to view a tree. | This is quite handy for debugging purposes, as it provides a quick way to view a tree. | ||||
| @see createXml() | @see createXml() | ||||
| */ | */ | ||||
| String toXmlString() const; | |||||
| String toXmlString (const XmlElement::TextFormat& format = {}) const; | |||||
| //============================================================================== | //============================================================================== | ||||
| /** Stores this tree (and all its children) in a binary format. | /** Stores this tree (and all its children) in a binary format. | ||||
| @@ -65,7 +65,7 @@ void NetworkServiceDiscovery::Advertiser::sendBroadcast() | |||||
| auto localAddress = IPAddress::getLocalAddress(); | auto localAddress = IPAddress::getLocalAddress(); | ||||
| message.setAttribute ("address", localAddress.toString()); | message.setAttribute ("address", localAddress.toString()); | ||||
| auto broadcastAddress = IPAddress::getInterfaceBroadcastAddress (localAddress); | auto broadcastAddress = IPAddress::getInterfaceBroadcastAddress (localAddress); | ||||
| auto data = message.createDocument ({}, true, false); | |||||
| auto data = message.toString (XmlElement::TextFormat().singleLine().withoutHeader()); | |||||
| socket.write (broadcastAddress.toString(), broadcastPort, data.toRawUTF8(), (int) data.getNumBytesAsUTF8()); | socket.write (broadcastAddress.toString(), broadcastPort, data.toRawUTF8(), (int) data.getNumBytesAsUTF8()); | ||||
| } | } | ||||
| @@ -319,9 +319,9 @@ void PropertyPanel::removeSection (int sectionIndex) | |||||
| } | } | ||||
| //============================================================================== | //============================================================================== | ||||
| XmlElement* PropertyPanel::getOpennessState() const | |||||
| std::unique_ptr<XmlElement> PropertyPanel::getOpennessState() const | |||||
| { | { | ||||
| auto* xml = new XmlElement ("PROPERTYPANELSTATE"); | |||||
| auto xml = std::make_unique<XmlElement> ("PROPERTYPANELSTATE"); | |||||
| xml->setAttribute ("scrollPos", viewport.getViewPositionY()); | xml->setAttribute ("scrollPos", viewport.getViewPositionY()); | ||||
| @@ -123,13 +123,10 @@ public: | |||||
| //============================================================================== | //============================================================================== | ||||
| /** Saves the current state of open/closed sections so it can be restored later. | /** Saves the current state of open/closed sections so it can be restored later. | ||||
| The caller is responsible for deleting the object that is returned. | |||||
| To restore this state, use restoreOpennessState(). | To restore this state, use restoreOpennessState(). | ||||
| @see restoreOpennessState | @see restoreOpennessState | ||||
| */ | */ | ||||
| XmlElement* getOpennessState() const; | |||||
| std::unique_ptr<XmlElement> getOpennessState() const; | |||||
| /** Restores a previously saved arrangement of open/closed sections. | /** Restores a previously saved arrangement of open/closed sections. | ||||
| @@ -431,7 +431,7 @@ String TableHeaderComponent::toString() const | |||||
| e->setAttribute ("width", ci->width); | e->setAttribute ("width", ci->width); | ||||
| } | } | ||||
| return doc.createDocument ({}, true, false); | |||||
| return doc.toString (XmlElement::TextFormat().singleLine().withoutHeader()); | |||||
| } | } | ||||
| void TableHeaderComponent::restoreFromString (const String& storedVersion) | void TableHeaderComponent::restoreFromString (const String& storedVersion) | ||||
| @@ -610,7 +610,7 @@ static void addAllSelectedItemIds (TreeViewItem* item, XmlElement& parent) | |||||
| addAllSelectedItemIds (item->getSubItem(i), parent); | addAllSelectedItemIds (item->getSubItem(i), parent); | ||||
| } | } | ||||
| XmlElement* TreeView::getOpennessState (const bool alsoIncludeScrollPosition) const | |||||
| std::unique_ptr<XmlElement> TreeView::getOpennessState (const bool alsoIncludeScrollPosition) const | |||||
| { | { | ||||
| XmlElement* e = nullptr; | XmlElement* e = nullptr; | ||||
| @@ -627,7 +627,7 @@ XmlElement* TreeView::getOpennessState (const bool alsoIncludeScrollPosition) co | |||||
| } | } | ||||
| } | } | ||||
| return e; | |||||
| return std::unique_ptr<XmlElement> (e); | |||||
| } | } | ||||
| void TreeView::restoreOpennessState (const XmlElement& newState, const bool restoreStoredSelection) | void TreeView::restoreOpennessState (const XmlElement& newState, const bool restoreStoredSelection) | ||||
| @@ -1858,9 +1858,9 @@ void TreeViewItem::restoreOpennessState (const XmlElement& e) | |||||
| } | } | ||||
| } | } | ||||
| XmlElement* TreeViewItem::getOpennessState() const | |||||
| std::unique_ptr<XmlElement> TreeViewItem::getOpennessState() const | |||||
| { | { | ||||
| return getOpennessState (true); | |||||
| return std::unique_ptr<XmlElement> (getOpennessState (true)); | |||||
| } | } | ||||
| XmlElement* TreeViewItem::getOpennessState (const bool canReturnNull) const | XmlElement* TreeViewItem::getOpennessState (const bool canReturnNull) const | ||||
| @@ -514,7 +514,7 @@ public: | |||||
| @see TreeView::getOpennessState, restoreOpennessState | @see TreeView::getOpennessState, restoreOpennessState | ||||
| */ | */ | ||||
| XmlElement* getOpennessState() const; | |||||
| std::unique_ptr<XmlElement> getOpennessState() const; | |||||
| /** Restores the openness of this item and all its sub-items from a saved state. | /** Restores the openness of this item and all its sub-items from a saved state. | ||||
| @@ -818,7 +818,7 @@ public: | |||||
| so this can also be restored | so this can also be restored | ||||
| @see restoreOpennessState | @see restoreOpennessState | ||||
| */ | */ | ||||
| XmlElement* getOpennessState (bool alsoIncludeScrollPosition) const; | |||||
| std::unique_ptr<XmlElement> getOpennessState (bool alsoIncludeScrollPosition) const; | |||||
| /** Restores a previously saved arrangement of open/closed nodes. | /** Restores a previously saved arrangement of open/closed nodes. | ||||
| @@ -73,7 +73,7 @@ struct KeyFileUtils | |||||
| static String encryptXML (const XmlElement& xml, RSAKey privateKey) | static String encryptXML (const XmlElement& xml, RSAKey privateKey) | ||||
| { | { | ||||
| MemoryOutputStream text; | MemoryOutputStream text; | ||||
| text << xml.createDocument (StringRef(), true); | |||||
| text << xml.toString (XmlElement::TextFormat().singleLine()); | |||||
| BigInteger val; | BigInteger val; | ||||
| val.loadFromMemoryBlock (text.getMemoryBlock()); | val.loadFromMemoryBlock (text.getMemoryBlock()); | ||||