dmay / xmlrpcnet

Automatically exported from code.google.com/p/xmlrpcnet
0 stars 0 forks source link

Maintain XML-RPC struct member ordering in XmlRpcStruct #56

Closed GoogleCodeExporter closed 9 years ago

GoogleCodeExporter commented 9 years ago
XmlRpcStruct derives from Hashtable and so the ordering of the entries in
the collection depends on the hash value of each entry.

The XML-RPC spec doesn't say anything about the ordering of members in an
XML-RPC struct value but it is generally assumed that no ordering is
implied and struct is represented as a dictionary type of collection. But I
suppose you could argue that the ordering should correspond to that in the
XML-RPC struct. I just wrote the version of XmlRpcStruct.cs below which
implements the enumerator so the ordering is preserved. I've not fully
tested it but it could be a starting point for what you need. I'll add an
enhancement request to add this to the library later.

using System;
using System.Collections;

namespace CookComputing.XmlRpc
{
public class XmlRpcStruct : Hashtable
{
private ArrayList _keys = new ArrayList();
private ArrayList _values = new ArrayList();

public override void Add(object key, object value)
{
if (!(key is string))
{
throw new ArgumentException("XmlRpcStruct key must be a string.");
}
if (XmlRpcServiceInfo.GetXmlRpcType(value.GetType())
== XmlRpcType.tInvalid)
{
throw new ArgumentException(String.Format(
"Type {0} cannot be mapped to an XML-RPC type", value.GetType()));
}
base.Add(key, value);
_keys.Add(key);
_values.Add(value);
}

public override object this[object key]
{
get
{
return base[key];
}
set
{
if (!(key is string))
{
throw new ArgumentException("XmlRpcStruct key must be a string.");
}
if (XmlRpcServiceInfo.GetXmlRpcType(value.GetType())
== XmlRpcType.tInvalid)
{
throw new ArgumentException(String.Format(
"Type {0} cannot be mapped to an XML-RPC type", value.GetType()));
}
base[key] = value;
}
}

public override bool Equals(Object obj)
{
if (obj.GetType() != typeof(XmlRpcStruct))
return false;
XmlRpcStruct xmlRpcStruct = (XmlRpcStruct)obj;
if (this.Keys.Count != xmlRpcStruct.Count)
return false;
foreach (String key in this.Keys)
{
if (!xmlRpcStruct.ContainsKey(key))
return false;
if (!this[key].Equals(xmlRpcStruct[key]))
return false;
}
return true;
}

public override int GetHashCode()
{
int hash = 0;
foreach (object obj in Values)
{
hash ^= obj.GetHashCode();
}
return hash;
}

public override void Clear()
{
base.Clear();
_keys.Clear();
_values.Clear();
}

public override IDictionaryEnumerator GetEnumerator()
{
return new XmlRpcStruct.Enumerator(_keys, _values);
}

public override ICollection Keys
{
get
{
return _keys;
}
}

public override void Remove(object key)
{
base.Remove(key);
int idx = _keys.IndexOf(key);
if (idx >= 0)
{
_keys.RemoveAt(idx);
_values.RemoveAt(idx);
}
}

public override ICollection Values
{
get
{
return _values;
}
}

private class Enumerator : IDictionaryEnumerator
{
private ArrayList _keys;
private ArrayList _values;
private int _index;

public Enumerator(ArrayList keys, ArrayList values)
{
_keys = keys;
_values = values;
_index = -1;
}

public void Reset()
{
_index = -1;
}

public object Current
{
get { return new DictionaryEntry(_keys[_index], _values[_index]); }
}

public bool MoveNext()
{
_index++;
if (_index >= _keys.Count)
return false;
else
return true;
}

public DictionaryEntry Entry
{
get { return new DictionaryEntry(_keys[_index], _values[_index]); }
}

public object Key
{
get { return _keys[_index]; }
}

public object Value
{
get { return _values[_index]; }

}
}
}
}

Original issue reported on code.google.com by ChasC...@gmail.com on 3 Aug 2009 at 8:45

GoogleCodeExporter commented 9 years ago
Implemented in revisions 106 (branch 2.4) and 107 (trunk).

Original comment by ChasC...@gmail.com on 6 Aug 2009 at 8:40

GoogleCodeExporter commented 9 years ago

Original comment by ChasC...@gmail.com on 6 Aug 2009 at 8:41