Browse Source

Made a lot of the functions that used to return a raw XmlElement* instead return a std::unique_ptr<XmlElement> to make it safer and more concise to capture them. Also added new methods to XmlElement for generating text, and deprecated the old ones

tags/2021-05-28
jules 7 years ago
parent
commit
2e2cfb5f6c
48 changed files with 375 additions and 364 deletions
  1. +1
    -3
      examples/Plugins/AudioPluginDemo.h
  2. +2
    -2
      examples/Plugins/InterAppAudioEffectPluginDemo.h
  3. +1
    -1
      examples/Utilities/AnalyticsCollectionDemo.h
  4. +2
    -4
      examples/Utilities/ChildProcessDemo.h
  5. +2
    -2
      examples/Utilities/XMLandJSONDemo.h
  6. +1
    -1
      extras/AudioPluginHost/Source/Filters/FilterGraph.cpp
  7. +4
    -10
      extras/AudioPluginHost/Source/UI/MainHostWindow.cpp
  8. +1
    -3
      extras/Projucer/Source/Application/jucer_MainWindow.cpp
  9. +1
    -1
      extras/Projucer/Source/Application/jucer_ProjucerAnalytics.cpp
  10. +3
    -13
      extras/Projucer/Source/ComponentEditor/UI/jucer_JucerDocumentEditor.cpp
  11. +1
    -1
      extras/Projucer/Source/ComponentEditor/UI/jucer_PaintRoutinePanel.cpp
  12. +4
    -4
      extras/Projucer/Source/ComponentEditor/jucer_ComponentLayout.cpp
  13. +2
    -2
      extras/Projucer/Source/ComponentEditor/jucer_JucerDocument.cpp
  14. +1
    -1
      extras/Projucer/Source/ComponentEditor/jucer_JucerDocument.h
  15. +1
    -1
      extras/Projucer/Source/ComponentEditor/jucer_PaintRoutine.cpp
  16. +1
    -3
      extras/Projucer/Source/Licenses/jucer_LicenseController.cpp
  17. +1
    -3
      extras/Projucer/Source/Project/UI/jucer_ProjectContentComponent.cpp
  18. +6
    -9
      extras/Projucer/Source/Project/jucer_Project.cpp
  19. +5
    -5
      extras/Projucer/Source/ProjectSaving/jucer_ProjectExport_Android.h
  20. +6
    -3
      extras/Projucer/Source/ProjectSaving/jucer_ProjectExport_CLion.h
  21. +3
    -2
      extras/Projucer/Source/ProjectSaving/jucer_ProjectExport_Xcode.h
  22. +8
    -6
      extras/Projucer/Source/ProjectSaving/jucer_ProjectExporter.h
  23. +20
    -22
      extras/Projucer/Source/ProjectSaving/jucer_ProjectSaver.h
  24. +4
    -2
      extras/Projucer/Source/Settings/jucer_AppearanceSettings.cpp
  25. +2
    -6
      extras/Projucer/Source/Settings/jucer_StoredSettings.cpp
  26. +3
    -4
      extras/Projucer/Source/Utility/PIPs/jucer_PIPGenerator.cpp
  27. +2
    -4
      extras/Projucer/Source/Utility/UI/jucer_JucerTreeViewBase.cpp
  28. +1
    -1
      modules/juce_audio_plugin_client/Standalone/juce_StandaloneFilterWindow.h
  29. +4
    -5
      modules/juce_audio_processors/processors/juce_AudioProcessor.cpp
  30. +2
    -4
      modules/juce_audio_processors/processors/juce_AudioProcessor.h
  31. +18
    -19
      modules/juce_core/containers/juce_PropertySet.cpp
  32. +2
    -2
      modules/juce_core/containers/juce_PropertySet.h
  33. +5
    -5
      modules/juce_core/network/juce_URL.cpp
  34. +1
    -1
      modules/juce_core/network/juce_URL.h
  35. +7
    -7
      modules/juce_core/xml/juce_XmlDocument.cpp
  36. +4
    -4
      modules/juce_core/xml/juce_XmlDocument.h
  37. +144
    -80
      modules/juce_core/xml/juce_XmlElement.cpp
  38. +54
    -70
      modules/juce_core/xml/juce_XmlElement.h
  39. +24
    -22
      modules/juce_data_structures/app_properties/juce_PropertiesFile.cpp
  40. +7
    -9
      modules/juce_data_structures/values/juce_ValueTree.cpp
  41. +2
    -2
      modules/juce_data_structures/values/juce_ValueTree.h
  42. +1
    -1
      modules/juce_events/interprocess/juce_NetworkServiceDiscovery.cpp
  43. +2
    -2
      modules/juce_gui_basics/properties/juce_PropertyPanel.cpp
  44. +1
    -4
      modules/juce_gui_basics/properties/juce_PropertyPanel.h
  45. +1
    -1
      modules/juce_gui_basics/widgets/juce_TableHeaderComponent.cpp
  46. +4
    -4
      modules/juce_gui_basics/widgets/juce_TreeView.cpp
  47. +2
    -2
      modules/juce_gui_basics/widgets/juce_TreeView.h
  48. +1
    -1
      modules/juce_product_unlocking/marketplace/juce_OnlineUnlockStatus.cpp

