Browse Source

Added a couple of handy methods XmlDocument::parse().

tags/2021-05-28
Julian Storer 15 years ago
parent
commit
030489f086
12 changed files with 136 additions and 179 deletions
  1. +1
    -2
      extras/Jucer (experimental)/Source/Project/jucer_Project.cpp
  2. +6
    -8
      src/audio/midi/juce_MidiFile.cpp
  3. +2
    -6
      src/audio/processors/juce_AudioProcessor.cpp
  4. +1
    -3
      src/containers/juce_PropertySet.cpp
  5. +1
    -3
      src/gui/components/controls/juce_TableHeaderComponent.cpp
  6. +1
    -2
      src/io/network/juce_URL.cpp
  7. +1
    -2
      src/native/linux/juce_linux_Fonts.cpp
  8. +52
    -36
      src/text/juce_XmlDocument.cpp
  9. +30
    -9
      src/text/juce_XmlDocument.h
  10. +38
    -106
      src/text/juce_XmlElement.cpp
  11. +2
    -0
      src/text/juce_XmlElement.h
  12. +1
    -2
      src/utilities/juce_PropertiesFile.cpp

+ 1
- 2
extras/Jucer (experimental)/Source/Project/jucer_Project.cpp View File

@@ -155,8 +155,7 @@ void Project::setMissingDefaultValues()
//==============================================================================
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()))
return "Not a valid Jucer project!";


+ 6
- 8
src/audio/midi/juce_MidiFile.cpp View File

