| @@ -155,8 +155,7 @@ void Project::setMissingDefaultValues() | |||||
| //============================================================================== | //============================================================================== | ||||
| const String Project::loadDocument (const File& file) | const String Project::loadDocument (const File& file) | ||||
| { | { | ||||
| XmlDocument doc (file); | |||||
| ScopedPointer <XmlElement> xml (doc.getDocumentElement()); | |||||
| ScopedPointer <XmlElement> xml (XmlDocument::parse (file)); | |||||
| if (xml == 0 || ! xml->hasTagName (Tags::projectRoot.toString())) | if (xml == 0 || ! xml->hasTagName (Tags::projectRoot.toString())) | ||||
| return "Not a valid Jucer project!"; | return "Not a valid Jucer project!"; | ||||
| @@ -34,7 +34,7 @@ BEGIN_JUCE_NAMESPACE | |||||
| //============================================================================== | //============================================================================== | ||||
| namespace MidiFileHelpers | namespace MidiFileHelpers | ||||
| { | { | ||||
| static void writeVariableLengthInt (OutputStream& out, unsigned int v) | |||||
| void writeVariableLengthInt (OutputStream& out, unsigned int v) | |||||
| { | { | ||||
| unsigned int buffer = v & 0x7F; | unsigned int buffer = v & 0x7F; | ||||
| @@ -55,7 +55,7 @@ namespace MidiFileHelpers | |||||
| } | } | ||||
| } | } | ||||
| static bool parseMidiHeader (const uint8* &data, short& timeFormat, short& fileType, short& numberOfTracks) throw() | |||||
| bool parseMidiHeader (const uint8* &data, short& timeFormat, short& fileType, short& numberOfTracks) throw() | |||||
| { | { | ||||
| unsigned int ch = (int) ByteOrder::bigEndianInt (data); | unsigned int ch = (int) ByteOrder::bigEndianInt (data); | ||||
| data += 4; | data += 4; | ||||
| @@ -97,9 +97,9 @@ namespace MidiFileHelpers | |||||
| return true; | return true; | ||||
| } | } | ||||
| static double convertTicksToSeconds (const double time, | |||||
| const MidiMessageSequence& tempoEvents, | |||||
| const int timeFormat) | |||||
| double convertTicksToSeconds (const double time, | |||||
| const MidiMessageSequence& tempoEvents, | |||||
| const int timeFormat) | |||||
| { | { | ||||
| if (timeFormat > 0) | if (timeFormat > 0) | ||||
| { | { | ||||
| @@ -184,7 +184,6 @@ namespace MidiFileHelpers | |||||
| } | } | ||||
| } | } | ||||
| }; | }; | ||||
| } | } | ||||
| //============================================================================== | //============================================================================== | ||||
| @@ -409,8 +408,7 @@ bool MidiFile::writeTo (OutputStream& out) | |||||
| return true; | return true; | ||||
| } | } | ||||
| void MidiFile::writeTrack (OutputStream& mainOut, | |||||
| const int trackNum) | |||||
| void MidiFile::writeTrack (OutputStream& mainOut, const int trackNum) | |||||
| { | { | ||||
| MemoryOutputStream out; | MemoryOutputStream out; | ||||
| @@ -285,12 +285,8 @@ XmlElement* AudioProcessor::getXmlFromBinary (const void* data, | |||||
| const int stringLength = (int) ByteOrder::littleEndianInt (addBytesToPointer (data, 4)); | const int stringLength = (int) ByteOrder::littleEndianInt (addBytesToPointer (data, 4)); | ||||
| if (stringLength > 0) | if (stringLength > 0) | ||||
| { | |||||
| XmlDocument doc (String::fromUTF8 (static_cast<const char*> (data) + 8, | |||||
| jmin ((sizeInBytes - 8), stringLength))); | |||||
| return doc.getDocumentElement(); | |||||
| } | |||||
| return XmlDocument::parse (String::fromUTF8 (static_cast<const char*> (data) + 8, | |||||
| jmin ((sizeInBytes - 8), stringLength))); | |||||
| } | } | ||||
| return 0; | return 0; | ||||
| @@ -127,9 +127,7 @@ bool PropertySet::getBoolValue (const String& keyName, | |||||
| XmlElement* PropertySet::getXmlValue (const String& keyName) const | XmlElement* PropertySet::getXmlValue (const String& keyName) const | ||||
| { | { | ||||
| XmlDocument doc (getValue (keyName)); | |||||
| return doc.getDocumentElement(); | |||||
| return XmlDocument::parse (getValue (keyName)); | |||||
| } | } | ||||
| void PropertySet::setValue (const String& keyName, const var& v) | void PropertySet::setValue (const String& keyName, const var& v) | ||||
| @@ -460,9 +460,7 @@ const String TableHeaderComponent::toString() const | |||||
| void TableHeaderComponent::restoreFromString (const String& storedVersion) | void TableHeaderComponent::restoreFromString (const String& storedVersion) | ||||
| { | { | ||||
| XmlDocument doc (storedVersion); | |||||
| ScopedPointer <XmlElement> storedXml (doc.getDocumentElement()); | |||||
| ScopedPointer <XmlElement> storedXml (XmlDocument::parse (storedVersion)); | |||||
| int index = 0; | int index = 0; | ||||
| if (storedXml != 0 && storedXml->hasTagName ("TABLELAYOUT")) | if (storedXml != 0 && storedXml->hasTagName ("TABLELAYOUT")) | ||||
| @@ -466,8 +466,7 @@ const String URL::readEntireTextStream (const bool usePostCommand) const | |||||
| XmlElement* URL::readEntireXmlStream (const bool usePostCommand) const | XmlElement* URL::readEntireXmlStream (const bool usePostCommand) const | ||||
| { | { | ||||
| XmlDocument doc (readEntireTextStream (usePostCommand)); | |||||
| return doc.getDocumentElement(); | |||||
| return XmlDocument::parse (readEntireTextStream (usePostCommand)); | |||||
| } | } | ||||
| //============================================================================== | //============================================================================== | ||||
| @@ -108,8 +108,7 @@ public: | |||||
| if (fontDirs.size() == 0) | if (fontDirs.size() == 0) | ||||
| { | { | ||||
| XmlDocument fontsConfig (File ("/etc/fonts/fonts.conf")); | |||||
| const ScopedPointer<XmlElement> fontsInfo (fontsConfig.getDocumentElement()); | |||||
| const ScopedPointer<XmlElement> fontsInfo (XmlDocument::parse (File ("/etc/fonts/fonts.conf"))); | |||||
| if (fontsInfo != 0) | if (fontsInfo != 0) | ||||
| { | { | ||||
| @@ -40,15 +40,27 @@ XmlDocument::XmlDocument (const String& documentText) | |||||
| } | } | ||||
| XmlDocument::XmlDocument (const File& file) | XmlDocument::XmlDocument (const File& file) | ||||
| : ignoreEmptyTextElements (true) | |||||
| : ignoreEmptyTextElements (true), | |||||
| inputSource (new FileInputSource (file)) | |||||
| { | { | ||||
| inputSource = new FileInputSource (file); | |||||
| } | } | ||||
| XmlDocument::~XmlDocument() | XmlDocument::~XmlDocument() | ||||
| { | { | ||||
| } | } | ||||
| XmlElement* XmlDocument::parse (const File& file) | |||||
| { | |||||
| XmlDocument doc (file); | |||||
| return doc.getDocumentElement(); | |||||
| } | |||||
| XmlElement* XmlDocument::parse (const String& xmlData) | |||||
| { | |||||
| XmlDocument doc (xmlData); | |||||
| return doc.getDocumentElement(); | |||||
| } | |||||
| void XmlDocument::setInputSource (InputSource* const newSource) throw() | void XmlDocument::setInputSource (InputSource* const newSource) throw() | ||||
| { | { | ||||
| inputSource = newSource; | inputSource = newSource; | ||||
| @@ -59,16 +71,36 @@ void XmlDocument::setEmptyTextElementsIgnored (const bool shouldBeIgnored) throw | |||||
| ignoreEmptyTextElements = shouldBeIgnored; | ignoreEmptyTextElements = shouldBeIgnored; | ||||
| } | } | ||||
| bool XmlDocument::isXmlIdentifierCharSlow (const juce_wchar c) throw() | |||||
| namespace XmlIdentifierChars | |||||
| { | { | ||||
| return CharacterFunctions::isLetterOrDigit (c) | |||||
| || c == '_' || c == '-' || c == ':' || c == '.'; | |||||
| } | |||||
| bool isIdentifierCharSlow (const juce_wchar c) throw() | |||||
| { | |||||
| return CharacterFunctions::isLetterOrDigit (c) | |||||
| || c == '_' || c == '-' || c == ':' || c == '.'; | |||||
| } | |||||
| inline bool XmlDocument::isXmlIdentifierChar (const juce_wchar c) const throw() | |||||
| { | |||||
| return (c > 0 && c <= 127) ? identifierLookupTable [(int) c] | |||||
| : isXmlIdentifierCharSlow (c); | |||||
| bool isIdentifierChar (const juce_wchar c) throw() | |||||
| { | |||||
| static const uint32 legalChars[] = { 0, 0x7ff6000, 0x87fffffe, 0x7fffffe, 0 }; | |||||
| return (c < numElementsInArray (legalChars) * 32) ? ((legalChars [c >> 5] & (1 << (c & 31))) != 0) | |||||
| : isIdentifierCharSlow (c); | |||||
| } | |||||
| /*static void generateIdentifierCharConstants() | |||||
| { | |||||
| uint32 n[8]; | |||||
| zerostruct (n); | |||||
| for (int i = 0; i < 256; ++i) | |||||
| if (isIdentifierCharSlow (i)) | |||||
| n[i >> 5] |= (1 << (i & 31)); | |||||
| String s; | |||||
| for (int i = 0; i < 8; ++i) | |||||
| s << "0x" << String::toHexString ((int) n[i]) << ", "; | |||||
| DBG (s); | |||||
| }*/ | |||||
| } | } | ||||
| XmlElement* XmlDocument::getDocumentElement (const bool onlyReadOuterDocumentElement) | XmlElement* XmlDocument::getDocumentElement (const bool onlyReadOuterDocumentElement) | ||||
| @@ -96,9 +128,6 @@ XmlElement* XmlDocument::getDocumentElement (const bool onlyReadOuterDocumentEle | |||||
| outOfData = false; | outOfData = false; | ||||
| needToLoadDTD = true; | needToLoadDTD = true; | ||||
| for (int i = 0; i < 128; ++i) | |||||
| identifierLookupTable[i] = isXmlIdentifierCharSlow ((juce_wchar) i); | |||||
| if (textToParse.isEmpty()) | if (textToParse.isEmpty()) | ||||
| { | { | ||||
| lastError = "not enough input"; | lastError = "not enough input"; | ||||
| @@ -150,14 +179,10 @@ const String XmlDocument::getFileContents (const String& filename) const | |||||
| juce_wchar XmlDocument::readNextChar() throw() | juce_wchar XmlDocument::readNextChar() throw() | ||||
| { | { | ||||
| if (*input != 0) | if (*input != 0) | ||||
| { | |||||
| return *input++; | return *input++; | ||||
| } | |||||
| else | |||||
| { | |||||
| outOfData = true; | |||||
| return 0; | |||||
| } | |||||
| outOfData = true; | |||||
| return 0; | |||||
| } | } | ||||
| int XmlDocument::findNextTokenLength() throw() | int XmlDocument::findNextTokenLength() throw() | ||||
| @@ -165,7 +190,7 @@ int XmlDocument::findNextTokenLength() throw() | |||||
| int len = 0; | int len = 0; | ||||
| juce_wchar c = *input; | juce_wchar c = *input; | ||||
| while (isXmlIdentifierChar (c)) | |||||
| while (XmlIdentifierChars::isIdentifierChar (c)) | |||||
| c = input [++len]; | c = input [++len]; | ||||
| return len; | return len; | ||||
| @@ -371,7 +396,7 @@ XmlElement* XmlDocument::readNextElement (const bool alsoParseSubElements) | |||||
| } | } | ||||
| // get an attribute.. | // get an attribute.. | ||||
| if (isXmlIdentifierChar (c)) | |||||
| if (XmlIdentifierChars::isIdentifierChar (c)) | |||||
| { | { | ||||
| const int attNameLen = findNextTokenLength(); | const int attNameLen = findNextTokenLength(); | ||||
| @@ -711,20 +736,11 @@ void XmlDocument::readEntity (String& result) | |||||
| const String XmlDocument::expandEntity (const String& ent) | const String XmlDocument::expandEntity (const String& ent) | ||||
| { | { | ||||
| if (ent.equalsIgnoreCase ("amp")) | |||||
| return String::charToString ('&'); | |||||
| if (ent.equalsIgnoreCase ("quot")) | |||||
| return String::charToString ('"'); | |||||
| if (ent.equalsIgnoreCase ("apos")) | |||||
| return String::charToString ('\''); | |||||
| if (ent.equalsIgnoreCase ("lt")) | |||||
| return String::charToString ('<'); | |||||
| if (ent.equalsIgnoreCase ("gt")) | |||||
| return String::charToString ('>'); | |||||
| if (ent.equalsIgnoreCase ("amp")) return String::charToString ('&'); | |||||
| if (ent.equalsIgnoreCase ("quot")) return String::charToString ('"'); | |||||
| if (ent.equalsIgnoreCase ("apos")) return String::charToString ('\''); | |||||
| if (ent.equalsIgnoreCase ("lt")) return String::charToString ('<'); | |||||
| if (ent.equalsIgnoreCase ("gt")) return String::charToString ('>'); | |||||
| if (ent[0] == '#') | if (ent[0] == '#') | ||||
| { | { | ||||
| @@ -57,6 +57,16 @@ | |||||
| @endcode | @endcode | ||||
| Or you can use the static helper methods for quick parsing.. | |||||
| @code | |||||
| XmlElement* xml = XmlDocument::parse (myXmlFile); | |||||
| if (xml != 0 && xml->hasTagName ("foobar")) | |||||
| { | |||||
| ...etc | |||||
| @endcode | |||||
| @see XmlElement | @see XmlElement | ||||
| */ | */ | ||||
| class JUCE_API XmlDocument | class JUCE_API XmlDocument | ||||
| @@ -64,28 +74,28 @@ class JUCE_API XmlDocument | |||||
| public: | public: | ||||
| //============================================================================== | //============================================================================== | ||||
| /** Creates an XmlDocument from the xml text. | /** Creates an XmlDocument from the xml text. | ||||
| The text doesn't actually get parsed until the getDocumentElement() method is | |||||
| called. | |||||
| The text doesn't actually get parsed until the getDocumentElement() method is called. | |||||
| */ | */ | ||||
| XmlDocument (const String& documentText); | XmlDocument (const String& documentText); | ||||
| /** Creates an XmlDocument from a file. | /** Creates an XmlDocument from a file. | ||||
| The text doesn't actually get parsed until the getDocumentElement() method is | |||||
| called. | |||||
| The text doesn't actually get parsed until the getDocumentElement() method is called. | |||||
| */ | */ | ||||
| XmlDocument (const File& file); | XmlDocument (const File& file); | ||||
| /** Destructor. */ | /** Destructor. */ | ||||
| ~XmlDocument(); | ~XmlDocument(); | ||||
| //============================================================================== | |||||
| /** Creates an XmlElement object to represent the main document node. | /** Creates an XmlElement object to represent the main document node. | ||||
| This method will do the actual parsing of the text, and if there's a | This method will do the actual parsing of the text, and if there's a | ||||
| parse error, it may returns 0 (and you can find out the error using | parse error, it may returns 0 (and you can find out the error using | ||||
| the getLastParseError() method). | the getLastParseError() method). | ||||
| See also the parse() methods, which provide a shorthand way to quickly | |||||
| parse a file or string. | |||||
| @param onlyReadOuterDocumentElement if true, the parser will only read the | @param onlyReadOuterDocumentElement if true, the parser will only read the | ||||
| first section of the file, and will only | first section of the file, and will only | ||||
| return the outer document element - this | return the outer document element - this | ||||
| @@ -126,6 +136,20 @@ public: | |||||
| */ | */ | ||||
| void setEmptyTextElementsIgnored (bool shouldBeIgnored) throw(); | void setEmptyTextElementsIgnored (bool shouldBeIgnored) throw(); | ||||
| //============================================================================== | |||||
| /** A handy static method that parses a file. | |||||
| This is a shortcut for creating an XmlDocument object and calling getDocumentElement() on it. | |||||
| @returns a new XmlElement which the caller will need to delete, or null if there was an error. | |||||
| */ | |||||
| static 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. | |||||
| @returns a new XmlElement which the caller will need to delete, or null if there was an error. | |||||
| */ | |||||
| static XmlElement* parse (const String& xmlData); | |||||
| //============================================================================== | //============================================================================== | ||||
| juce_UseDebuggingNewOperator | juce_UseDebuggingNewOperator | ||||
| @@ -134,7 +158,6 @@ private: | |||||
| const juce_wchar* input; | const juce_wchar* input; | ||||
| bool outOfData, errorOccurred; | bool outOfData, errorOccurred; | ||||
| bool identifierLookupTable [128]; | |||||
| String lastError, dtdText; | String lastError, dtdText; | ||||
| StringArray tokenisedDTD; | StringArray tokenisedDTD; | ||||
| bool needToLoadDTD, ignoreEmptyTextElements; | bool needToLoadDTD, ignoreEmptyTextElements; | ||||
| @@ -149,8 +172,6 @@ private: | |||||
| int findNextTokenLength() throw(); | int findNextTokenLength() throw(); | ||||
| void readQuotedString (String& result); | void readQuotedString (String& result); | ||||
| void readEntity (String& result); | void readEntity (String& result); | ||||
| static bool isXmlIdentifierCharSlow (juce_wchar c) throw(); | |||||
| bool isXmlIdentifierChar (juce_wchar c) const throw(); | |||||
| const String getFileContents (const String& filename) const; | const String getFileContents (const String& filename) const; | ||||
| const String expandEntity (const String& entity); | const String expandEntity (const String& entity); | ||||
| @@ -47,6 +47,16 @@ XmlElement::XmlAttributeNode::XmlAttributeNode (const String& name_, const Strin | |||||
| value (value_), | value (value_), | ||||
| next (0) | next (0) | ||||
| { | { | ||||
| #if JUCE_DEBUG | |||||
| // this checks whether the attribute name string contains any illegals characters.. | |||||
| for (const juce_wchar* t = name; *t != 0; ++t) | |||||
| jassert (CharacterFunctions::isLetterOrDigit (*t) || *t == '_' || *t == '-' || *t == ':'); | |||||
| #endif | |||||
| } | |||||
| inline bool XmlElement::XmlAttributeNode::hasName (const String& nameToMatch) const throw() | |||||
| { | |||||
| return name.equalsIgnoreCase (nameToMatch); | |||||
| } | } | ||||
| //============================================================================== | //============================================================================== | ||||
| @@ -220,21 +230,13 @@ namespace XmlOutputFunctions | |||||
| case '<': outputStream << "<"; break; | case '<': outputStream << "<"; break; | ||||
| case '\n': | case '\n': | ||||
| if (changeNewLines) | |||||
| outputStream << " "; | |||||
| else | |||||
| outputStream << (char) character; | |||||
| break; | |||||
| case '\r': | case '\r': | ||||
| if (changeNewLines) | |||||
| outputStream << " "; | |||||
| else | |||||
| if (! changeNewLines) | |||||
| { | |||||
| outputStream << (char) character; | outputStream << (char) character; | ||||
| break; | |||||
| break; | |||||
| } | |||||
| // Note: deliberate fall-through here! | |||||
| default: | default: | ||||
| outputStream << "&#" << ((int) (unsigned int) character) << ';'; | outputStream << "&#" << ((int) (unsigned int) character) << ';'; | ||||
| break; | break; | ||||
| @@ -282,8 +284,7 @@ void XmlElement::writeElementAsText (OutputStream& outputStream, | |||||
| const int attIndent = indentationLevel + tagName.length() + 1; | const int attIndent = indentationLevel + tagName.length() + 1; | ||||
| int lineLen = 0; | int lineLen = 0; | ||||
| const XmlAttributeNode* att = attributes; | |||||
| while (att != 0) | |||||
| for (const XmlAttributeNode* att = attributes; att != 0; att = att->next) | |||||
| { | { | ||||
| if (lineLen > lineWrapLength && indentationLevel >= 0) | if (lineLen > lineWrapLength && indentationLevel >= 0) | ||||
| { | { | ||||
| @@ -299,8 +300,6 @@ void XmlElement::writeElementAsText (OutputStream& outputStream, | |||||
| escapeIllegalXmlChars (outputStream, att->value, true); | escapeIllegalXmlChars (outputStream, att->value, true); | ||||
| outputStream.writeByte ('"'); | outputStream.writeByte ('"'); | ||||
| lineLen += (int) (outputStream.getPosition() - startPos); | lineLen += (int) (outputStream.getPosition() - startPos); | ||||
| att = att->next; | |||||
| } | } | ||||
| } | } | ||||
| @@ -460,29 +459,23 @@ XmlElement* XmlElement::getNextElementWithTagName (const String& requiredTagName | |||||
| //============================================================================== | //============================================================================== | ||||
| int XmlElement::getNumAttributes() const throw() | int XmlElement::getNumAttributes() const throw() | ||||
| { | { | ||||
| const XmlAttributeNode* att = attributes; | |||||
| int count = 0; | int count = 0; | ||||
| while (att != 0) | |||||
| { | |||||
| att = att->next; | |||||
| for (const XmlAttributeNode* att = attributes; att != 0; att = att->next) | |||||
| ++count; | ++count; | ||||
| } | |||||
| return count; | return count; | ||||
| } | } | ||||
| const String& XmlElement::getAttributeName (const int index) const throw() | const String& XmlElement::getAttributeName (const int index) const throw() | ||||
| { | { | ||||
| const XmlAttributeNode* att = attributes; | |||||
| int count = 0; | int count = 0; | ||||
| while (att != 0) | |||||
| for (const XmlAttributeNode* att = attributes; att != 0; att = att->next) | |||||
| { | { | ||||
| if (count == index) | if (count == index) | ||||
| return att->name; | return att->name; | ||||
| att = att->next; | |||||
| ++count; | ++count; | ||||
| } | } | ||||
| @@ -491,15 +484,13 @@ const String& XmlElement::getAttributeName (const int index) const throw() | |||||
| const String& XmlElement::getAttributeValue (const int index) const throw() | const String& XmlElement::getAttributeValue (const int index) const throw() | ||||
| { | { | ||||
| const XmlAttributeNode* att = attributes; | |||||
| int count = 0; | int count = 0; | ||||
| while (att != 0) | |||||
| for (const XmlAttributeNode* att = attributes; att != 0; att = att->next) | |||||
| { | { | ||||
| if (count == index) | if (count == index) | ||||
| return att->value; | return att->value; | ||||
| att = att->next; | |||||
| ++count; | ++count; | ||||
| } | } | ||||
| @@ -508,87 +499,55 @@ const String& XmlElement::getAttributeValue (const int index) const throw() | |||||
| bool XmlElement::hasAttribute (const String& attributeName) const throw() | bool XmlElement::hasAttribute (const String& attributeName) const throw() | ||||
| { | { | ||||
| const XmlAttributeNode* att = attributes; | |||||
| while (att != 0) | |||||
| { | |||||
| if (att->name.equalsIgnoreCase (attributeName)) | |||||
| for (const XmlAttributeNode* att = attributes; att != 0; att = att->next) | |||||
| if (att->hasName (attributeName)) | |||||
| return true; | return true; | ||||
| att = att->next; | |||||
| } | |||||
| return false; | return false; | ||||
| } | } | ||||
| //============================================================================== | //============================================================================== | ||||
| const String& XmlElement::getStringAttribute (const String& attributeName) const throw() | const String& XmlElement::getStringAttribute (const String& attributeName) const throw() | ||||
| { | { | ||||
| const XmlAttributeNode* att = attributes; | |||||
| while (att != 0) | |||||
| { | |||||
| if (att->name.equalsIgnoreCase (attributeName)) | |||||
| for (const XmlAttributeNode* att = attributes; att != 0; att = att->next) | |||||
| if (att->hasName (attributeName)) | |||||
| return att->value; | return att->value; | ||||
| att = att->next; | |||||
| } | |||||
| return String::empty; | return String::empty; | ||||
| } | } | ||||
| const String XmlElement::getStringAttribute (const String& attributeName, const String& defaultReturnValue) const | const String XmlElement::getStringAttribute (const String& attributeName, const String& defaultReturnValue) const | ||||
| { | { | ||||
| const XmlAttributeNode* att = attributes; | |||||
| while (att != 0) | |||||
| { | |||||
| if (att->name.equalsIgnoreCase (attributeName)) | |||||
| for (const XmlAttributeNode* att = attributes; att != 0; att = att->next) | |||||
| if (att->hasName (attributeName)) | |||||
| return att->value; | return att->value; | ||||
| att = att->next; | |||||
| } | |||||
| return defaultReturnValue; | return defaultReturnValue; | ||||
| } | } | ||||
| int XmlElement::getIntAttribute (const String& attributeName, const int defaultReturnValue) const | int XmlElement::getIntAttribute (const String& attributeName, const int defaultReturnValue) const | ||||
| { | { | ||||
| const XmlAttributeNode* att = attributes; | |||||
| while (att != 0) | |||||
| { | |||||
| if (att->name.equalsIgnoreCase (attributeName)) | |||||
| for (const XmlAttributeNode* att = attributes; att != 0; att = att->next) | |||||
| if (att->hasName (attributeName)) | |||||
| return att->value.getIntValue(); | return att->value.getIntValue(); | ||||
| att = att->next; | |||||
| } | |||||
| return defaultReturnValue; | return defaultReturnValue; | ||||
| } | } | ||||
| double XmlElement::getDoubleAttribute (const String& attributeName, const double defaultReturnValue) const | double XmlElement::getDoubleAttribute (const String& attributeName, const double defaultReturnValue) const | ||||
| { | { | ||||
| const XmlAttributeNode* att = attributes; | |||||
| while (att != 0) | |||||
| { | |||||
| if (att->name.equalsIgnoreCase (attributeName)) | |||||
| for (const XmlAttributeNode* att = attributes; att != 0; att = att->next) | |||||
| if (att->hasName (attributeName)) | |||||
| return att->value.getDoubleValue(); | return att->value.getDoubleValue(); | ||||
| att = att->next; | |||||
| } | |||||
| return defaultReturnValue; | return defaultReturnValue; | ||||
| } | } | ||||
| bool XmlElement::getBoolAttribute (const String& attributeName, const bool defaultReturnValue) const | bool XmlElement::getBoolAttribute (const String& attributeName, const bool defaultReturnValue) const | ||||
| { | { | ||||
| const XmlAttributeNode* att = attributes; | |||||
| while (att != 0) | |||||
| for (const XmlAttributeNode* att = attributes; att != 0; att = att->next) | |||||
| { | { | ||||
| if (att->name.equalsIgnoreCase (attributeName)) | |||||
| if (att->hasName (attributeName)) | |||||
| { | { | ||||
| juce_wchar firstChar = att->value[0]; | juce_wchar firstChar = att->value[0]; | ||||
| @@ -601,8 +560,6 @@ bool XmlElement::getBoolAttribute (const String& attributeName, const bool defau | |||||
| || firstChar == 'T' | || firstChar == 'T' | ||||
| || firstChar == 'Y'; | || firstChar == 'Y'; | ||||
| } | } | ||||
| att = att->next; | |||||
| } | } | ||||
| return defaultReturnValue; | return defaultReturnValue; | ||||
| @@ -612,20 +569,10 @@ bool XmlElement::compareAttribute (const String& attributeName, | |||||
| const String& stringToCompareAgainst, | const String& stringToCompareAgainst, | ||||
| const bool ignoreCase) const throw() | const bool ignoreCase) const throw() | ||||
| { | { | ||||
| const XmlAttributeNode* att = attributes; | |||||
| while (att != 0) | |||||
| { | |||||
| if (att->name.equalsIgnoreCase (attributeName)) | |||||
| { | |||||
| if (ignoreCase) | |||||
| return att->value.equalsIgnoreCase (stringToCompareAgainst); | |||||
| else | |||||
| return att->value == stringToCompareAgainst; | |||||
| } | |||||
| att = att->next; | |||||
| } | |||||
| for (const XmlAttributeNode* att = attributes; att != 0; att = att->next) | |||||
| if (att->hasName (attributeName)) | |||||
| return ignoreCase ? att->value.equalsIgnoreCase (stringToCompareAgainst) | |||||
| : att->value == stringToCompareAgainst; | |||||
| return false; | return false; | ||||
| } | } | ||||
| @@ -633,19 +580,6 @@ bool XmlElement::compareAttribute (const String& attributeName, | |||||
| //============================================================================== | //============================================================================== | ||||
| void XmlElement::setAttribute (const String& attributeName, const String& value) | void XmlElement::setAttribute (const String& attributeName, const String& value) | ||||
| { | { | ||||
| #if JUCE_DEBUG | |||||
| // check the identifier being passed in is legal.. | |||||
| const juce_wchar* t = attributeName; | |||||
| while (*t != 0) | |||||
| { | |||||
| jassert (CharacterFunctions::isLetterOrDigit (*t) | |||||
| || *t == '_' | |||||
| || *t == '-' | |||||
| || *t == ':'); | |||||
| ++t; | |||||
| } | |||||
| #endif | |||||
| if (attributes == 0) | if (attributes == 0) | ||||
| { | { | ||||
| attributes = new XmlAttributeNode (attributeName, value); | attributes = new XmlAttributeNode (attributeName, value); | ||||
| @@ -656,7 +590,7 @@ void XmlElement::setAttribute (const String& attributeName, const String& value) | |||||
| for (;;) | for (;;) | ||||
| { | { | ||||
| if (att->name.equalsIgnoreCase (attributeName)) | |||||
| if (att->hasName (attributeName)) | |||||
| { | { | ||||
| att->value = value; | att->value = value; | ||||
| break; | break; | ||||
| @@ -684,12 +618,11 @@ void XmlElement::setAttribute (const String& attributeName, const double number) | |||||
| void XmlElement::removeAttribute (const String& attributeName) throw() | void XmlElement::removeAttribute (const String& attributeName) throw() | ||||
| { | { | ||||
| XmlAttributeNode* att = attributes; | |||||
| XmlAttributeNode* lastAtt = 0; | XmlAttributeNode* lastAtt = 0; | ||||
| while (att != 0) | |||||
| for (XmlAttributeNode* att = attributes; att != 0; att = att->next) | |||||
| { | { | ||||
| if (att->name.equalsIgnoreCase (attributeName)) | |||||
| if (att->hasName (attributeName)) | |||||
| { | { | ||||
| if (lastAtt == 0) | if (lastAtt == 0) | ||||
| attributes = att->next; | attributes = att->next; | ||||
| @@ -701,7 +634,6 @@ void XmlElement::removeAttribute (const String& attributeName) throw() | |||||
| } | } | ||||
| lastAtt = att; | lastAtt = att; | ||||
| att = att->next; | |||||
| } | } | ||||
| } | } | ||||
| @@ -704,6 +704,8 @@ private: | |||||
| String name, value; | String name, value; | ||||
| XmlAttributeNode* next; | XmlAttributeNode* next; | ||||
| bool hasName (const String& name) const throw(); | |||||
| private: | private: | ||||
| XmlAttributeNode& operator= (const XmlAttributeNode&); | XmlAttributeNode& operator= (const XmlAttributeNode&); | ||||
| }; | }; | ||||
| @@ -198,8 +198,7 @@ bool PropertiesFile::save() | |||||
| e->setAttribute (PropertyFileConstants::nameAttribute, getAllProperties().getAllKeys() [i]); | e->setAttribute (PropertyFileConstants::nameAttribute, getAllProperties().getAllKeys() [i]); | ||||
| // if the value seems to contain xml, store it as such.. | // if the value seems to contain xml, store it as such.. | ||||
| XmlDocument xmlContent (getAllProperties().getAllValues() [i]); | |||||
| XmlElement* const childElement = xmlContent.getDocumentElement(); | |||||
| XmlElement* const childElement = XmlDocument::parse (getAllProperties().getAllValues() [i]); | |||||
| if (childElement != 0) | if (childElement != 0) | ||||
| e->addChildElement (childElement); | e->addChildElement (childElement); | ||||