+ 1
- 3
examples/Plugins/AudioPluginDemo.h View File

@@ -285,9 +285,7 @@ public:
void getStateInformation (MemoryBlock& destData) override
{
// 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);
}


+ 2
- 2
examples/Plugins/InterAppAudioEffectPluginDemo.h View File

@@ -230,8 +230,8 @@ public:
//==============================================================================
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


+ 1
- 1
examples/Utilities/AnalyticsCollectionDemo.h View File

@@ -243,7 +243,7 @@ private:
xml->addChildElement (xmlEvent);
}
xml->writeToFile (savedEventsFile, {});
xml->writeTo (savedEventsFile, {});
}
void restoreUnloggedEvents (std::deque<AnalyticsEvent>& restoredEventQueue) override


+ 2
- 4
examples/Utilities/ChildProcessDemo.h View File

@@ -69,10 +69,8 @@ static MemoryBlock valueTreeToMemoryBlock (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 {};
}


+ 2
- 2
examples/Utilities/XMLandJSONDemo.h View File

@@ -314,7 +314,7 @@ private:
std::unique_ptr<XmlElement> openness;
if (rootItem.get() != nullptr)
openness.reset (rootItem->getOpennessState());
openness = rootItem->getOpennessState();
createNewRootNode();
@@ -351,7 +351,7 @@ private:
parsedXml.reset();
XmlDocument doc (codeDocument.getAllContent());
parsedXml.reset (doc.getDocumentElement());
parsedXml = doc.getDocumentElement();
if (parsedXml.get() == nullptr)
{


+ 1
- 1
extras/AudioPluginHost/Source/Filters/FilterGraph.cpp View File

@@ -242,7 +242,7 @@ Result FilterGraph::saveDocument (const File& file)
{
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::ok();


+ 4
- 10
extras/AudioPluginHost/Source/UI/MainHostWindow.cpp View File

@@ -85,10 +85,8 @@ MainHostWindow::MainHostWindow()
RuntimePermissions::request (RuntimePermissions::recordAudio,
[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
@@ -110,9 +108,7 @@ MainHostWindow::MainHostWindow()
InternalPluginFormat internalFormat;
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);
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
// 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().saveIfNeeded();


+ 1
- 3
extras/Projucer/Source/Application/jucer_MainWindow.cpp View File

@@ -60,9 +60,7 @@ MainWindow::MainWindow()
{
commandManager.getKeyMappings()->resetToDefaultMappings();
std::unique_ptr<XmlElement> keys (getGlobalProperties().getXmlValue ("keyMappings"));
if (keys != nullptr)
if (auto keys = getGlobalProperties().getXmlValue ("keyMappings"))
commandManager.getKeyMappings()->restoreFromXml (*keys);
addKeyListener (commandManager.getKeyMappings());


+ 1
- 1
extras/Projucer/Source/Application/jucer_ProjucerAnalytics.cpp View File

@@ -209,7 +209,7 @@ void ProjucerAnalyticsDestination::saveUnloggedEvents (const std::deque<Analytic
xml->addChildElement (xmlEvent);
}
xml->writeToFile (savedEventsFile, {});
xml->writeTo (savedEventsFile, {});
}
void ProjucerAnalyticsDestination::restoreUnloggedEvents (std::deque<AnalyticsEvent>& restoredEventQueue)


+ 3
- 13
extras/Projucer/Source/ComponentEditor/UI/jucer_JucerDocumentEditor.cpp View File

@@ -609,7 +609,7 @@ void JucerDocumentEditor::saveLastSelectedTab() const
{
auto& projectProps = project->getStoredProperties();
std::unique_ptr<XmlElement> root (projectProps.getXmlValue ("GUIComponentsLastTab"));
auto root = projectProps.getXmlValue ("GUIComponentsLastTab");
if (root == nullptr)
root.reset (new XmlElement ("FILES"));
@@ -631,20 +631,10 @@ void JucerDocumentEditor::saveLastSelectedTab() const
void JucerDocumentEditor::restoreLastSelectedTab()
{
if (document != nullptr)
{
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"));
}
}
}
}
//==============================================================================


+ 1
- 1
extras/Projucer/Source/ComponentEditor/UI/jucer_PaintRoutinePanel.cpp View File

@@ -109,7 +109,7 @@ public:
void updateList()
{
std::unique_ptr<XmlElement> state (propsPanel->getOpennessState());
auto state = propsPanel->getOpennessState();
clear();


+ 4
- 4
extras/Projucer/Source/ComponentEditor/jucer_ComponentLayout.cpp View File

@@ -254,19 +254,19 @@ void ComponentLayout::copySelectedToClipboard()
for (int i = 0; i < components.size(); ++i)
{
Component* const c = components.getUnchecked(i);
auto c = components.getUnchecked(i);
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);
}
}
}
SystemClipboard::copyTextToClipboard (clip.createDocument ("", false, false));
SystemClipboard::copyTextToClipboard (clip.toString());
}
void ComponentLayout::paste()