@@ -34,7 +34,7 @@ BEGIN_JUCE_NAMESPACE
//==============================================================================
namespace MidiFileHelpers
{
static void writeVariableLengthInt (OutputStream& out, unsigned int v)
void writeVariableLengthInt (OutputStream& out, unsigned int v)
{
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);
data += 4;
@@ -97,9 +97,9 @@ namespace MidiFileHelpers
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)
{
@@ -184,7 +184,6 @@ namespace MidiFileHelpers
}
}
};
}
//==============================================================================
@@ -409,8 +408,7 @@ bool MidiFile::writeTo (OutputStream& out)
return true;
}
void MidiFile::writeTrack (OutputStream& mainOut,
const int trackNum)
void MidiFile::writeTrack (OutputStream& mainOut, const int trackNum)
{
MemoryOutputStream out;


+ 2
- 6
src/audio/processors/juce_AudioProcessor.cpp View File

@@ -285,12 +285,8 @@ XmlElement* AudioProcessor::getXmlFromBinary (const void* data,
const int stringLength = (int) ByteOrder::littleEndianInt (addBytesToPointer (data, 4));
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;


+ 1
- 3
src/containers/juce_PropertySet.cpp View File

@@ -127,9 +127,7 @@ bool PropertySet::getBoolValue (const String& keyName,
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)


+ 1
- 3
src/gui/components/controls/juce_TableHeaderComponent.cpp View File

@@ -460,9 +460,7 @@ const String TableHeaderComponent::toString() const
void TableHeaderComponent::restoreFromString (const String& storedVersion)
{
XmlDocument doc (storedVersion);
ScopedPointer <XmlElement> storedXml (doc.getDocumentElement());
ScopedPointer <XmlElement> storedXml (XmlDocument::parse (storedVersion));
int index = 0;
if (storedXml != 0 && storedXml->hasTagName ("TABLELAYOUT"))


+ 1
- 2
src/io/network/juce_URL.cpp View File

@@ -466,8 +466,7 @@ const String URL::readEntireTextStream (const bool usePostCommand) const
XmlElement* URL::readEntireXmlStream (const bool usePostCommand) const
{
XmlDocument doc (readEntireTextStream (usePostCommand));
return doc.getDocumentElement();
return XmlDocument::parse (readEntireTextStream (usePostCommand));
}
//==============================================================================


+ 1
- 2
src/native/linux/juce_linux_Fonts.cpp View File

@@ -108,8 +108,7 @@ public:
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)
{


+ 52
- 36
src/text/juce_XmlDocument.cpp View File

@@ -40,15 +40,27 @@ XmlDocument::XmlDocument (const String& documentText)
}
XmlDocument::XmlDocument (const File& file)
: ignoreEmptyTextElements (true)
: ignoreEmptyTextElements (true),
inputSource (new FileInputSource (file))
{
inputSource = new FileInputSource (file);
}
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()
{
inputSource = newSource;
@@ -59,16 +71,36 @@ void XmlDocument::setEmptyTextElementsIgnored (const bool shouldBeIgnored) throw
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)
@@ -96,9 +128,6 @@ XmlElement* XmlDocument::getDocumentElement (const bool onlyReadOuterDocumentEle
outOfData = false;
needToLoadDTD = true;
for (int i = 0; i < 128; ++i)
identifierLookupTable[i] = isXmlIdentifierCharSlow ((juce_wchar) i);
if (textToParse.isEmpty())
{
lastError = "not enough input";
@@ -150,14 +179,10 @@ const String XmlDocument::getFileContents (const String& filename) const
juce_wchar XmlDocument::readNextChar() throw()
{
if (*input != 0)
{
return *input++;
}
else
{
outOfData = true;
return 0;
}
outOfData = true;
return 0;
}
int XmlDocument::findNextTokenLength() throw()
@@ -165,7 +190,7 @@ int XmlDocument::findNextTokenLength() throw()
int len = 0;
juce_wchar c = *input;
while (isXmlIdentifierChar (c))
while (XmlIdentifierChars::isIdentifierChar (c))
c = input [++len];
return len;
@@ -371,7 +396,7 @@ XmlElement* XmlDocument::readNextElement (const bool alsoParseSubElements)
}
// get an attribute..
if (isXmlIdentifierChar (c))
if (XmlIdentifierChars::isIdentifierChar (c))
{
const int attNameLen = findNextTokenLength();
@@ -711,20 +736,11 @@ void XmlDocument::readEntity (String& result)
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] == '#')
{


+ 30
- 9
src/text/juce_XmlDocument.h View File

@@ -57,6 +57,16 @@
@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
*/
class JUCE_API XmlDocument
@@ -64,28 +74,28 @@ class JUCE_API XmlDocument
public:
//==============================================================================
/** 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);
/** 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);
/** Destructor. */
~XmlDocument();
//==============================================================================
/** 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
parse error, it may returns 0 (and you can find out the error using
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
first section of the file, and will only
return the outer document element - this
@@ -126,6 +136,20 @@ public:
*/
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
@@ -134,7 +158,6 @@ private:
const juce_wchar* input;
bool outOfData, errorOccurred;
bool identifierLookupTable [128];
String lastError, dtdText;
StringArray tokenisedDTD;
bool needToLoadDTD, ignoreEmptyTextElements;
@@ -149,8 +172,6 @@ private:
int findNextTokenLength() throw();
void readQuotedString (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 expandEntity (const String& entity);


+ 38
- 106
src/text/juce_XmlElement.cpp View File

@@ -47,6 +47,16 @@ XmlElement::XmlAttributeNode::XmlAttributeNode (const String& name_, const Strin
value (value_),
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 << "&lt;"; break;
case '\n':
if (changeNewLines)
outputStream << "&#10;";
else
outputStream << (char) character;
break;
case '\r':
if (changeNewLines)
outputStream << "&#13;";
else
if (! changeNewLines)
{
outputStream << (char) character;
break;
break;
}
// Note: deliberate fall-through here!
default:
outputStream << "&#" << ((int) (unsigned int) character) << ';';
break;
@@ -282,8 +284,7 @@ void XmlElement::writeElementAsText (OutputStream& outputStream,
const int attIndent = indentationLevel + tagName.length() + 1;
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)
{
@@ -299,8 +300,6 @@ void XmlElement::writeElementAsText (OutputStream& outputStream,
escapeIllegalXmlChars (outputStream, att->value, true);
outputStream.writeByte ('"');
lineLen += (int) (outputStream.getPosition() - startPos);
att = att->next;
}
}
@@ -460,29 +459,23 @@ XmlElement* XmlElement::getNextElementWithTagName (const String& requiredTagName
//==============================================================================
int XmlElement::getNumAttributes() const throw()
{
const XmlAttributeNode* att = attributes;
int count = 0;
while (att != 0)
{
att = att->next;
for (const XmlAttributeNode* att = attributes; att != 0; att = att->next)
++count;
}
return count;
}
const String& XmlElement::getAttributeName (const int index) const throw()
{
const XmlAttributeNode* att = attributes;
int count = 0;
while (att != 0)
for (const XmlAttributeNode* att = attributes; att != 0; att = att->next)
{
if (count == index)
return att->name;
att = att->next;
++count;
}
@@ -491,15 +484,13 @@ const String& XmlElement::getAttributeName (const int index) const throw()
const String& XmlElement::getAttributeValue (const int index) const throw()
{
const XmlAttributeNode* att = attributes;
int count = 0;
while (att != 0)
for (const XmlAttributeNode* att = attributes; att != 0; att = att->next)
{
if (count == index)
return att->value;
att = att->next;
++count;
}
@@ -508,87 +499,55 @@ const String& XmlElement::getAttributeValue (const int index) 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;
att = att->next;
}
return false;
}
//==============================================================================
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;
att = att->next;
}
return String::empty;
}
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;
att = att->next;
}
return defaultReturnValue;
}
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();
att = att->next;
}
return defaultReturnValue;
}
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();
att = att->next;
}
return defaultReturnValue;
}
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];
@@ -601,8 +560,6 @@ bool XmlElement::getBoolAttribute (const String& attributeName, const bool defau
|| firstChar == 'T'
|| firstChar == 'Y';
}
att = att->next;
}
return defaultReturnValue;
@@ -612,20 +569,10 @@ bool XmlElement::compareAttribute (const String& attributeName,
const String& stringToCompareAgainst,
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;
}
@@ -633,19 +580,6 @@ bool XmlElement::compareAttribute (const String& attributeName,
//==============================================================================
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)
{
attributes = new XmlAttributeNode (attributeName, value);
@@ -656,7 +590,7 @@ void XmlElement::setAttribute (const String& attributeName, const String& value)
for (;;)
{
if (att->name.equalsIgnoreCase (attributeName))
if (att->hasName (attributeName))
{
att->value = value;
break;
@@ -684,12 +618,11 @@ void XmlElement::setAttribute (const String& attributeName, const double number)
void XmlElement::removeAttribute (const String& attributeName) throw()
{
XmlAttributeNode* att = attributes;
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)
attributes = att->next;
@@ -701,7 +634,6 @@ void XmlElement::removeAttribute (const String& attributeName) throw()
}
lastAtt = att;
att = att->next;
}
}


+ 2
- 0
src/text/juce_XmlElement.h View File

@@ -704,6 +704,8 @@ private:
String name, value;
XmlAttributeNode* next;
bool hasName (const String& name) const throw();
private:
XmlAttributeNode& operator= (const XmlAttributeNode&);
};


+ 1
- 2
src/utilities/juce_PropertiesFile.cpp View File

@@ -198,8 +198,7 @@ bool PropertiesFile::save()
e->setAttribute (PropertyFileConstants::nameAttribute, getAllProperties().getAllKeys() [i]);
// 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)
e->addChildElement (childElement);


Loading…
Cancel
Save