PageRenderTime 43ms CodeModel.GetById 17ms RepoModel.GetById 1ms app.codeStats 0ms

/source/library/Interlace/Collections/CactusStack.cs

https://bitbucket.org/VahidN/interlace
C# | 231 lines | 153 code | 49 blank | 29 comment | 31 complexity | edfa86b60d57d9d69f0883814ccc65a0 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.Collections
  32. {
  33. /// <summary>
  34. /// An immutable cactus stack; see http://www.nist.gov/dads/HTML/cactusstack.html for details.
  35. /// </summary>
  36. /// <typeparam name="T">The type stored in the stack.</typeparam>
  37. public class CactusStack<T>
  38. {
  39. T _value;
  40. CactusStack<T> _parent;
  41. public CactusStack(T value)
  42. {
  43. _value = value;
  44. _parent = null;
  45. }
  46. CactusStack(CactusStack<T> parent, T value)
  47. {
  48. _value = value;
  49. _parent = parent;
  50. }
  51. public CactusStack<T> Push(T value)
  52. {
  53. return new CactusStack<T>(this, value);
  54. }
  55. public T Value
  56. {
  57. get { return _value; }
  58. }
  59. public CactusStack<T> Parent
  60. {
  61. get { return _parent; }
  62. }
  63. public IEnumerable<T> ValuesInReverse
  64. {
  65. get
  66. {
  67. CactusStack<T> current = this;
  68. while (current != null)
  69. {
  70. yield return current.Value;
  71. current = current.Parent;
  72. }
  73. }
  74. }
  75. public IEnumerable<CactusStack<T>> StackedValues
  76. {
  77. get
  78. {
  79. CactusStack<T> current = this;
  80. while (current != null)
  81. {
  82. yield return current;
  83. current = current.Parent;
  84. }
  85. }
  86. }
  87. public CactusStack<T> Reversed
  88. {
  89. get
  90. {
  91. CactusStack<T> top = new CactusStack<T>(_value);
  92. CactusStack<T> current = _parent;
  93. while (current != null)
  94. {
  95. top = top.Push(current.Value);
  96. current = current.Parent;
  97. }
  98. return top;
  99. }
  100. }
  101. public int Count
  102. {
  103. get
  104. {
  105. CactusStack<T> current = this;
  106. int count = 0;
  107. while (current != null)
  108. {
  109. count++;
  110. current = current.Parent;
  111. }
  112. return count;
  113. }
  114. }
  115. public IEnumerable<T> Values
  116. {
  117. get
  118. {
  119. T[] values = new T[Count];
  120. int i = values.Length - 1;
  121. CactusStack<T> current = this;
  122. while (current != null)
  123. {
  124. values[i] = current.Value;
  125. i--;
  126. current = current.Parent;
  127. }
  128. return values;
  129. }
  130. }
  131. public override string ToString()
  132. {
  133. StringBuilder result = new StringBuilder();
  134. CactusStack<T> current = this;
  135. result.Append("[CactusStack, top first: ");
  136. while (current != null)
  137. {
  138. if (current._value != null)
  139. {
  140. result.Append(current._value.ToString());
  141. }
  142. else
  143. {
  144. result.Append("(null)");
  145. }
  146. if (current.Parent != null) result.Append(", ");
  147. current = current.Parent;
  148. }
  149. result.Append("]");
  150. return result.ToString();
  151. }
  152. public override bool Equals(object obj)
  153. {
  154. CactusStack<T> currentLeft = this;
  155. CactusStack<T> currentRight = obj as CactusStack<T>;
  156. if (currentRight == null) return false;
  157. do
  158. {
  159. if (!object.Equals(currentLeft._value, currentRight._value)) return false;
  160. currentLeft = currentLeft._parent;
  161. currentRight = currentRight._parent;
  162. if ((currentLeft == null) != (currentRight == null))
  163. {
  164. return false;
  165. }
  166. }
  167. while (currentLeft != null && currentRight != null);
  168. return true;
  169. }
  170. public override int GetHashCode()
  171. {
  172. int hashCode = 0;
  173. CactusStack<T> current = this;
  174. while (current != null)
  175. {
  176. if (current._value != null) hashCode ^= current._value.GetHashCode();
  177. current = current.Parent;
  178. }
  179. return hashCode;
  180. }
  181. }
  182. }