+ 2
- 2
extras/Projucer/Source/ComponentEditor/jucer_JucerDocument.cpp View File

@@ -426,7 +426,7 @@ void JucerDocument::fillInGeneratedCode (GeneratedCode& code) const
std::unique_ptr<XmlElement> e (createXml());
jassert (e != nullptr);
code.jucerMetadata = e->createDocument ("", false, false);
code.jucerMetadata = e->toString (XmlElement::TextFormat().withoutHeader());
resources.fillInGeneratedCode (code);
@@ -621,7 +621,7 @@ void JucerDocument::extractCustomPaintSnippetsFromCppFile (const String& cppCont
applyCustomPaintSnippets (customPaintSnippets);
}
XmlElement* JucerDocument::pullMetaDataFromCppFile (const String& cpp)
std::unique_ptr<XmlElement> JucerDocument::pullMetaDataFromCppFile (const String& cpp)
{
auto lines = StringArray::fromLines (cpp);


+ 1
- 1
extras/Projucer/Source/ComponentEditor/jucer_JucerDocument.h View File

@@ -43,7 +43,7 @@ public:
~JucerDocument() override;
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&);
void changed();


+ 1
- 1
extras/Projucer/Source/ComponentEditor/jucer_PaintRoutine.cpp View File

@@ -297,7 +297,7 @@ void PaintRoutine::copySelectedToClipboard()
if (selectedElements.isSelected (pe))
clip.addChildElement (pe->createXml());
SystemClipboard::copyTextToClipboard (clip.createDocument ("", false, false));
SystemClipboard::copyTextToClipboard (clip.toString());
}
void PaintRoutine::paste()


+ 1
- 3
extras/Projucer/Source/Licenses/jucer_LicenseController.cpp View File

@@ -293,9 +293,7 @@ LicenseState LicenseController::licenseStateFromOldSettings (XmlElement* license
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
if (licenseXml->getChildElementAllSubText ("type", {}) != String())


+ 1
- 3
extras/Projucer/Source/Project/UI/jucer_ProjectContentComponent.cpp View File

@@ -315,9 +315,7 @@ void ProjectContentComponent::reloadLastOpenDocuments()
{
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);
showDocument (recentDocumentList.getCurrentDocument(), true);


+ 6
- 9
extras/Projucer/Source/Project/jucer_Project.cpp View File

@@ -697,18 +697,15 @@ void Project::moveTemporaryDirectory (const File& newParentDirectory)
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;
}
//==============================================================================


+ 5
- 5
extras/Projucer/Source/ProjectSaving/jucer_ProjectExport_Android.h View File

