[gxml] Fixed implementation of libxml-NamedAttrMap
- From: Daniel Espinosa Ortiz <despinosa src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [gxml] Fixed implementation of libxml-NamedAttrMap
- Date: Sat, 2 May 2015 02:22:48 +0000 (UTC)
commit 6cd0e4c2d59276e5915bf4390e3dd25b98cd80fd
Author: Daniel Espinosa <esodan gmail com>
Date: Fri May 1 20:59:32 2015 -0500
Fixed implementation of libxml-NamedAttrMap
* NamedAttrMap re-implemented Gee.Map for GXml.Attribute
using libxml2 direct access
* Create a new NamedAttrMap is required each time access
GXml.Node.attrs, in order to access any update (FIXIT!)
* More SerializableObjectModel xElement substitutions
gxml/Makefile.am | 1 +
gxml/SerializableObjectModel.vala | 2 +-
gxml/libxml-Attr.vala | 2 +-
gxml/libxml-NamedAttrMap.vala | 337 +++++++++++++++++++++++++++++++++++++
gxml/libxml-NamedNodeMap.vala | 258 +----------------------------
5 files changed, 341 insertions(+), 259 deletions(-)
---
diff --git a/gxml/Makefile.am b/gxml/Makefile.am
index 3afa6d9..2c28bc0 100644
--- a/gxml/Makefile.am
+++ b/gxml/Makefile.am
@@ -37,6 +37,7 @@ sources = \
libxml-Implementation.vala \
libxml-LinkedList.vala \
libxml-NamedNodeMap.vala \
+ libxml-NamedAttrMap.vala \
libxml-NamespaceAttr.vala \
libxml-NodeChildNodeList.vala \
libxml-NodeList.vala \
diff --git a/gxml/SerializableObjectModel.vala b/gxml/SerializableObjectModel.vala
index 67ad0eb..669f8c6 100644
--- a/gxml/SerializableObjectModel.vala
+++ b/gxml/SerializableObjectModel.vala
@@ -246,7 +246,7 @@ public abstract class GXml.SerializableObjectModel : Object, Serializable
stdout.printf (@"Node is: $(element)\n\n");
stdout.printf (@"Attributes in Node: $(element.name)\n");
#endif
- foreach (GXml.Node attr in ((xElement)element).attributes.get_values ())
+ foreach (GXml.Node attr in element.attrs.values)
{
deserialize_property (attr);
}
diff --git a/gxml/libxml-Attr.vala b/gxml/libxml-Attr.vala
index 853ba26..19d1210 100644
--- a/gxml/libxml-Attr.vala
+++ b/gxml/libxml-Attr.vala
@@ -55,7 +55,7 @@ namespace GXml {
*
* @see GXml.Node
*/
- public class Attr : BackedNode {
+ public class Attr : BackedNode, GXml.Attribute {
/** Private properties */
/* this displaces BackedNode's xmlNode node */
internal new Xml.Attr *node;
diff --git a/gxml/libxml-NamedAttrMap.vala b/gxml/libxml-NamedAttrMap.vala
new file mode 100644
index 0000000..0789d63
--- /dev/null
+++ b/gxml/libxml-NamedAttrMap.vala
@@ -0,0 +1,337 @@
+/* -*- Mode: vala; indent-tabs-mode: t; c-basic-offset: 2; tab-width: 2 -*- */
+/* Node.vala
+ *
+ * Copyright (C) 2011-2013 Richard Schwarting <aquarichy gmail com>
+ * Copyright (C) 2011,2014-2015 Daniel Espinosa <esodan gmail com>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, see <http://www.gnu.org/licenses/>.
+ *
+ * Authors:
+ * Richard Schwarting <aquarichy gmail com>
+ */
+
+using GXml;
+using Gee;
+
+namespace GXml {
+ /**
+ * A class implementing { link NamedNodeMap} interface for { link Attr} objects.
+ *
+ * A collection of { link NamedNodeMap} of type { link Attr} objects in a { link xElement}.
+ */
+ public abstract class AbstractNamedAttrMap : Object,
+ Traversable<Entry<string,GXml.Attribute>>,
+ Iterable<Entry<string,GXml.Attribute>>
+ {
+ protected xElement elem;
+
+ internal AbstractNamedAttrMap (xElement e) {
+ this.elem = e;
+ }
+
+ // Gee.Iterable
+ public Gee.Iterator<AbstractNamedAttrMap.Entry> iterator () { return new Iterator (this); }
+ // Gee.Traversable
+ public new bool @foreach (Gee.ForallFunc<AbstractNamedAttrMap.Entry> f) { return new Iterator
(this).foreach (f); }
+
+ public class Entry : Gee.Map.Entry<string,Attribute> {
+ public Entry (string k, Attribute v) {
+ _key = k;
+ value = v;
+ }
+ private string _key;
+ public override string key { get { return _key; } }
+ public override bool read_only { get { return true; } }
+ public override Attribute value { get; set; }
+ }
+ protected class Iterator : Object,
+ Gee.Traversable<AbstractNamedAttrMap.Entry>,
+ Gee.Iterator<AbstractNamedAttrMap.Entry>
+ {
+ protected AbstractNamedAttrMap nm;
+ protected Xml.Attr* cur = null;
+ public Iterator (AbstractNamedAttrMap nm)
+ {
+ this.nm = nm;
+ }
+ // Gee.Traversable
+ new bool @foreach (Gee.ForallFunc<AbstractNamedAttrMap.Entry> f)
+ {
+ while (next ()) { if (!f (@get())) return false; }
+ return true;
+ }
+ // Gee.Iterator
+ public new Entry @get ()
+ {
+ string k = "";
+ if (cur != null) k = cur->name;
+ return new Entry (k, (GXml.Attribute) new Attr (cur, (xDocument)
nm.elem.document));
+ }
+ public bool has_next ()
+ {
+ if (nm.elem.node == null) return false;
+ if (nm.elem.node->properties == null) return false;
+ if (cur == null) return false;
+ if (cur->next == null) return false;
+ return true;
+ }
+ public bool next ()
+ {
+ if (cur == null) {
+ if (nm.elem.node == null) return false;
+ if (nm.elem.node->properties == null) return false;
+ cur = nm.elem.node->properties;
+ return true;
+ }
+ if (has_next ()) {
+ cur = cur->next;
+ return true;
+ }
+ return false;
+ }
+ public void remove () {
+ if (!valid) return;
+ nm.elem.node->unset_prop (cur->name); // TODO: namespace
+ }
+ public bool read_only { get { return false; } }
+ public bool valid {
+ get {
+ if (nm.elem.node == null) return false;
+ if (nm.elem.node->properties == null) return false;
+ if (cur == null) return false;
+ return true;
+ }
+ }
+ }
+ }
+ /**
+ * A class implementing { link NamedNodeMap} interface for { link Attr} objects.
+ *
+ * A collection of { link NamedNodeMap} of type { link Attr} objects in a { link xElement}.
+ */
+ public class NamedAttrMap : AbstractNamedAttrMap, Map<string,GXml.Attribute>,
+ NamedNodeMap<Attr?>
+ {
+ internal NamedAttrMap (xElement e)
+ {
+ base (e);
+ this.elem = e;
+ }
+ // Gee.Map
+ public void clear ()
+ {
+ if (elem.node == null) return;
+ foreach (string key in keys) {
+ elem.node->unset_prop (key);
+ }
+ }
+ public bool contains (string key) { return has_key (key); }
+ public bool contains_all (Gee.Map<string,GXml.Attribute> map) { return has_all (map); }
+ public new Attribute @get (string key)
+ {
+ var at = elem.node->has_prop (key);
+ return (Attribute) new Attr(at, (xDocument) elem.document);
+ }
+ public bool has (string key, Attribute value)
+ {
+ var at = elem.node->has_prop (key);
+ if (at == null) return false;
+ if (at->name == value.name) return true; // Xml.Attr to Xml.Node? to check its value
+ return false;
+ }
+ public bool has_key (string key)
+ {
+ var at = elem.node->has_prop (key);
+ if (at == null) return false;
+ return true;
+ }
+ public Gee.MapIterator<string,Attribute> map_iterator () { return new Iterator (this); }
+ public bool remove (string key, out Attribute val = null) { return unset (key, out val); }
+ public bool remove_all (Gee.Map<string,Attribute> map) { return unset_all (map); }
+ public new void @set (string key, Attribute val)
+ {
+ elem.node->set_prop (key, val.value);
+ }
+ public bool unset (string key, out Attribute value = null)
+ {
+ var r = elem.node->unset_prop (key);
+ if (r != 0) return false;
+ return true;
+ }
+ public Gee.Set<Gee.Map.Entry<string,Attribute>> entries {
+ owned get {
+ var s = new HashSet<AbstractNamedAttrMap.Entry> ();
+ var iter = new Iterator (this);
+ while (iter.next ()) {
+ var v = iter.get ();
+ s.add (v);
+ }
+ return s;
+ }
+ }
+ public Gee.Set<string> keys {
+ owned get {
+ var s = new HashSet<string> ();
+ var iter = new Iterator (this);
+ while (iter.next ()) {
+ var v = iter.get ();
+ s.add (v.key);
+ }
+ return s;
+ }
+ }
+ public bool read_only { get { return false; } }
+ public Gee.Map<string,GXml.Attribute> read_only_view {
+ owned get {
+ return new NamedAttrMap (this.elem); // FIXME: No read only is setup
+ }
+ }
+ public int size {
+ get {
+ var iter = new Iterator (this);
+ int i = 0;
+ while (iter.next ()) { i++; }
+ return i;
+ }
+ }
+ public Gee.Collection<GXml.Attribute> values
+ {
+ owned get {
+ var s = new HashSet<GXml.Attribute> ();
+ var iter = new Iterator (this);
+ while (iter.next ()) {
+ var v = iter.get ();
+ s.add (v.value);
+ }
+ return s;
+ }
+ }
+ // Map Iterator
+ private class Iterator : AbstractNamedAttrMap.Iterator, Gee.MapIterator<string,GXml.Attribute>
+ {
+ public Iterator (NamedAttrMap m) {
+ base (m);
+ }
+ public string get_key () { return get ().key; }
+ public Attribute get_value () { return get ().value; }
+ public void set_value (Attribute val)
+ {
+ unset ();
+ @set (val.name, val);
+ }
+ public void unset () {
+ nm.elem.node->unset_prop (get ().key);
+ }
+ public bool mutable { get { return true; } }
+ }
+ // NamedNodeMap interface
+ public Attr? get_named_item (string name) {
+ Xml.Attr *prop = this.elem.node->has_prop (name);
+ return this.elem.owner_document.lookup_attr (prop);
+ }
+
+ public Attr? set_named_item (Attr? gxml_attr_new) {
+ Xml.Node *xml_elem;
+ Xml.Attr *xml_prop_old;
+ Xml.Attr *xml_prop_new;
+ Attr gxml_attr_old;
+
+ /* TODO: INUSE_ATTRIBUTE_ERR if new_attr already belongs to
+ another element */
+ this.elem.check_read_only ();
+ this.elem.check_wrong_document (gxml_attr_new);
+
+ /* If you set an attribute/property in libxml2, it reuses any existing
+ Xml.Attr with the same name and just changes the value. With GXml,
+ if you set a new value, we want a new GXml.Attr to represent that,
+ and we want the old GXml.Attr to represent the old one. */
+ xml_elem = this.elem.node;
+ gxml_attr_old = this.get_named_item (gxml_attr_new.node_name);
+ if (gxml_attr_old != null) {
+ /* TODO: make sure xmlCopyNode is appropriate for xmlAttrs;
+ xmlCopyProp didn't seem to do what we wanted */
+ xml_prop_old = (Xml.Attr*)((Xml.Node*)gxml_attr_old.node)->copy (1);
+ gxml_attr_old.set_xmlnode ((Xml.Node*)xml_prop_old,
gxml_attr_old.owner_document);
+ }
+
+ /* TODO: instead of using item.node_value, which uses child_nodes
+ and iterates over them, use xmlNodeListGetString () */
+ xml_prop_new = xml_elem->set_prop (gxml_attr_new.node_name, gxml_attr_new.node_value);
+ gxml_attr_new.set_xmlnode ((Xml.Node*)xml_prop_new, gxml_attr_new.owner_document); //
TODO: what of the old xmlNode that gxml_attr_new used to have?
+
+ return gxml_attr_old;
+ }
+
+ public Attr? remove_named_item (string name) {
+ Attr gxml_attr_old;
+ Xml.Attr *xml_prop_old;
+ Xml.Node *xml_elem;
+
+ gxml_attr_old = this.get_named_item (name);
+ if (gxml_attr_old == null) {
+ GXml.warning (DomException.NOT_FOUND,
+ "No child with name '%s' exists in node '%s'".printf (name,
this.elem.node_name));
+ return null;
+ } else {
+ /* xmlRemoveProp () frees the underlying Attr memory
+ preventing us from returning the old attribute.
+ We could just clone the GXml.Attr with it, but
+ then the user would get a GXml.Attr for their old
+ different that would be different from previous GXml.Attrs
+ for it pre-removal (since they'd now have a clone).
+
+ So, instead we're going to clone the underlying xmlNode
+ and we're going to replace the existing GXmlAttr's
+ underlying xmlNode with the clone, so the user sees
+ the same GXmlAttr, and it has memory that wasn't freed.
+ */
+ xml_elem = this.elem.node;
+ /* TODO: make sure xmlCopyNode is appropriate for xmlAttrs;
+ xmlCopyProp didn't seem to do what we wanted */
+ xml_prop_old = (Xml.Attr*)((Xml.Node*)gxml_attr_old.node)->copy (1);
+ gxml_attr_old.set_xmlnode ((Xml.Node*)xml_prop_old,
gxml_attr_old.owner_document);
+
+ xml_elem->has_prop (name)->remove ();
+
+ return gxml_attr_old;
+ }
+ }
+
+ public Attr? item (ulong index) {
+ Xml.Attr *attr;
+
+ attr = this.elem.node->properties;
+ for (int i = 0; i < index && attr != null; i++) {
+ attr = attr->next;
+ }
+
+ if (attr == null) {
+ return null;
+ } else {
+ return this.elem.owner_document.lookup_attr (attr);
+ }
+ }
+
+ public ulong length {
+ get {
+ int len = 0;
+ for (Xml.Attr *attr = this.elem.node->properties; attr != null; attr =
attr->next) {
+ len++;
+ }
+ return len;
+ }
+ }
+
+ }
+}
diff --git a/gxml/libxml-NamedNodeMap.vala b/gxml/libxml-NamedNodeMap.vala
index 8f6e6b2..357b8da 100644
--- a/gxml/libxml-NamedNodeMap.vala
+++ b/gxml/libxml-NamedNodeMap.vala
@@ -36,262 +36,6 @@ namespace GXml {
public abstract T set_named_item (T item);
public abstract T remove_named_item (string name);
public abstract T item (ulong index);
- public abstract ulong length {
- get;
- private set;
- }
- }
-
- /**
- * A class implementing { link NamedNodeMap} interface for { link Attr} objects.
- *
- * A collection of { link NamedNodeMap} of type { link Attr} objects in a { link xElement}.
- */
- public class NamedAttrMap : AbstractMap<string,xNode>, NamedNodeMap<Attr?> {
- private xElement elem;
-
- internal NamedAttrMap (xElement e) {
- this.elem = e;
- }
-
- public Attr? get_named_item (string name) {
- Xml.Attr *prop = this.elem.node->has_prop (name);
- return this.elem.owner_document.lookup_attr (prop);
- }
-
- public Attr? set_named_item (Attr? gxml_attr_new) {
- Xml.Node *xml_elem;
- Xml.Attr *xml_prop_old;
- Xml.Attr *xml_prop_new;
- Attr gxml_attr_old;
-
- /* TODO: INUSE_ATTRIBUTE_ERR if new_attr already belongs to
- another element */
- this.elem.check_read_only ();
- this.elem.check_wrong_document (gxml_attr_new);
-
- /* If you set an attribute/property in libxml2, it reuses any existing
- Xml.Attr with the same name and just changes the value. With GXml,
- if you set a new value, we want a new GXml.Attr to represent that,
- and we want the old GXml.Attr to represent the old one. */
- xml_elem = this.elem.node;
- gxml_attr_old = this.get_named_item (gxml_attr_new.node_name);
- if (gxml_attr_old != null) {
- /* TODO: make sure xmlCopyNode is appropriate for xmlAttrs;
- xmlCopyProp didn't seem to do what we wanted */
- xml_prop_old = (Xml.Attr*)((Xml.Node*)gxml_attr_old.node)->copy (1);
- gxml_attr_old.set_xmlnode ((Xml.Node*)xml_prop_old,
gxml_attr_old.owner_document);
- }
-
- /* TODO: instead of using item.node_value, which uses child_nodes
- and iterates over them, use xmlNodeListGetString () */
- xml_prop_new = xml_elem->set_prop (gxml_attr_new.node_name, gxml_attr_new.node_value);
- gxml_attr_new.set_xmlnode ((Xml.Node*)xml_prop_new, gxml_attr_new.owner_document); //
TODO: what of the old xmlNode that gxml_attr_new used to have?
-
- return gxml_attr_old;
- }
-
- public Attr? remove_named_item (string name) {
- Attr gxml_attr_old;
- Xml.Attr *xml_prop_old;
- Xml.Node *xml_elem;
-
- gxml_attr_old = this.get_named_item (name);
- if (gxml_attr_old == null) {
- GXml.warning (DomException.NOT_FOUND,
- "No child with name '%s' exists in node '%s'".printf (name,
this.elem.node_name));
- return null;
- } else {
- /* xmlRemoveProp () frees the underlying Attr memory
- preventing us from returning the old attribute.
- We could just clone the GXml.Attr with it, but
- then the user would get a GXml.Attr for their old
- different that would be different from previous GXml.Attrs
- for it pre-removal (since they'd now have a clone).
-
- So, instead we're going to clone the underlying xmlNode
- and we're going to replace the existing GXmlAttr's
- underlying xmlNode with the clone, so the user sees
- the same GXmlAttr, and it has memory that wasn't freed.
- */
- xml_elem = this.elem.node;
- /* TODO: make sure xmlCopyNode is appropriate for xmlAttrs;
- xmlCopyProp didn't seem to do what we wanted */
- xml_prop_old = (Xml.Attr*)((Xml.Node*)gxml_attr_old.node)->copy (1);
- gxml_attr_old.set_xmlnode ((Xml.Node*)xml_prop_old,
gxml_attr_old.owner_document);
-
- xml_elem->has_prop (name)->remove ();
-
- return gxml_attr_old;
- }
- }
-
- public Attr? item (ulong index) {
- Xml.Attr *attr;
-
- attr = this.elem.node->properties;
- for (int i = 0; i < index && attr != null; i++) {
- attr = attr->next;
- }
-
- if (attr == null) {
- return null;
- } else {
- return this.elem.owner_document.lookup_attr (attr);
- }
- }
-
- public ulong length {
- get {
- int len = 0;
- for (Xml.Attr *attr = this.elem.node->properties; attr != null; attr =
attr->next) {
- len++;
- }
- return len;
- }
- private set {
- }
- }
-
- public Gee.Collection<Attr> get_values ()
- {
- var c = new Gee.ArrayList<Attr> ();
- for (int i =0; i < length; i++) {
- c.add (item (i));
- }
- return c;
- }
- // Gee.AbstractMap
- public override void clear () {
- foreach (string key in keys) {
- remove_named_item (key);
- }
- }
- public override new xNode @get (string key) { return get_named_item (key); }
- public override bool has (string key, xNode value) {
- var e = get_named_item (key);
- if (e == null) return false;
- if (!(value is BackedNode)) return false;
- if (((BackedNode) value).node == ((BackedNode) e).node) return true;
- if (((Attr) value).node == ((Attr) e).node) return true;
- return false;
- }
- public override bool has_key (string key) {
- if (get_named_item (key) == null) return false;
- return true;
- }
- public override Gee.MapIterator<string,xNode> map_iterator () { return new Iterator (this); }
- public override new void @set (string key, xNode value) {
- var n = get_named_item (key);
- if (n == null) return;
- remove_named_item (key);
- set_named_item ((Attr) value);
- }
- public override bool unset (string key, out xNode value = null) {
- var n = get_named_item (key);
- if (n == null) return false;
- remove_named_item (key);
- return true;
- }
- public override Gee.Set<Gee.Map.Entry<string,xNode>> entries {
- owned get {
- var s = new HashSet<Gee.Map.Entry<string,xNode>> ();
- var iter = map_iterator ();
- while (iter.next ()) {
- var v = iter.get_value ();
- var e = new Entry (iter.get_key (), v);
- s.add (e);
- }
- return s;
- }
- }
- public override Gee.Set<string> keys {
- owned get {
- var s = new HashSet<string> ();
- var iter = map_iterator ();
- while (iter.next ()) {
- s.add (iter.get_key ());
- }
- return s;
- }
- }
- public override bool read_only { get { return false; } }
- public override int size {
- get {
- var iter = map_iterator ();
- int i = 0;
- while (iter.next ()) i++;
- return i;
- }
- }
- public override Gee.Collection<xNode> values {
- owned get {
- var s = new ArrayList <xNode> ();
- var iter = map_iterator ();
- while (iter.next ()) {
- s.add (iter.get_value ());
- }
- return s;
- }
- }
- public class Entry : Gee.Map.Entry<string,xNode> {
- public Entry (string k, xNode v) {
- _key = k;
- value = v;
- }
- private string _key;
- public override string key { get { return _key; } }
- public override bool read_only { get { return true; } }
- public override xNode value { get; set; }
- }
- // Map Iterator
- private class Iterator : Object, Gee.MapIterator<string,xNode>
- {
- NamedAttrMap m;
- Xml.Attr *cur= null;
- Xml.Attr *head = null;
- public Iterator (NamedAttrMap m) {
- this.m = m;
- head = m.elem.node->properties;
- }
- public string get_key () { return cur->name; }
- public xNode get_value () { return m.get_named_item (get_key ()); }
- public bool has_next ()
- {
- if (cur == null) {
- if (head == null) return false;
- return true;
- }
- if (cur->next == null) return false;
- return true;
- }
- public bool next () {
- if (cur == null) {
- cur = head;
- return true;
- }
- if (cur->next == null) return false;
- cur = cur->next;
- return true;
- }
- public void set_value (xNode value) {
- if (!(value is Attr)) return;
- var n = m.get_named_item (get_key ());
- if (n == null) return;
- m.remove_named_item (get_key ());
- m.set_named_item ((Attr) value);
- }
- public void unset () {
- m.remove_named_item (get_key ());
- }
- public bool mutable { get { return true; } }
- public bool read_only { get { return false; } }
- public bool valid {
- get {
- if (cur == null) return false;
- return true;
- }
- }
- }
+ public abstract ulong length { get; }
}
}
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]