PageRenderTime 44ms CodeModel.GetById 17ms RepoModel.GetById 0ms app.codeStats 0ms

/Languages/IronPython/IronPython/Runtime/Types/DictProxy.cs

http://github.com/IronLanguages/main
C# | 322 lines | 234 code | 74 blank | 14 comment | 17 complexity | 2cacea523348fcdec0eee6dc17df2e7b MD5 | raw file
Possible License(s): CPL-1.0, BSD-3-Clause, ISC, GPL-2.0, MPL-2.0-no-copyleft-exception
  1. /* ****************************************************************************
  2. *
  3. * Copyright (c) Microsoft Corporation.
  4. *
  5. * This source code is subject to terms and conditions of the Apache License, Version 2.0. A
  6. * copy of the license can be found in the License.html file at the root of this distribution. If
  7. * you cannot locate the Apache License, Version 2.0, please send an email to
  8. * dlr@microsoft.com. By using this source code in any fashion, you are agreeing to be bound
  9. * by the terms of the Apache License, Version 2.0.
  10. *
  11. * You must not remove this notice, or any other, from this software.
  12. *
  13. *
  14. * ***************************************************************************/
  15. using System;
  16. using System.Collections;
  17. using System.Collections.Generic;
  18. using System.Diagnostics;
  19. using System.Linq;
  20. using System.Runtime.InteropServices;
  21. using IronPython.Runtime.Operations;
  22. using Microsoft.Scripting.Runtime;
  23. using Microsoft.Scripting.Utils;
  24. namespace IronPython.Runtime.Types {
  25. [PythonType("dictproxy")]
  26. public class DictProxy : IDictionary, IEnumerable, IDictionary<object, object> {
  27. private readonly PythonType/*!*/ _dt;
  28. public DictProxy(PythonType/*!*/ dt) {
  29. Debug.Assert(dt != null);
  30. _dt = dt;
  31. }
  32. #region Python Public API Surface
  33. public int __len__(CodeContext context) {
  34. return _dt.GetMemberDictionary(context, false).Count;
  35. }
  36. public bool __contains__(CodeContext/*!*/ context, object value) {
  37. return has_key(context, value);
  38. }
  39. public string/*!*/ __str__(CodeContext/*!*/ context) {
  40. return DictionaryOps.__repr__(context, this);
  41. }
  42. public bool has_key(CodeContext/*!*/ context, object key) {
  43. object dummy;
  44. return TryGetValue(context, key, out dummy);
  45. }
  46. public object get(CodeContext/*!*/ context, [NotNull]object k, [DefaultParameterValue(null)]object d) {
  47. object res;
  48. if (!TryGetValue(context, k, out res)) {
  49. res = d;
  50. }
  51. return res;
  52. }
  53. public object keys(CodeContext context) {
  54. return _dt.GetMemberDictionary(context, false).keys();
  55. }
  56. public object values(CodeContext context) {
  57. return _dt.GetMemberDictionary(context, false).values();
  58. }
  59. public List items(CodeContext context) {
  60. return _dt.GetMemberDictionary(context, false).items();
  61. }
  62. public PythonDictionary copy(CodeContext/*!*/ context) {
  63. return new PythonDictionary(context, this);
  64. }
  65. public IEnumerator iteritems(CodeContext/*!*/ context) {
  66. return new DictionaryItemEnumerator(_dt.GetMemberDictionary(context, false)._storage);
  67. }
  68. public IEnumerator iterkeys(CodeContext/*!*/ context) {
  69. return new DictionaryKeyEnumerator(_dt.GetMemberDictionary(context, false)._storage);
  70. }
  71. public IEnumerator itervalues(CodeContext/*!*/ context) {
  72. return new DictionaryValueEnumerator(_dt.GetMemberDictionary(context, false)._storage);
  73. }
  74. #endregion
  75. #region Object overrides
  76. public override bool Equals(object obj) {
  77. DictProxy proxy = obj as DictProxy;
  78. if (proxy == null) return false;
  79. return proxy._dt == _dt;
  80. }
  81. public override int GetHashCode() {
  82. return ~_dt.GetHashCode();
  83. }
  84. #endregion
  85. #region IDictionary Members
  86. public object this[object key] {
  87. get {
  88. return GetIndex(DefaultContext.Default, key);
  89. }
  90. [PythonHidden]
  91. set {
  92. throw PythonOps.TypeError("cannot assign to dictproxy");
  93. }
  94. }
  95. bool IDictionary.Contains(object key) {
  96. return has_key(DefaultContext.Default, key);
  97. }
  98. #endregion
  99. #region IEnumerable Members
  100. System.Collections.IEnumerator IEnumerable.GetEnumerator() {
  101. return DictionaryOps.iterkeys(_dt.GetMemberDictionary(DefaultContext.Default, false));
  102. }
  103. #endregion
  104. #region IDictionary Members
  105. [PythonHidden]
  106. public void Add(object key, object value) {
  107. this[key] = value;
  108. }
  109. [PythonHidden]
  110. public void Clear() {
  111. throw new InvalidOperationException("dictproxy is read-only");
  112. }
  113. IDictionaryEnumerator IDictionary.GetEnumerator() {
  114. return new PythonDictionary.DictEnumerator(_dt.GetMemberDictionary(DefaultContext.Default, false).GetEnumerator());
  115. }
  116. bool IDictionary.IsFixedSize {
  117. get { return true; }
  118. }
  119. bool IDictionary.IsReadOnly {
  120. get { return true; }
  121. }
  122. ICollection IDictionary.Keys {
  123. get {
  124. ICollection<object> res = _dt.GetMemberDictionary(DefaultContext.Default, false).Keys;
  125. ICollection coll = res as ICollection;
  126. if (coll != null) {
  127. return coll;
  128. }
  129. return new List<object>(res);
  130. }
  131. }
  132. void IDictionary.Remove(object key) {
  133. throw new InvalidOperationException("dictproxy is read-only");
  134. }
  135. ICollection IDictionary.Values {
  136. get {
  137. List<object> res = new List<object>();
  138. foreach (KeyValuePair<object, object> kvp in _dt.GetMemberDictionary(DefaultContext.Default, false)) {
  139. res.Add(kvp.Value);
  140. }
  141. return res;
  142. }
  143. }
  144. #endregion
  145. #region ICollection Members
  146. void ICollection.CopyTo(Array array, int index) {
  147. foreach (DictionaryEntry de in (IDictionary)this) {
  148. array.SetValue(de, index++);
  149. }
  150. }
  151. int ICollection.Count {
  152. get { return __len__(DefaultContext.Default); }
  153. }
  154. bool ICollection.IsSynchronized {
  155. get { return false; }
  156. }
  157. object ICollection.SyncRoot {
  158. get { return this; }
  159. }
  160. #endregion
  161. #region IDictionary<object,object> Members
  162. bool IDictionary<object, object>.ContainsKey(object key) {
  163. return has_key(DefaultContext.Default, key);
  164. }
  165. ICollection<object> IDictionary<object, object>.Keys {
  166. get {
  167. return _dt.GetMemberDictionary(DefaultContext.Default, false).Keys;
  168. }
  169. }
  170. bool IDictionary<object, object>.Remove(object key) {
  171. throw new InvalidOperationException("dictproxy is read-only");
  172. }
  173. bool IDictionary<object, object>.TryGetValue(object key, out object value) {
  174. return TryGetValue(DefaultContext.Default, key, out value);
  175. }
  176. ICollection<object> IDictionary<object, object>.Values {
  177. get {
  178. return _dt.GetMemberDictionary(DefaultContext.Default, false).Values;
  179. }
  180. }
  181. #endregion
  182. #region ICollection<KeyValuePair<object,object>> Members
  183. void ICollection<KeyValuePair<object, object>>.Add(KeyValuePair<object, object> item) {
  184. this[item.Key] = item.Value;
  185. }
  186. bool ICollection<KeyValuePair<object, object>>.Contains(KeyValuePair<object, object> item) {
  187. return has_key(DefaultContext.Default, item.Key);
  188. }
  189. void ICollection<KeyValuePair<object, object>>.CopyTo(KeyValuePair<object, object>[] array, int arrayIndex) {
  190. foreach (KeyValuePair<object, object> de in (IEnumerable<KeyValuePair<object, object>>)this) {
  191. array.SetValue(de, arrayIndex++);
  192. }
  193. }
  194. int ICollection<KeyValuePair<object, object>>.Count {
  195. get { return __len__(DefaultContext.Default); }
  196. }
  197. bool ICollection<KeyValuePair<object, object>>.IsReadOnly {
  198. get { return true; }
  199. }
  200. bool ICollection<KeyValuePair<object, object>>.Remove(KeyValuePair<object, object> item) {
  201. return ((IDictionary<object, object>)this).Remove(item.Key);
  202. }
  203. #endregion
  204. #region IEnumerable<KeyValuePair<object,object>> Members
  205. IEnumerator<KeyValuePair<object, object>> IEnumerable<KeyValuePair<object, object>>.GetEnumerator() {
  206. return _dt.GetMemberDictionary(DefaultContext.Default, false).GetEnumerator();
  207. }
  208. #endregion
  209. #region Internal implementation details
  210. private object GetIndex(CodeContext context, object index) {
  211. string strIndex = index as string;
  212. if (strIndex != null) {
  213. PythonTypeSlot dts;
  214. if (_dt.TryLookupSlot(context, strIndex, out dts)) {
  215. PythonTypeUserDescriptorSlot uds = dts as PythonTypeUserDescriptorSlot;
  216. if (uds != null) {
  217. return uds.Value;
  218. }
  219. return dts;
  220. }
  221. }
  222. throw PythonOps.KeyError(index.ToString());
  223. }
  224. private bool TryGetValue(CodeContext/*!*/ context, object key, out object value) {
  225. string strIndex = key as string;
  226. if (strIndex != null) {
  227. PythonTypeSlot dts;
  228. if (_dt.TryLookupSlot(context, strIndex, out dts)) {
  229. PythonTypeUserDescriptorSlot uds = dts as PythonTypeUserDescriptorSlot;
  230. if (uds != null) {
  231. value = uds.Value;
  232. return true;
  233. }
  234. value = dts;
  235. return true;
  236. }
  237. }
  238. value = null;
  239. return false;
  240. }
  241. internal PythonType Type {
  242. get {
  243. return _dt;
  244. }
  245. }
  246. #endregion
  247. }
  248. }