@@ -1510,9 +1510,9 @@ private:
}
//==============================================================================
XmlElement* createManifestXML() const
std::unique_ptr<XmlElement> createManifestXML() const
{
auto* manifest = createManifestElement();
auto manifest = createManifestElement();
createSupportsScreensElement (*manifest);
createPermissionElements (*manifest);
@@ -1532,12 +1532,12 @@ private:
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)
manifest = new XmlElement ("manifest");
manifest = std::make_unique<XmlElement> ("manifest");
setAttributeIfNotPresent (*manifest, "xmlns:android", "http://schemas.android.com/apk/res/android");
setAttributeIfNotPresent (*manifest, "android:versionCode", androidVersionCode.get());


+ 6
- 3
extras/Projucer/Source/ProjectSaving/jucer_ProjectExport_CLion.h View File

@@ -1014,9 +1014,8 @@ private:
{
auto plistFile = exporter.getTargetFolder().getChildFile (targetAttributes["INFOPLIST_FILE"]);
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"))
{
@@ -1039,7 +1038,11 @@ private:
}
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());
}
else


+ 3
- 2
extras/Projucer/Source/ProjectSaving/jucer_ProjectExport_Xcode.h View File

@@ -1607,8 +1607,9 @@ public:
dict->addChildElement (new XmlElement (e));
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);
}


+ 8
- 6
extras/Projucer/Source/ProjectSaving/jucer_ProjectExporter.h View File

@@ -443,14 +443,16 @@ protected:
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);
}


+ 20
- 22
extras/Projucer/Source/ProjectSaving/jucer_ProjectSaver.h View File

@@ -314,8 +314,8 @@ private:
{
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 false;
@@ -323,25 +323,27 @@ private:
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);
}
else
{
jassertfalse;
}
}
static int findLongestModuleName (const OwnedArray<LibraryModule>& modules)
{
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;
}
@@ -352,8 +354,8 @@ private:
{
StringArray userContent;
bool foundCodeSection = false;
auto lines = StringArray::fromLines (getAppConfigFile().loadFileAsString());
for (int i = 0; i < lines.size(); ++i)
{
if (lines[i].contains ("[BEGIN_USER_CODE_SECTION]"))
@@ -385,7 +387,7 @@ private:
return;
}
for (LibraryModule** moduleIter = modules.begin(); moduleIter != modules.end(); ++moduleIter)
for (auto moduleIter = modules.begin(); moduleIter != modules.end(); ++moduleIter)
{
if (auto* module = *moduleIter)
{
@@ -463,18 +465,14 @@ private:
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()
<< String::repeatedString (" ", longestName + 5 - m->getID().length()) << " 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;
m->getConfigFlags (project, flags);
@@ -619,6 +617,7 @@ private:
if (resourceFile.getNumFiles() > 0)
{
auto dataNamespace = project.getBinaryDataNamespaceString().trim();
if (dataNamespace.isEmpty())
dataNamespace = "BinaryData";
@@ -627,6 +626,7 @@ private:
Array<File> binaryDataFiles;
auto maxSize = project.getMaxBinaryFileSize();
if (maxSize <= 0)
maxSize = 10 * 1024 * 1024;
@@ -636,10 +636,8 @@ private:
{
hasBinaryData = true;
for (int i = 0; i < binaryDataFiles.size(); ++i)
for (auto& f : binaryDataFiles)
{
auto& f = binaryDataFiles.getReference(i);
filesCreated.add (f);
generatedFilesGroup.addFileRetainingSortOrder (f, ! f.hasFileExtension (".h"));
}


+ 4
- 2
extras/Projucer/Source/Settings/jucer_AppearanceSettings.cpp View File

@@ -138,8 +138,10 @@ bool AppearanceSettings::readFromFile (const File& file)
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()


+ 2
- 6
extras/Projucer/Source/Settings/jucer_StoredSettings.cpp View File

@@ -136,14 +136,10 @@ void StoredSettings::reload()
propertyFiles.clear();
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);
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);
// recent files...


+ 3
- 4
extras/Projucer/Source/Utility/PIPs/jucer_PIPGenerator.cpp View File

@@ -146,10 +146,9 @@ Result PIPGenerator::createJucerFile()
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());
}


+ 2
- 4
extras/Projucer/Source/Utility/UI/jucer_JucerTreeViewBase.cpp View File

@@ -37,14 +37,12 @@ void TreePanelBase::setRoot (JucerTreeViewBase* root)
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);
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();
}
}


+ 1
- 1
modules/juce_audio_plugin_client/Standalone/juce_StandaloneFilterWindow.h View File

