PageRenderTime 42ms CodeModel.GetById 21ms RepoModel.GetById 0ms app.codeStats 0ms

/source/library/Interlace/Erlang/ErlangDictionary.cs

https://bitbucket.org/VahidN/interlace
C# | 229 lines | 153 code | 49 blank | 27 comment | 23 complexity | 20d2ab8730ad5b823fa00688a42166b3 MD5 | raw file
  1. #region Using Directives and Copyright Notice
  2. // Copyright (c) 2007-2010, Computer Consultancy Pty Ltd
  3. // All rights reserved.
  4. //
  5. // Redistribution and use in source and binary forms, with or without
  6. // modification, are permitted provided that the following conditions are met:
  7. // * Redistributions of source code must retain the above copyright
  8. // notice, this list of conditions and the following disclaimer.
  9. // * Redistributions in binary form must reproduce the above copyright
  10. // notice, this list of conditions and the following disclaimer in the
  11. // documentation and/or other materials provided with the distribution.
  12. // * Neither the name of the Computer Consultancy Pty Ltd nor the
  13. // names of its contributors may be used to endorse or promote products
  14. // derived from this software without specific prior written permission.
  15. //
  16. // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
  17. // AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
  18. // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
  19. // ARE DISCLAIMED. IN NO EVENT SHALL COMPUTER CONSULTANCY PTY LTD BE LIABLE
  20. // FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
  21. // DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
  22. // SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
  23. // CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
  24. // LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
  25. // OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
  26. // DAMAGE.
  27. using System;
  28. using System.Collections.Generic;
  29. using System.Text;
  30. #endregion
  31. namespace Interlace.Erlang
  32. {
  33. public class ErlangDictionary : ITermWritable
  34. {
  35. Dictionary<string, object> _values;
  36. public ErlangDictionary()
  37. {
  38. _values = new Dictionary<string, object>();
  39. }
  40. public ErlangDictionary(object dictionaryTuples)
  41. {
  42. if (!(dictionaryTuples is List<object>))
  43. {
  44. throw new ErlangProtocolException(
  45. "A list of options was expected but some term other than a list was found.");
  46. }
  47. List<object> dictionaryTuplesList = dictionaryTuples as List<object>;
  48. _values = new Dictionary<string, object>(dictionaryTuplesList.Count);
  49. foreach (object tupleObject in dictionaryTuplesList)
  50. {
  51. if (!(tupleObject is Tuple))
  52. {
  53. throw new ErlangProtocolException(
  54. "A list of options was expected but an element in the list is not a tuple.");
  55. }
  56. Tuple tuple = tupleObject as Tuple;
  57. if (tuple.Length != 2)
  58. {
  59. throw new ErlangProtocolException(
  60. "A tuple in an option list is expected to have two elements, and one was " +
  61. "found with fewer or more than two items.");
  62. }
  63. Atom key = tuple.AtomAt(0);
  64. object value = tuple.ObjectAt(1);
  65. _values[key.Value] = value;
  66. }
  67. }
  68. public object this[string key]
  69. {
  70. get { return _values[key]; }
  71. set { _values[key] = value; }
  72. }
  73. T InternalAt<T>(string atom)
  74. {
  75. if (!_values.ContainsKey(atom)) throw new ErlangProtocolException(string.Format(
  76. "A list of options was expected to contain an option \"{0}\", but did not.",
  77. atom));
  78. if (typeof(T).Equals(typeof(string)) && _values[atom] is List<object>)
  79. {
  80. List<object> list = _values[atom] as List<object>;
  81. if (list.Count == 0) return (T)(object)"";
  82. }
  83. if (!(_values[atom] is T)) throw new ErlangProtocolException(string.Format(
  84. "The option value for option {0} of an option list is not the correct type."));
  85. return (T)_values[atom];
  86. }
  87. public Tuple TupleAt(string atom)
  88. {
  89. return InternalAt<Tuple>(atom);
  90. }
  91. public string StringAt(string atom)
  92. {
  93. return InternalAt<string>(atom);
  94. }
  95. public int IntegerAt(string atom)
  96. {
  97. return InternalAt<int>(atom);
  98. }
  99. public Atom AtomAt(string atom)
  100. {
  101. return InternalAt<Atom>(atom);
  102. }
  103. public object ObjectAt(string atom)
  104. {
  105. return InternalAt<object>(atom);
  106. }
  107. T InternalAt<T>(string atom, T defaultValue)
  108. {
  109. if (!_values.ContainsKey(atom)) return defaultValue;
  110. if (typeof(T).Equals(typeof(string)) && _values[atom] is List<object>)
  111. {
  112. List<object> list = _values[atom] as List<object>;
  113. if (list.Count == 0) return (T)(object)"";
  114. }
  115. if (!(_values[atom] is T)) throw new ErlangProtocolException(string.Format(
  116. "The option value for option {0} of an option list is not the correct type."));
  117. return (T)_values[atom];
  118. }
  119. public Tuple TupleAt(string atom, Tuple defaultValue)
  120. {
  121. return InternalAt<Tuple>(atom, defaultValue);
  122. }
  123. public string StringAt(string atom, string defaultValue)
  124. {
  125. return InternalAt<string>(atom, defaultValue);
  126. }
  127. public int IntegerAt(string atom, int defaultValue)
  128. {
  129. return InternalAt<int>(atom, defaultValue);
  130. }
  131. public Atom AtomAt(string atom, Atom defaultValue)
  132. {
  133. return InternalAt<Atom>(atom, defaultValue);
  134. }
  135. public object ObjectAt(string atom, object defaultValue)
  136. {
  137. return InternalAt<object>(atom, defaultValue);
  138. }
  139. #region ITermWritable Members
  140. public object SerializeToTerms()
  141. {
  142. List<object> tuples = new List<object>();
  143. foreach (KeyValuePair<string, object> pair in _values)
  144. {
  145. tuples.Add(new Tuple(Atom.From(pair.Key), pair.Value));
  146. }
  147. return tuples;
  148. }
  149. #endregion
  150. public override bool Equals(object obj)
  151. {
  152. ErlangDictionary rhs = obj as ErlangDictionary;
  153. if (rhs == null) return false;
  154. // All of the names in the lhs should be in the rhs, and the values equal:
  155. foreach (string lhsName in _values.Keys)
  156. {
  157. if (!rhs._values.ContainsKey(lhsName)) return false;
  158. if (!object.Equals(_values[lhsName], rhs._values[lhsName])) return false;
  159. }
  160. // All of the names in the rhs should be in the lhs if they are equal:
  161. foreach (string rhsName in rhs._values.Keys)
  162. {
  163. if (!_values.ContainsKey(rhsName)) return false;
  164. }
  165. return true;
  166. }
  167. public override int GetHashCode()
  168. {
  169. int hashCode = 0;
  170. List<string> keys = new List<string>(_values.Keys);
  171. keys.Sort();
  172. foreach (string key in keys)
  173. {
  174. hashCode ^= key.GetHashCode();
  175. if (_values[key] != null) hashCode ^= _values[key].GetHashCode();
  176. }
  177. return hashCode;
  178. }
  179. }
  180. }