Browse Source

XML Parser: Fast attribute lookup using hashtable

git-svn-id: svn://svn.sharpdevelop.net/sharpdevelop/trunk@4622 1ccf3a8d-04fe-1044-b7c0-cef0b8235c61
shortcuts
David Srbecký 16 years ago
parent
commit
75b9c68567
  1. 92
      src/Libraries/AvalonEdit/ICSharpCode.AvalonEdit/XmlParser/Collections.cs
  2. 12
      src/Libraries/AvalonEdit/ICSharpCode.AvalonEdit/XmlParser/RawObjects.cs

92
src/Libraries/AvalonEdit/ICSharpCode.AvalonEdit/XmlParser/Collections.cs

@ -71,6 +71,98 @@ namespace ICSharpCode.AvalonEdit.XmlParser @@ -71,6 +71,98 @@ namespace ICSharpCode.AvalonEdit.XmlParser
}
}
/// <summary>
/// Specailized attribute collection with attribute name caching
/// </summary>
public class AttributeCollection: FilteredCollection<RawAttribute, ChildrenCollection<RawObject>>
{
/// <summary> Wrap the given collection. Non-attributes are filtered </summary>
public AttributeCollection(ChildrenCollection<RawObject> source): base(source) {}
/// <summary> Wrap the given collection. Non-attributes are filtered. Items not matching the condition are filtered. </summary>
public AttributeCollection(ChildrenCollection<RawObject> source, Predicate<object> condition): base(source, condition) {}
Dictionary<string, List<RawAttribute>> hashtable = new Dictionary<string, List<RawAttribute>>();
void AddToHashtable(RawAttribute attr)
{
string localName = attr.LocalName;
if (!hashtable.ContainsKey(localName)) {
hashtable[localName] = new List<RawAttribute>(1);
}
hashtable[localName].Add(attr);
}
void RemoveFromHashtable(RawAttribute attr)
{
string localName = attr.LocalName;
hashtable[localName].Remove(attr);
}
static List<RawAttribute> NoAttributes = new List<RawAttribute>();
/// <summary>
/// Get all attributes with given local name.
/// Hash table is used for lookup so this is cheap.
/// </summary>
public IEnumerable<RawAttribute> GetByLocalName(string localName)
{
if (hashtable.ContainsKey(localName)) {
return hashtable[localName];
} else {
return NoAttributes;
}
}
/// <inheritdoc/>
protected override void ClearItems()
{
foreach(RawAttribute item in this) {
RemoveFromHashtable(item);
item.Changing -= item_Changing;
item.Changed -= item_Changed;
}
base.ClearItems();
}
/// <inheritdoc/>
protected override void InsertItem(int index, RawAttribute item)
{
AddToHashtable(item);
item.Changing += item_Changing;
item.Changed += item_Changed;
base.InsertItem(index, item);
}
/// <inheritdoc/>
protected override void RemoveItem(int index)
{
RemoveFromHashtable(this[index]);
this[index].Changing -= item_Changing;
this[index].Changed -= item_Changed;
base.RemoveItem(index);
}
/// <inheritdoc/>
protected override void SetItem(int index, RawAttribute item)
{
throw new NotSupportedException();
}
// Every item in the collectoin should be registered to these handlers
// so that we can handle renames
void item_Changing(object sender, RawObjectEventArgs e)
{
RemoveFromHashtable((RawAttribute)e.Object);
}
void item_Changed(object sender, RawObjectEventArgs e)
{
AddToHashtable((RawAttribute)e.Object);
}
}
/// <summary>
/// Collection that presents only some items from the wrapped collection.
/// It implicitely filters object that are not of type T (or derived).

12
src/Libraries/AvalonEdit/ICSharpCode.AvalonEdit/XmlParser/RawObjects.cs

@ -672,13 +672,13 @@ namespace ICSharpCode.AvalonEdit.XmlParser @@ -672,13 +672,13 @@ namespace ICSharpCode.AvalonEdit.XmlParser
#region Helpper methods
ObservableCollection<RawAttribute> attributes;
AttributeCollection attributes;
/// <summary> Gets attributes of the element </summary>
public ObservableCollection<RawAttribute> Attributes {
public AttributeCollection Attributes {
get {
if (attributes == null) {
attributes = new FilteredCollection<RawAttribute, ChildrenCollection<RawObject>>(this.StartTag.Children);
attributes = new AttributeCollection(this.StartTag.Children);
}
return attributes;
}
@ -786,9 +786,9 @@ namespace ICSharpCode.AvalonEdit.XmlParser @@ -786,9 +786,9 @@ namespace ICSharpCode.AvalonEdit.XmlParser
public string GetAttributeValue(string @namespace, string localName)
{
@namespace = @namespace ?? string.Empty;
// TODO: More efficient
foreach(RawAttribute attr in this.Attributes) {
if (attr.LocalName == localName && attr.Namespace == @namespace) {
foreach(RawAttribute attr in this.Attributes.GetByLocalName(localName)) {
Assert(attr.LocalName == localName);
if (attr.Namespace == @namespace) {
return attr.Value;
}
}

Loading…
Cancel
Save