@@ -314,7 +314,7 @@ public:
if (settings != nullptr)
{
savedState.reset (settings->getXmlValue ("audioSetup"));
savedState = settings->getXmlValue ("audioSetup");
#if ! (JUCE_IOS || JUCE_ANDROID)
shouldMuteInput.setValue (settings->getBoolValue ("shouldMuteInput", true));


+ 4
- 5
modules/juce_audio_processors/processors/juce_AudioProcessor.cpp View File

@@ -1105,7 +1105,7 @@ void AudioProcessor::copyXmlToBinary (const XmlElement& xml, juce::MemoryBlock&
MemoryOutputStream out (destData, false);
out.writeInt (magicXmlNumber);
out.writeInt (0);
xml.writeToStream (out, String(), true, false);
xml.writeTo (out, XmlElement::TextFormat().singleLine());
out.writeByte (0);
}
@@ -1114,10 +1114,9 @@ void AudioProcessor::copyXmlToBinary (const XmlElement& xml, juce::MemoryBlock&
= 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));
@@ -1126,7 +1125,7 @@ XmlElement* AudioProcessor::getXmlFromBinary (const void* data, const int sizeIn
jmin ((sizeInBytes - 8), stringLength)));
}
return nullptr;
return {};
}
bool AudioProcessor::canApplyBusCountChange (bool isInput, bool isAdding,


+ 2
- 4
modules/juce_audio_processors/processors/juce_AudioProcessor.h View File

@@ -1477,11 +1477,9 @@ public:
juce::MemoryBlock& destData);
/** 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 */
static void JUCE_CALLTYPE setTypeOfNextNewPlugin (WrapperType);


+ 18
- 19
modules/juce_core/containers/juce_PropertySet.cpp View File

@@ -23,7 +23,7 @@
namespace juce
{
PropertySet::PropertySet (const bool ignoreCaseOfKeyNames)
PropertySet::PropertySet (bool ignoreCaseOfKeyNames)
: properties (ignoreCaseOfKeyNames),
fallbackProperties (nullptr),
ignoreCaseOfKeys (ignoreCaseOfKeyNames)
@@ -65,8 +65,7 @@ void PropertySet::clear()
String PropertySet::getValue (StringRef keyName, const String& defaultValue) const noexcept
{
const ScopedLock sl (lock);
const int index = properties.getAllKeys().indexOf (keyName, ignoreCaseOfKeys);
auto index = properties.getAllKeys().indexOf (keyName, ignoreCaseOfKeys);
if (index >= 0)
return properties.getAllValues() [index];
@@ -75,10 +74,10 @@ String PropertySet::getValue (StringRef keyName, const String& defaultValue) con
: 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 int index = properties.getAllKeys().indexOf (keyName, ignoreCaseOfKeys);
auto index = properties.getAllKeys().indexOf (keyName, ignoreCaseOfKeys);
if (index >= 0)
return properties.getAllValues() [index].getIntValue();
@@ -87,10 +86,10 @@ int PropertySet::getIntValue (StringRef keyName, const int defaultValue) const n
: 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 int index = properties.getAllKeys().indexOf (keyName, ignoreCaseOfKeys);
auto index = properties.getAllKeys().indexOf (keyName, ignoreCaseOfKeys);
if (index >= 0)
return properties.getAllValues()[index].getDoubleValue();
@@ -99,10 +98,10 @@ double PropertySet::getDoubleValue (StringRef keyName, const double 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 int index = properties.getAllKeys().indexOf (keyName, ignoreCaseOfKeys);
auto index = properties.getAllKeys().indexOf (keyName, ignoreCaseOfKeys);
if (index >= 0)
return properties.getAllValues() [index].getIntValue() != 0;
@@ -111,7 +110,7 @@ bool PropertySet::getBoolValue (StringRef keyName, const bool defaultValue) cons
: defaultValue;
}
XmlElement* PropertySet::getXmlValue (StringRef keyName) const
std::unique_ptr<XmlElement> PropertySet::getXmlValue (StringRef keyName) const
{
return XmlDocument::parse (getValue (keyName));
}
@@ -122,10 +121,9 @@ void PropertySet::setValue (const String& keyName, const var& v)
if (keyName.isNotEmpty())
{
const String value (v.toString());
auto value = v.toString();
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)
{
@@ -140,7 +138,7 @@ void PropertySet::removeValue (StringRef keyName)
if (keyName.isNotEmpty())
{
const ScopedLock sl (lock);
const int index = properties.getAllKeys().indexOf (keyName, ignoreCaseOfKeys);
auto index = properties.getAllKeys().indexOf (keyName, ignoreCaseOfKeys);
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()
: var (xml->createDocument ("", true)));
: var (xml->toString (XmlElement::TextFormat().singleLine().withoutHeader())));
}
bool PropertySet::containsKey (StringRef keyName) const noexcept
@@ -177,14 +175,15 @@ void PropertySet::setFallbackPropertySet (PropertySet* fallbackProperties_) noex
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);
XmlElement* const xml = new XmlElement (nodeName);
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 ("val", properties.getAllValues()[i]);
}


