| @@ -293,9 +293,7 @@ public: | |||||
| { | { | ||||
| // Restore our plug-in's state from the xml representation stored in the above | // Restore our plug-in's state from the xml representation stored in the above | ||||
| // method. | // method. | ||||
| std::unique_ptr<XmlElement> xmlState (getXmlFromBinary (data, sizeInBytes)); | |||||
| if (xmlState.get() != nullptr) | |||||
| if (auto xmlState = getXmlFromBinary (data, sizeInBytes)) | |||||
| state.replaceState (ValueTree::fromXml (*xmlState)); | state.replaceState (ValueTree::fromXml (*xmlState)); | ||||
| } | } | ||||
| @@ -236,9 +236,7 @@ public: | |||||
| void setStateInformation (const void* data, int sizeInBytes) override | void setStateInformation (const void* data, int sizeInBytes) override | ||||
| { | { | ||||
| auto xmlState = std::unique_ptr<XmlElement> (getXmlFromBinary (data, sizeInBytes)); | |||||
| if (xmlState.get() != nullptr) | |||||
| if (auto xmlState = getXmlFromBinary (data, sizeInBytes)) | |||||
| if (xmlState->hasTagName (parameters.state.getType())) | if (xmlState->hasTagName (parameters.state.getType())) | ||||
| parameters.state = ValueTree::fromXml (*xmlState); | parameters.state = ValueTree::fromXml (*xmlState); | ||||
| } | } | ||||
| @@ -212,11 +212,10 @@ private: | |||||
| // a binary format may be more suitable if it is faster - remember that this | // a binary format may be more suitable if it is faster - remember that this | ||||
| // method is called on app shutdown so it needs to complete quickly! | // method is called on app shutdown so it needs to complete quickly! | ||||
| XmlDocument previouslySavedEvents (savedEventsFile); | |||||
| std::unique_ptr<XmlElement> xml (previouslySavedEvents.getDocumentElement()); | |||||
| auto xml = parseXMLIfTagMatches (savedEventsFile, "events"); | |||||
| if (xml.get() == nullptr || xml->getTagName() != "events") | |||||
| xml.reset (new XmlElement ("events")); | |||||
| if (xml == nullptr) | |||||
| xml = std::make_unique<XmlElement> ("events"); | |||||
| for (auto& event : eventsToSave) | for (auto& event : eventsToSave) | ||||
| { | { | ||||
| @@ -248,45 +247,42 @@ private: | |||||
| void restoreUnloggedEvents (std::deque<AnalyticsEvent>& restoredEventQueue) override | void restoreUnloggedEvents (std::deque<AnalyticsEvent>& restoredEventQueue) override | ||||
| { | { | ||||
| XmlDocument savedEvents (savedEventsFile); | |||||
| std::unique_ptr<XmlElement> xml (savedEvents.getDocumentElement()); | |||||
| if (xml.get() == nullptr || xml->getTagName() != "events") | |||||
| return; | |||||
| if (auto xml = parseXMLIfTagMatches (savedEventsFile, "events")) | |||||
| { | |||||
| auto numEvents = xml->getNumChildElements(); | |||||
| auto numEvents = xml->getNumChildElements(); | |||||
| for (auto iEvent = 0; iEvent < numEvents; ++iEvent) | |||||
| { | |||||
| auto* xmlEvent = xml->getChildElement (iEvent); | |||||
| StringPairArray parameters; | |||||
| auto* xmlParameters = xmlEvent->getChildByName ("parameters"); | |||||
| auto numParameters = xmlParameters->getNumAttributes(); | |||||
| for (auto iParam = 0; iParam < numParameters; ++iParam) | |||||
| parameters.set (xmlParameters->getAttributeName (iParam), | |||||
| xmlParameters->getAttributeValue (iParam)); | |||||
| StringPairArray userProperties; | |||||
| auto* xmlUserProperties = xmlEvent->getChildByName ("user_properties"); | |||||
| auto numUserProperties = xmlUserProperties->getNumAttributes(); | |||||
| for (auto iProp = 0; iProp < numUserProperties; ++iProp) | |||||
| userProperties.set (xmlUserProperties->getAttributeName (iProp), | |||||
| xmlUserProperties->getAttributeValue (iProp)); | |||||
| restoredEventQueue.push_back ({ | |||||
| xmlEvent->getStringAttribute ("name"), | |||||
| xmlEvent->getIntAttribute ("type"), | |||||
| static_cast<uint32> (xmlEvent->getIntAttribute ("timestamp")), | |||||
| parameters, | |||||
| xmlEvent->getStringAttribute ("user_id"), | |||||
| userProperties | |||||
| }); | |||||
| } | |||||
| for (auto iEvent = 0; iEvent < numEvents; ++iEvent) | |||||
| { | |||||
| auto* xmlEvent = xml->getChildElement (iEvent); | |||||
| StringPairArray parameters; | |||||
| auto* xmlParameters = xmlEvent->getChildByName ("parameters"); | |||||
| auto numParameters = xmlParameters->getNumAttributes(); | |||||
| for (auto iParam = 0; iParam < numParameters; ++iParam) | |||||
| parameters.set (xmlParameters->getAttributeName (iParam), | |||||
| xmlParameters->getAttributeValue (iParam)); | |||||
| StringPairArray userProperties; | |||||
| auto* xmlUserProperties = xmlEvent->getChildByName ("user_properties"); | |||||
| auto numUserProperties = xmlUserProperties->getNumAttributes(); | |||||
| for (auto iProp = 0; iProp < numUserProperties; ++iProp) | |||||
| userProperties.set (xmlUserProperties->getAttributeName (iProp), | |||||
| xmlUserProperties->getAttributeValue (iProp)); | |||||
| restoredEventQueue.push_back ({ | |||||
| xmlEvent->getStringAttribute ("name"), | |||||
| xmlEvent->getIntAttribute ("type"), | |||||
| static_cast<uint32> (xmlEvent->getIntAttribute ("timestamp")), | |||||
| parameters, | |||||
| xmlEvent->getStringAttribute ("user_id"), | |||||
| userProperties | |||||
| }); | |||||
| savedEventsFile.deleteFile(); | |||||
| } | } | ||||
| savedEventsFile.deleteFile(); | |||||
| } | } | ||||
| const int initialPeriodMs = 1000; | const int initialPeriodMs = 1000; | ||||
| @@ -221,26 +221,26 @@ void FilterGraph::newDocument() | |||||
| Result FilterGraph::loadDocument (const File& file) | Result FilterGraph::loadDocument (const File& file) | ||||
| { | { | ||||
| XmlDocument doc (file); | |||||
| std::unique_ptr<XmlElement> xml (doc.getDocumentElement()); | |||||
| if (xml == nullptr || ! xml->hasTagName ("FILTERGRAPH")) | |||||
| return Result::fail ("Not a valid filter graph file"); | |||||
| if (auto xml = parseXMLIfTagMatches (file, "FILTERGRAPH")) | |||||
| { | |||||
| graph.removeChangeListener (this); | |||||
| restoreFromXml (*xml); | |||||
| graph.removeChangeListener (this); | |||||
| restoreFromXml (*xml); | |||||
| MessageManager::callAsync ([this] | |||||
| { | |||||
| setChangedFlag (false); | |||||
| graph.addChangeListener (this); | |||||
| }); | |||||
| MessageManager::callAsync ([this] () { | |||||
| setChangedFlag (false); | |||||
| graph.addChangeListener (this); | |||||
| } ); | |||||
| return Result::ok(); | |||||
| } | |||||
| return Result::ok(); | |||||
| return Result::fail ("Not a valid filter graph file"); | |||||
| } | } | ||||
| Result FilterGraph::saveDocument (const File& file) | Result FilterGraph::saveDocument (const File& file) | ||||
| { | { | ||||
| std::unique_ptr<XmlElement> xml (createXml()); | |||||
| auto xml = createXml(); | |||||
| if (! xml->writeTo (file, {})) | if (! xml->writeTo (file, {})) | ||||
| return Result::fail ("Couldn't write to the file"); | return Result::fail ("Couldn't write to the file"); | ||||
| @@ -178,11 +178,10 @@ void ProjucerAnalyticsDestination::stopLoggingEvents() | |||||
| //============================================================================== | //============================================================================== | ||||
| void ProjucerAnalyticsDestination::saveUnloggedEvents (const std::deque<AnalyticsEvent>& eventsToSave) | void ProjucerAnalyticsDestination::saveUnloggedEvents (const std::deque<AnalyticsEvent>& eventsToSave) | ||||
| { | { | ||||
| XmlDocument previouslySavedEvents (savedEventsFile); | |||||
| std::unique_ptr<XmlElement> xml (previouslySavedEvents.getDocumentElement()); | |||||
| auto xml = parseXMLIfTagMatches (savedEventsFile, "events"); | |||||
| if (xml.get() == nullptr || xml->getTagName() != "events") | |||||
| xml.reset (new XmlElement ("events")); | |||||
| if (xml == nullptr) | |||||
| xml = std::make_unique<XmlElement> ("events"); | |||||
| for (auto& event : eventsToSave) | for (auto& event : eventsToSave) | ||||
| { | { | ||||
| @@ -214,10 +213,9 @@ void ProjucerAnalyticsDestination::saveUnloggedEvents (const std::deque<Analytic | |||||
| void ProjucerAnalyticsDestination::restoreUnloggedEvents (std::deque<AnalyticsEvent>& restoredEventQueue) | void ProjucerAnalyticsDestination::restoreUnloggedEvents (std::deque<AnalyticsEvent>& restoredEventQueue) | ||||
| { | { | ||||
| XmlDocument savedEvents (savedEventsFile); | |||||
| std::unique_ptr<XmlElement> xml (savedEvents.getDocumentElement()); | |||||
| auto xml = parseXMLIfTagMatches (savedEventsFile, "events"); | |||||
| if (xml.get() == nullptr || xml->getTagName() != "events") | |||||
| if (xml == nullptr) | |||||
| return; | return; | ||||
| auto numEvents = xml->getNumChildElements(); | auto numEvents = xml->getNumChildElements(); | ||||
| @@ -271,10 +271,7 @@ void ComponentLayout::copySelectedToClipboard() | |||||
| void ComponentLayout::paste() | void ComponentLayout::paste() | ||||
| { | { | ||||
| XmlDocument clip (SystemClipboard::getTextFromClipboard()); | |||||
| std::unique_ptr<XmlElement> doc (clip.getDocumentElement()); | |||||
| if (doc != nullptr && doc->hasTagName (clipboardXmlTag)) | |||||
| if (auto doc = parseXMLIfTagMatches (SystemClipboard::getTextFromClipboard(), clipboardXmlTag)) | |||||
| { | { | ||||
| selected.deselectAll(); | selected.deselectAll(); | ||||
| @@ -624,16 +624,14 @@ void JucerDocument::extractCustomPaintSnippetsFromCppFile (const String& cppCont | |||||
| std::unique_ptr<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); | ||||
| const int startLine = indexOfLineStartingWith (lines, "BEGIN_JUCER_METADATA", 0); | |||||
| auto startLine = indexOfLineStartingWith (lines, "BEGIN_JUCER_METADATA", 0); | |||||
| if (startLine > 0) | if (startLine > 0) | ||||
| { | { | ||||
| const int endLine = indexOfLineStartingWith (lines, "END_JUCER_METADATA", startLine); | |||||
| auto endLine = indexOfLineStartingWith (lines, "END_JUCER_METADATA", startLine); | |||||
| if (endLine > startLine) | if (endLine > startLine) | ||||
| return XmlDocument::parse (lines.joinIntoString ("\n", startLine + 1, | |||||
| endLine - startLine - 1)); | |||||
| return parseXML (lines.joinIntoString ("\n", startLine + 1, endLine - startLine - 1)); | |||||
| } | } | ||||
| return nullptr; | return nullptr; | ||||
| @@ -302,10 +302,7 @@ void PaintRoutine::copySelectedToClipboard() | |||||
| void PaintRoutine::paste() | void PaintRoutine::paste() | ||||
| { | { | ||||
| XmlDocument clip (SystemClipboard::getTextFromClipboard()); | |||||
| std::unique_ptr<XmlElement> doc (clip.getDocumentElement()); | |||||
| if (doc != nullptr && doc->hasTagName (clipboardXmlTag)) | |||||
| if (auto doc = parseXMLIfTagMatches (SystemClipboard::getTextFromClipboard(), clipboardXmlTag)) | |||||
| { | { | ||||
| selectedElements.deselectAll(); | selectedElements.deselectAll(); | ||||
| selectedPoints.deselectAll(); | selectedPoints.deselectAll(); | ||||
| @@ -1543,7 +1543,7 @@ private: | |||||
| std::unique_ptr<XmlElement> createManifestElement() const | std::unique_ptr<XmlElement> createManifestElement() const | ||||
| { | { | ||||
| auto manifest = XmlDocument::parse (androidManifestCustomXmlElements.get()); | |||||
| auto manifest = parseXML (androidManifestCustomXmlElements.get()); | |||||
| if (manifest == nullptr) | if (manifest == nullptr) | ||||
| manifest = std::make_unique<XmlElement> ("manifest"); | manifest = std::make_unique<XmlElement> ("manifest"); | ||||
| @@ -1013,9 +1013,8 @@ private: | |||||
| if (targetAttributeKeys.contains ("INFOPLIST_FILE")) | if (targetAttributeKeys.contains ("INFOPLIST_FILE")) | ||||
| { | { | ||||
| auto plistFile = exporter.getTargetFolder().getChildFile (targetAttributes["INFOPLIST_FILE"]); | auto plistFile = exporter.getTargetFolder().getChildFile (targetAttributes["INFOPLIST_FILE"]); | ||||
| XmlDocument infoPlistData (plistFile); | |||||
| if (auto plist = std::unique_ptr<XmlElement> (infoPlistData.getDocumentElement())) | |||||
| if (auto plist = parseXML (plistFile)) | |||||
| { | { | ||||
| if (auto* dict = plist->getChildByName ("dict")) | if (auto* dict = plist->getChildByName ("dict")) | ||||
| { | { | ||||
| @@ -2292,9 +2292,7 @@ public: | |||||
| void setStateInformation (const void* data, int sizeInBytes) override | void setStateInformation (const void* data, int sizeInBytes) override | ||||
| { | { | ||||
| std::unique_ptr<XmlElement> head (AudioProcessor::getXmlFromBinary (data, sizeInBytes)); | |||||
| if (head != nullptr) | |||||
| if (auto head = AudioProcessor::getXmlFromBinary (data, sizeInBytes)) | |||||
| { | { | ||||
| auto componentStream (createMemoryStreamForState (*head, "IComponent")); | auto componentStream (createMemoryStreamForState (*head, "IComponent")); | ||||
| @@ -1121,8 +1121,8 @@ std::unique_ptr<XmlElement> AudioProcessor::getXmlFromBinary (const void* data, | |||||
| auto stringLength = (int) ByteOrder::littleEndianInt (addBytesToPointer (data, 4)); | auto stringLength = (int) ByteOrder::littleEndianInt (addBytesToPointer (data, 4)); | ||||
| if (stringLength > 0) | if (stringLength > 0) | ||||
| return XmlDocument::parse (String::fromUTF8 (static_cast<const char*> (data) + 8, | |||||
| jmin ((sizeInBytes - 8), stringLength))); | |||||
| return parseXML (String::fromUTF8 (static_cast<const char*> (data) + 8, | |||||
| jmin ((sizeInBytes - 8), stringLength))); | |||||
| } | } | ||||
| return {}; | return {}; | ||||
| @@ -112,7 +112,7 @@ bool PropertySet::getBoolValue (StringRef keyName, bool defaultValue) const noex | |||||
| std::unique_ptr<XmlElement> PropertySet::getXmlValue (StringRef keyName) const | std::unique_ptr<XmlElement> PropertySet::getXmlValue (StringRef keyName) const | ||||
| { | { | ||||
| return XmlDocument::parse (getValue (keyName)); | |||||
| return parseXML (getValue (keyName)); | |||||
| } | } | ||||
| void PropertySet::setValue (const String& keyName, const var& v) | void PropertySet::setValue (const String& keyName, const var& v) | ||||
| @@ -790,7 +790,7 @@ String URL::readEntireTextStream (bool usePostCommand) const | |||||
| std::unique_ptr<XmlElement> URL::readEntireXmlStream (bool usePostCommand) const | std::unique_ptr<XmlElement> URL::readEntireXmlStream (bool usePostCommand) const | ||||
| { | { | ||||
| return XmlDocument::parse (readEntireTextStream (usePostCommand)); | |||||
| return parseXML (readEntireTextStream (usePostCommand)); | |||||
| } | } | ||||
| //============================================================================== | //============================================================================== | ||||
| @@ -30,24 +30,32 @@ XmlDocument::~XmlDocument() {} | |||||
| std::unique_ptr<XmlElement> XmlDocument::parse (const File& file) | std::unique_ptr<XmlElement> XmlDocument::parse (const File& file) | ||||
| { | { | ||||
| XmlDocument doc (file); | |||||
| return doc.getDocumentElement(); | |||||
| return XmlDocument (file).getDocumentElement(); | |||||
| } | } | ||||
| std::unique_ptr<XmlElement> XmlDocument::parse (const String& xmlData) | |||||
| std::unique_ptr<XmlElement> XmlDocument::parse (const String& textToParse) | |||||
| { | { | ||||
| XmlDocument doc (xmlData); | |||||
| return doc.getDocumentElement(); | |||||
| return XmlDocument (textToParse).getDocumentElement(); | |||||
| } | } | ||||
| std::unique_ptr<XmlElement> parseXML (const String& textToParse) | std::unique_ptr<XmlElement> parseXML (const String& textToParse) | ||||
| { | { | ||||
| return std::unique_ptr<XmlElement> (XmlDocument::parse (textToParse)); | |||||
| return XmlDocument (textToParse).getDocumentElement(); | |||||
| } | } | ||||
| std::unique_ptr<XmlElement> parseXML (const File& fileToParse) | |||||
| std::unique_ptr<XmlElement> parseXML (const File& file) | |||||
| { | { | ||||
| return std::unique_ptr<XmlElement> (XmlDocument::parse (fileToParse)); | |||||
| return XmlDocument (file).getDocumentElement(); | |||||
| } | |||||
| std::unique_ptr<XmlElement> parseXMLIfTagMatches (const String& textToParse, StringRef requiredTag) | |||||
| { | |||||
| return XmlDocument (textToParse).getDocumentElementIfTagMatches (requiredTag); | |||||
| } | |||||
| std::unique_ptr<XmlElement> parseXMLIfTagMatches (const File& file, StringRef requiredTag) | |||||
| { | |||||
| return XmlDocument (file).getDocumentElementIfTagMatches (requiredTag); | |||||
| } | } | ||||
| void XmlDocument::setInputSource (InputSource* newSource) noexcept | void XmlDocument::setInputSource (InputSource* newSource) noexcept | ||||
| @@ -139,6 +147,15 @@ std::unique_ptr<XmlElement> XmlDocument::getDocumentElement (const bool onlyRead | |||||
| return parseDocumentElement (originalText.getCharPointer(), onlyReadOuterDocumentElement); | return parseDocumentElement (originalText.getCharPointer(), onlyReadOuterDocumentElement); | ||||
| } | } | ||||
| std::unique_ptr<XmlElement> XmlDocument::getDocumentElementIfTagMatches (StringRef requiredTag) | |||||
| { | |||||
| if (auto xml = getDocumentElement (true)) | |||||
| if (xml->hasTagName (requiredTag)) | |||||
| return getDocumentElement (false); | |||||
| return {}; | |||||
| } | |||||
| const String& XmlDocument::getLastParseError() const noexcept | const String& XmlDocument::getLastParseError() const noexcept | ||||
| { | { | ||||
| return lastError; | return lastError; | ||||
| @@ -98,12 +98,17 @@ public: | |||||
| tag, without having to parse the entire file | tag, without having to parse the entire file | ||||
| @returns a new XmlElement which the caller will need to delete, or null if | @returns a new XmlElement which the caller will need to delete, or null if | ||||
| there was an error. | there was an error. | ||||
| @see getLastParseError | |||||
| @see getLastParseError, getDocumentElementIfTagMatches | |||||
| */ | */ | ||||
| std::unique_ptr<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. | |||||
| /** Does an inexpensive check to see whether the outer element has the given tag name, and | |||||
| then does a full parse if it matches. | |||||
| If the tag is different, or the XML parse fails, this will return nullptr. | |||||
| */ | |||||
| std::unique_ptr<XmlElement> getDocumentElementIfTagMatches (StringRef requiredTag); | |||||
| /** Returns the parsing error that occurred the last time getDocumentElement was called. | |||||
| @returns the error, or an empty string if there was no error. | @returns the error, or an empty string if there was no error. | ||||
| */ | */ | ||||
| const String& getLastParseError() const noexcept; | const String& getLastParseError() const noexcept; | ||||
| @@ -178,18 +183,31 @@ private: | |||||
| //============================================================================== | //============================================================================== | ||||
| /** Attempts to parse some XML text, returning a new XmlElement if it was valid. | /** Attempts to parse some XML text, returning a new XmlElement if it was valid. | ||||
| If the parse fails, this will return a nullptr - if you need more information about | If the parse fails, this will return a nullptr - if you need more information about | ||||
| errors or more parsing options, see the XmlDocument instead. | |||||
| @see XmlDocument | |||||
| errors or more parsing options, see the XmlDocument class instead. | |||||
| @see XmlDocument, parseXMLIfTagMatches | |||||
| */ | */ | ||||
| std::unique_ptr<XmlElement> parseXML (const String& textToParse); | std::unique_ptr<XmlElement> parseXML (const String& textToParse); | ||||
| /** Attempts to parse some XML text, returning a new XmlElement if it was valid. | /** Attempts to parse some XML text, returning a new XmlElement if it was valid. | ||||
| If the parse fails, this will return a nullptr - if you need more information about | If the parse fails, this will return a nullptr - if you need more information about | ||||
| errors or more parsing options, see the XmlDocument instead. | |||||
| @see XmlDocument | |||||
| errors or more parsing options, see the XmlDocument class instead. | |||||
| @see XmlDocument, parseXMLIfTagMatches | |||||
| */ | */ | ||||
| std::unique_ptr<XmlElement> parseXML (const File& fileToParse); | std::unique_ptr<XmlElement> parseXML (const File& fileToParse); | ||||
| /** Does an inexpensive check to see whether the top-level element has the given tag | |||||
| name, and if that's true, does a full parse and returns the result. | |||||
| If the outer tag doesn't match, or the XML has errors, this will return nullptr; | |||||
| @see parseXML | |||||
| */ | |||||
| std::unique_ptr<XmlElement> parseXMLIfTagMatches (const String& textToParse, StringRef requiredTag); | |||||
| /** Does an inexpensive check to see whether the top-level element has the given tag | |||||
| name, and if that's true, does a full parse and returns the result. | |||||
| If the outer tag doesn't match, or the XML has errors, this will return nullptr; | |||||
| @see parseXML | |||||
| */ | |||||
| std::unique_ptr<XmlElement> parseXMLIfTagMatches (const File& fileToParse, StringRef requiredTag); | |||||
| } // namespace juce | } // namespace juce | ||||
| @@ -130,7 +130,7 @@ namespace juce | |||||
| auto xmlString = animalsList.toString(); | auto xmlString = animalsList.toString(); | ||||
| @endcode | @endcode | ||||
| @see XmlDocument | |||||
| @see parseXML, parseXMLIfTagMatches, XmlDocument | |||||
| @tags{Core} | @tags{Core} | ||||
| */ | */ | ||||
| @@ -186,35 +186,20 @@ bool PropertiesFile::save() | |||||
| bool PropertiesFile::loadAsXml() | bool PropertiesFile::loadAsXml() | ||||
| { | { | ||||
| XmlDocument parser (file); | |||||
| if (auto doc = parser.getDocumentElement (true)) | |||||
| if (auto doc = parseXMLIfTagMatches (file, PropertyFileConstants::fileTag)) | |||||
| { | { | ||||
| if (doc->hasTagName (PropertyFileConstants::fileTag)) | |||||
| forEachXmlChildElementWithTagName (*doc, e, PropertyFileConstants::valueTag) | |||||
| { | { | ||||
| doc = parser.getDocumentElement(); | |||||
| 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; | |||||
| } | |||||
| // 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. | |||||
| 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 false; | return false; | ||||
| @@ -231,7 +216,7 @@ 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])) | |||||
| if (auto childElement = parseXML (props.getAllValues() [i])) | |||||
| e->addChildElement (childElement.release()); | e->addChildElement (childElement.release()); | ||||
| else | else | ||||
| e->setAttribute (PropertyFileConstants::valueAttribute, props.getAllValues() [i]); | e->setAttribute (PropertyFileConstants::valueAttribute, props.getAllValues() [i]); | ||||
| @@ -180,14 +180,8 @@ std::unique_ptr<Drawable> Drawable::createFromImageData (const void* data, const | |||||
| } | } | ||||
| else | else | ||||
| { | { | ||||
| auto asString = String::createStringFromData (data, (int) numBytes); | |||||
| XmlDocument doc (asString); | |||||
| std::unique_ptr<XmlElement> outer (doc.getDocumentElement (true)); | |||||
| if (outer != nullptr && outer->hasTagName ("svg")) | |||||
| if (auto svg = doc.getDocumentElement()) | |||||
| result = Drawable::createFromSVG (*svg); | |||||
| if (auto svg = parseXMLIfTagMatches (String::createStringFromData (data, (int) numBytes), "svg")) | |||||
| result = Drawable::createFromSVG (*svg); | |||||
| } | } | ||||
| return result; | return result; | ||||
| @@ -1702,24 +1702,13 @@ std::unique_ptr<Drawable> Drawable::createFromSVG (const XmlElement& svgDocument | |||||
| return {}; | return {}; | ||||
| SVGState state (&svgDocument); | SVGState state (&svgDocument); | ||||
| return std::unique_ptr<Drawable> (state.parseSVGElement (SVGState::XmlPath (&svgDocument, nullptr))); | |||||
| return std::unique_ptr<Drawable> (state.parseSVGElement (SVGState::XmlPath (&svgDocument, {}))); | |||||
| } | } | ||||
| std::unique_ptr<Drawable> Drawable::createFromSVGFile (const File& svgFile) | std::unique_ptr<Drawable> Drawable::createFromSVGFile (const File& svgFile) | ||||
| { | { | ||||
| XmlDocument doc (svgFile); | |||||
| if (auto outer = doc.getDocumentElement (true)) | |||||
| { | |||||
| if (outer->hasTagName ("svg")) | |||||
| { | |||||
| if (auto svgDocument = doc.getDocumentElement()) | |||||
| { | |||||
| SVGState state (svgDocument.get(), svgFile); | |||||
| return std::unique_ptr<Drawable> (state.parseSVGElement (SVGState::XmlPath (svgDocument.get(), nullptr))); | |||||
| } | |||||
| } | |||||
| } | |||||
| if (auto xml = parseXMLIfTagMatches (svgFile, "svg")) | |||||
| return createFromSVG (*xml); | |||||
| return {}; | return {}; | ||||
| } | } | ||||