Clone in a terminal:
Commit 5298e75
Johan Mattsson - 2014-10-26T23:04:49+00:00
5298e757f85d1cb8fdcd097a28fd9bc0dd1398c8johan.mattsson.m@gmail.com

Speed optimizations in the XML parser Uses a referens counted string class instead of copying the entire XML document.

Changed files (3)

Diff

diff --git a/libbirdxml/Attribute.vala b/libbirdxml/Attribute.valaindex 8b935d5..e8170d0 100644--- a/libbirdxml/Attribute.vala+++ b/libbirdxml/Attribute.vala@@ -20,22 +20,22 @@ namespace Bird { [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 @@ public class Attribute { 	 * @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 ();diff --git a/libbirdxml/Tag.vala b/libbirdxml/Tag.valaindex 67673a4..ff88438 100644--- a/libbirdxml/Tag.vala+++ b/libbirdxml/Tag.vala@@ -27,9 +27,9 @@ public class Tag { 	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 class Tag { 	 	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 @@ public class Tag { 	} 	 	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 @@ public class Tag { 	 * @return the name of this tag.  	 */  	public string get_name () {-		return name;+		return name.to_string (); 	}  	/** @@ -110,7 +110,7 @@ public class Tag { 	 * @return data between the start and end tags. 	 */ 	public string get_content () {-		return data;+		return data.to_string (); 	}  	/** @@ -148,15 +148,15 @@ public class Tag { 		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 @@ public class Tag { 		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 @@ public class Tag { 				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,13 +249,19 @@ public class Tag { 		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; 			if (!data.get_next_char (ref index, out c)) {@@ -262,11 +287,12 @@ public class Tag { 		} 		 		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 @@ public class Tag { 		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 @@ public class Tag { 		 		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 class Tag { 		}  		public bool next () {+			if (tag.error) { +				return false;+			}+			 			if (tag.has_more_tags ()) { 				next_tag = tag.get_next_tag (); 			} else {diff --git a/libbirdxml/Xml.vala b/libbirdxml/Xml.valaindex 5694782..87ad225 100644--- a/libbirdxml/Xml.vala+++ b/libbirdxml/Xml.vala@@ -72,16 +72,18 @@ internal const int WARNINGS = 1; [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 @@ public class XmlParser { 		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 @@ public class XmlParser { 	internal void reparse (int log_level) { 		int root_index; 		Tag container;-		string content;+		XmlString content; 		 		error = false; 		@@ -165,7 +167,7 @@ public class XmlParser { 			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 @@ public class XmlParser {  	/** Print a warning message. */ 	public static void warning (string message) {-		print ("XML Parser: "); +		print ("XML error: ");  		print (message); 		print ("\n"); 	}

Contact

Email: johan.mattsson.m@gmail.com
Mastodon: typo.social/@birdfont
GitHub: johanmattssonm
LinkedIn: johan-mattsson-2ab324112