+ 2
- 2
modules/juce_core/containers/juce_PropertySet.h View File

@@ -113,7 +113,7 @@ public:
@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.
@@ -161,7 +161,7 @@ public:
The string parameter is the tag name that should be used for the node.
@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.
The node passed in must have been created by the createXml() method.


+ 5
- 5
modules/juce_core/network/juce_URL.cpp View File

@@ -788,7 +788,7 @@ String URL::readEntireTextStream (bool usePostCommand) const
return {};
}
XmlElement* URL::readEntireXmlStream (bool usePostCommand) const
std::unique_ptr<XmlElement> URL::readEntireXmlStream (bool usePostCommand) const
{
return XmlDocument::parse (readEntireTextStream (usePostCommand));
}
@@ -797,14 +797,14 @@ XmlElement* URL::readEntireXmlStream (bool usePostCommand) const
URL URL::withParameter (const String& parameterName,
const String& parameterValue) const
{
URL u (*this);
auto u = *this;
u.addParameter (parameterName, parameterValue);
return u;
}
URL URL::withParameters (const StringPairArray& parametersToAdd) const
{
URL u (*this);
auto u = *this;
for (int i = 0; i < parametersToAdd.size(); ++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 u (*this);
auto u = *this;
u.postData = newPostData;
return u;
}
@@ -834,7 +834,7 @@ URL::Upload::Upload (const String& param, const String& name,
URL URL::withUpload (Upload* const f) const
{
URL u (*this);
auto u = *this;
for (int i = u.filesToUpload.size(); --i >= 0;)
if (u.filesToUpload.getObjectPointerUnchecked(i)->parameterName == f->parameterName)


+ 1
- 1
modules/juce_core/network/juce_URL.h View File

@@ -487,7 +487,7 @@ public:
@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


+ 7
- 7
modules/juce_core/xml/juce_XmlDocument.cpp View File

@@ -28,13 +28,13 @@ XmlDocument::XmlDocument (const File& file) : inputSource (new FileInputSource
XmlDocument::~XmlDocument() {}
XmlElement* XmlDocument::parse (const File& file)
std::unique_ptr<XmlElement> XmlDocument::parse (const File& file)
{
XmlDocument doc (file);
return doc.getDocumentElement();
}
XmlElement* XmlDocument::parse (const String& xmlData)
std::unique_ptr<XmlElement> XmlDocument::parse (const String& xmlData)
{
XmlDocument doc (xmlData);
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)
{
@@ -176,8 +176,8 @@ juce_wchar XmlDocument::readNextChar() noexcept
return c;
}
XmlElement* XmlDocument::parseDocumentElement (String::CharPointerType textToParse,
const bool onlyReadOuterDocumentElement)
std::unique_ptr<XmlElement> XmlDocument::parseDocumentElement (String::CharPointerType textToParse,
bool onlyReadOuterDocumentElement)
{
input = textToParse;
errorOccurred = false;
@@ -202,10 +202,10 @@ XmlElement* XmlDocument::parseDocumentElement (String::CharPointerType textToPar
std::unique_ptr<XmlElement> result (readNextElement (! onlyReadOuterDocumentElement));
if (! errorOccurred)
return result.release();
return result;
}
return nullptr;
return {};
}
bool XmlDocument::parseHeader()


+ 4
- 4
modules/juce_core/xml/juce_XmlDocument.h View File

@@ -100,7 +100,7 @@ public:
there was an error.
@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.
@@ -136,14 +136,14 @@ public:
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.
*/
static XmlElement* parse (const File& file);
static std::unique_ptr<XmlElement> parse (const File& file);
/** A handy static method that parses some XML data.
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>!
@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;
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);
bool parseHeader();
bool parseDTD();


+ 144
- 80
modules/juce_core/xml/juce_XmlElement.cpp View File

@@ -167,50 +167,46 @@ XmlElement::~XmlElement() noexcept
//==============================================================================
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();
@@ -221,7 +217,7 @@ namespace XmlOutputFunctions
if (character == 0)
break;
if (isLegalXmlChar (character))
if (LegalCharLookupTable::isLegal (character))
{
outputStream << (char) character;
}
@@ -257,13 +253,12 @@ namespace XmlOutputFunctions
}
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)
writeSpaces (outputStream, (size_t) indentationLevel);
XmlOutputFunctions::writeSpaces (outputStream, (size_t) indentationLevel);
if (! isTextElement())
{
@@ -278,8 +273,8 @@ void XmlElement::writeElementAsText (OutputStream& outputStream,
{
if (lineLen > lineWrapLength && indentationLevel >= 0)
{
outputStream << newLine;
writeSpaces (outputStream, attIndent);
outputStream << newLineChars;
XmlOutputFunctions::writeSpaces (outputStream, attIndent);
lineLen = 0;
}
@@ -287,7 +282,7 @@ void XmlElement::writeElementAsText (OutputStream& outputStream,
outputStream.writeByte (' ');
outputStream << att->name;
outputStream.write ("=\"", 2);
escapeIllegalXmlChars (outputStream, att->value, true);
XmlOutputFunctions::escapeIllegalXmlChars (outputStream, att->value, true);
outputStream.writeByte ('"');
lineLen += (int) (outputStream.getPosition() - startPos);
}
@@ -302,24 +297,25 @@ void XmlElement::writeElementAsText (OutputStream& outputStream,
{
if (child->isTextElement())
{
escapeIllegalXmlChars (outputStream, child->getText(), false);
XmlOutputFunctions::escapeIllegalXmlChars (outputStream, child->getText(), false);
lastWasTextNode = true;
}
else
{
if (indentationLevel >= 0 && ! lastWasTextNode)
outputStream << newLine;
outputStream << newLineChars;
child->writeElementAsText (outputStream,
lastWasTextNode ? 0 : (indentationLevel + (indentationLevel >= 0 ? 2 : 0)), lineWrapLength);
lastWasTextNode ? 0 : (indentationLevel + (indentationLevel >= 0 ? 2 : 0)), lineWrapLength,
newLineChars);
lastWasTextNode = false;
}
}
if (indentationLevel >= 0 && ! lastWasTextNode)
{
outputStream << newLine;
writeSpaces (outputStream, (size_t) indentationLevel);
outputStream << newLineChars;
XmlOutputFunctions::writeSpaces (outputStream, (size_t) indentationLevel);
}
outputStream.write ("</", 2);
@@ -333,58 +329,84 @@ void XmlElement::writeElementAsText (OutputStream& outputStream,
}
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();
}
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 (' ');
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 (' ');
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());
@@ -392,7 +414,7 @@ bool XmlElement::writeToFile (const File& file, StringRef dtdToUse,
if (! out.openedOk())
return false;
writeToStream (out, dtdToUse, false, true, encodingType, lineWrapLength);
writeTo (out, options);
out.flush(); // (called explicitly to force an fsync on posix)
if (out.getStatus().failed())
@@ -402,6 +424,48 @@ bool XmlElement::writeToFile (const File& file, StringRef dtdToUse,
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
{
@@ -608,7 +672,7 @@ int XmlElement::getNumChildElements() 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


+ 54
- 70
modules/juce_core/xml/juce_XmlElement.h View File

@@ -126,8 +126,8 @@ namespace juce
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
@see XmlDocument
@@ -184,74 +184,37 @@ public:
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.
@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.
@@ -728,6 +691,28 @@ public:
/** Checks if a given string is a valid XML name */
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:
struct XmlAttributeNode
@@ -750,14 +735,13 @@ private:
friend class LinkedListPointer<XmlElement>::Appender;
friend class NamedValueSet;
LinkedListPointer<XmlElement> nextListItem;
LinkedListPointer<XmlElement> firstChildElement;
LinkedListPointer<XmlElement> nextListItem, firstChildElement;
LinkedListPointer<XmlAttributeNode> attributes;
String tagName;
XmlElement (int) noexcept;
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 reorderChildElements (XmlElement**, int) noexcept;
XmlAttributeNode* getAttribute (StringRef) const noexcept;


+ 24
- 22
modules/juce_data_structures/app_properties/juce_PropertiesFile.cpp View File

@@ -187,32 +187,34 @@ bool PropertiesFile::save()
bool PropertiesFile::loadAsXml()
{
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;
@@ -229,8 +231,8 @@ bool PropertiesFile::saveAsXml()
e->setAttribute (PropertyFileConstants::nameAttribute, props.getAllKeys() [i]);
// 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
e->setAttribute (PropertyFileConstants::valueAttribute, props.getAllValues() [i]);
}
@@ -240,7 +242,7 @@ bool PropertiesFile::saveAsXml()
if (pl != nullptr && ! pl->isLocked())
return false; // locking failure..
if (doc.writeToFile (file, {}))
if (doc.writeTo (file, {}))
{
needsWriting = false;
return true;


+ 7
- 9
modules/juce_data_structures/values/juce_ValueTree.cpp View File

@@ -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)
@@ -1015,12 +1015,10 @@ ValueTree ValueTree::fromXml (const XmlElement& xml)
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 {};
}
@@ -1188,8 +1186,8 @@ public:
}
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));
auto v4 = v2.createCopy();


