The Birdfont Source Code


All Repositories / birdfont.git / commit – RSS feed

Speed optimizations in the XML parser

These changes was commited to the Birdfont repository Sun, 26 Oct 2014 23:03:30 +0000.

Contributing

Send patches or pull requests to johan.mattsson.m@gmail.com.
Clone this repository: git clone https://github.com/johanmattssonm/birdfont.git
author Johan Mattsson <johan.mattsson.m@gmail.com>
Sun, 26 Oct 2014 23:03:30 +0000 (00:03 +0100)
committer Johan Mattsson <johan.mattsson.m@gmail.com>
Sun, 26 Oct 2014 23:04:49 +0000 (00:04 +0100)
commit 5298e757f85d1cb8fdcd097a28fd9bc0dd1398c8
tree 67d6a08688d8067912970ba6097ae08573f0399b
parent 2fb45abca0c15456286c5c3f8fb4e22ad4c273a0
Speed optimizations in the XML parser
Uses a referens counted string class instead of copying the entire XML document.

libbirdxml/Attribute.vala
libbirdxml/Tag.vala
libbirdxml/Xml.vala
--- a/libbirdxml/Attribute.vala +++ b/libbirdxml/Attribute.vala @@ -20,22 +20,22 @@ [CCode (ref_function = "bird_attribute_ref", unref_function = "bird_attribute_unref")] public class Attribute { - public string ns; - public string name; - public string content; + public XmlString ns; + public XmlString name; + public XmlString content; public int refcount = 1; - internal Attribute (string ns, string name, string content) { + internal Attribute (XmlString ns, XmlString name, XmlString content) { this.ns = ns; this.name = name; this.content = content; } internal Attribute.empty () { - this.ns = ""; - this.name = ""; - this.content = ""; + this.ns = new XmlString ("", 0); + this.name = new XmlString ("", 0); + this.content = new XmlString ("", 0); } /** Increment the reference count. @@ -57,21 +57,21 @@ * @return namespace part for this attribute. */ public string get_namespace () { - return ns; + return ns.to_string (); } /** * @return the name of this attribute. */ public string get_name () { - return name; + return name.to_string (); } /** * @return the value of this attribute. */ public string get_content () { - return content; + return content.to_string (); } private extern void finalize ();
--- a/libbirdxml/Tag.vala +++ b/libbirdxml/Tag.vala @@ -27,9 +27,9 @@ public bool has_tags; public bool has_attributes; - public string name; - public string data; - public string attributes; + public XmlString name; + public XmlString data; + public XmlString attributes; public Tag? next_tag = null; public Attribute? next_attribute = null; @@ -39,7 +39,7 @@ public int refcount = 1; - internal Tag (string name, string attributes, string content, int log_level) { + internal Tag (XmlString name, XmlString attributes, XmlString content, int log_level) { this.log_level = log_level; this.name = name; this.data = content; @@ -49,9 +49,9 @@ } internal Tag.empty () { - data = ""; - attributes = ""; - name = ""; + data = new XmlString ("", 0); + attributes = new XmlString ("", 0); + name = new XmlString ("", 0); } /** Increment the reference count. @@ -102,7 +102,7 @@ * @return the name of this tag. */ public string get_name () { - return name; + return name.to_string (); } /** @@ -110,7 +110,7 @@ * @return data between the start and end tags. */ public string get_content () { - return data; + return data.to_string (); } /** @@ -148,15 +148,15 @@ Tag tag; tag = find_next_tag (tag_index, out end_tag_index); - + if (end_tag_index != -1) { tag_index = end_tag_index; has_tags = true; - } else { - has_tags = false; + return tag; } - return tag; + has_tags = false; + return new Tag.empty (); } Tag find_next_tag (int start, out int end_tag_index) { @@ -166,12 +166,13 @@ int end; int closing_tag; - string name; - string attributes; - string content; + XmlString name; + XmlString attributes; + XmlString content; index = start; end_tag_index = -1; + while (data.get_next_char (ref index, out c)) { if (c == '<') { separator = find_next_separator (index); @@ -192,12 +193,30 @@ attributes = data.substring (separator, end - separator); if (attributes.has_suffix ("/")) { - content = ""; + content = new XmlString ("", 0); end_tag_index = data.index_of (">", index); data.get_next_char (ref end_tag_index, out c); } else { - data.get_next_char (ref end, out c); // skip > + if (!data.get_next_char (ref end, out c)) {; // skip > + warn ("Unexpected end of data."); + error = true; + break; + } + + if (c != '>') { + warn ("Expecting '>'"); + error = true; + break; + } + closing_tag = find_closing_tag (name, end); + + if (closing_tag == -1) { + warn ("No closing tag."); + error = true; + break; + } + content = data.substring (end, closing_tag - end); end_tag_index = data.index_of (">", closing_tag); data.get_next_char (ref end_tag_index, out c); @@ -230,12 +249,18 @@ return -1; } - int find_closing_tag (string name, int start) { + int find_closing_tag (XmlString name, int start) { int index = start; int slash_index = start; int previous_index; unichar c; int start_count = 0; + + if (name.length == 0) { + error = true; + warn ("No name for tag."); + return -1; + } while (true) { previous_index = index; @@ -262,11 +287,12 @@ } error = true; - warn (@"No closing tag for $(name)."); + warn (@"No closing tag for $(name.to_string ())"); + return -1; } - bool is_tag (string name, int start) { + bool is_tag (XmlString name, int start) { int index = 0; int data_index = start; unichar c; @@ -293,9 +319,9 @@ int previous_index; int index = attribute_index; int name_start; - string attribute_name; - string ns; - string content; + XmlString attribute_name; + XmlString ns; + XmlString content; int ns_separator; int content_start; int content_stop; @@ -335,7 +361,7 @@ attribute_name = attributes.substring (name_start, previous_index - name_start); index = name_start + attribute_name.length; - ns = ""; + ns = new XmlString ("", 0); ns_separator = attribute_name.index_of (":"); if (ns_separator != -1) { ns = attribute_name.substring (0, ns_separator); @@ -407,6 +433,10 @@ } public bool next () { + if (tag.error) { + return false; + } + if (tag.has_more_tags ()) { next_tag = tag.get_next_tag (); } else {
--- a/libbirdxml/Xml.vala +++ b/libbirdxml/Xml.vala @@ -72,16 +72,18 @@ [CCode (ref_function = "bird_xml_parser_ref", unref_function = "bird_xml_parser_unref")] public class XmlParser { public Tag root; - public string data; + public XmlString data; + public string input; public bool error; public int refcount = 1; - + /** * Create a new xml parser. * @param data valid xml data */ public XmlParser (string data) { - this.data = data; + this.input = data; + this.data = new XmlString (data, data.length); reparse (NONE); } @@ -121,7 +123,7 @@ Attributes attributes = tag.get_attributes (); foreach (Attribute a in attributes) { - if (tag.has_failed () || a.get_name () == "") { + if (tag.has_failed () || a.name.length == 0) { error = true; return; } @@ -152,7 +154,7 @@ internal void reparse (int log_level) { int root_index; Tag container; - string content; + XmlString content; error = false; @@ -165,7 +167,7 @@ root = new Tag.empty (); } else { content = data.substring (root_index); - container = new Tag ("", "", content, log_level); + container = new Tag (new XmlString ("", 0), new XmlString ("", 0), content, log_level); root = container.get_next_tag (); } } @@ -196,7 +198,7 @@ /** Print a warning message. */ public static void warning (string message) { - print ("XML Parser: "); + print ("XML error: "); print (message); print ("\n"); }