+ 2
- 2
modules/juce_data_structures/values/juce_ValueTree.h View File

@@ -430,7 +430,7 @@ public:
The caller must delete the object that is returned.
@see fromXml, toXmlString
*/
XmlElement* createXml() const;
std::unique_ptr<XmlElement> createXml() const;
/** 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
@@ -442,7 +442,7 @@ public:
This is quite handy for debugging purposes, as it provides a quick way to view a tree.
@see createXml()
*/
String toXmlString() const;
String toXmlString (const XmlElement::TextFormat& format = {}) const;
//==============================================================================
/** Stores this tree (and all its children) in a binary format.


+ 1
- 1
modules/juce_events/interprocess/juce_NetworkServiceDiscovery.cpp View File

@@ -65,7 +65,7 @@ void NetworkServiceDiscovery::Advertiser::sendBroadcast()
auto localAddress = IPAddress::getLocalAddress();
message.setAttribute ("address", localAddress.toString());
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());
}


+ 2
- 2
modules/juce_gui_basics/properties/juce_PropertyPanel.cpp View File

@@ -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());


+ 1
- 4
modules/juce_gui_basics/properties/juce_PropertyPanel.h View File

@@ -123,13 +123,10 @@ public:
//==============================================================================
/** 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().
@see restoreOpennessState
*/
XmlElement* getOpennessState() const;
std::unique_ptr<XmlElement> getOpennessState() const;
/** Restores a previously saved arrangement of open/closed sections.


+ 1
- 1
modules/juce_gui_basics/widgets/juce_TableHeaderComponent.cpp View File

@@ -431,7 +431,7 @@ String TableHeaderComponent::toString() const
e->setAttribute ("width", ci->width);
}
return doc.createDocument ({}, true, false);
return doc.toString (XmlElement::TextFormat().singleLine().withoutHeader());
}
void TableHeaderComponent::restoreFromString (const String& storedVersion)


+ 4
- 4
modules/juce_gui_basics/widgets/juce_TreeView.cpp View File

@@ -610,7 +610,7 @@ static void addAllSelectedItemIds (TreeViewItem* item, XmlElement& 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;
@@ -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)
@@ -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


+ 2
- 2
modules/juce_gui_basics/widgets/juce_TreeView.h View File

@@ -514,7 +514,7 @@ public:
@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.
@@ -818,7 +818,7 @@ public:
so this can also be restored
@see restoreOpennessState
*/
XmlElement* getOpennessState (bool alsoIncludeScrollPosition) const;
std::unique_ptr<XmlElement> getOpennessState (bool alsoIncludeScrollPosition) const;
/** Restores a previously saved arrangement of open/closed nodes.


+ 1
- 1
modules/juce_product_unlocking/marketplace/juce_OnlineUnlockStatus.cpp View File

@@ -73,7 +73,7 @@ struct KeyFileUtils
static String encryptXML (const XmlElement& xml, RSAKey privateKey)
{
MemoryOutputStream text;
text << xml.createDocument (StringRef(), true);
text << xml.toString (XmlElement::TextFormat().singleLine());
BigInteger val;
val.loadFromMemoryBlock (text.getMemoryBlock());


Loading…
Cancel
Save