PageRenderTime 57ms CodeModel.GetById 11ms RepoModel.GetById 0ms app.codeStats 1ms

/dotmars/base/variant.d

http://dotmars.googlecode.com/
D | 231 lines | 178 code | 37 blank | 16 comment | 30 complexity | efc8dafcd270be6ac3383df75c5af931 MD5 | raw file
  1. /** Module: variant.d: A stack-based variant implemention
  2. Written in the D programming language 1.0
  3. Authors: Wei Li <oldrev@gmail.com>
  4. Copyright: Copyright (C) 2007 Wei Li.
  5. License: BSD
  6. */
  7. module dotmars.base.variant;
  8. import dotmars.base.tuple;
  9. import dotmars.base.stdexcept;
  10. private template MaxSizeImp(T, V...)
  11. {
  12. static if(V.length > 0)
  13. private const int tailResult = MaxSizeImp!(V).result;
  14. else
  15. private const int tailResult = T.sizeof;
  16. public const int result = T.sizeof > tailResult ? T.sizeof : tailResult;
  17. };
  18. private template MaxSize(TList...)
  19. {
  20. const int MaxSize = MaxSizeImp!(TList).result;
  21. }
  22. /**
  23. A Variant implemention inspired by boost.variant
  24. */
  25. struct Variant(TList...)
  26. {
  27. //ensure void was not in the TList
  28. static assert( IndexOf!(void, TList) < 0, "Error: Invalid type in the TList");
  29. public alias TList TypeList;
  30. public alias Variant!(TypeList) SelfType;
  31. private alias ubyte[MaxSize!(TypeList)] Holder;
  32. private Holder m_held;
  33. private int m_which = -1;
  34. template indexof(T)
  35. {
  36. const int indexof = IndexOf!(T, TypeList);
  37. }
  38. public static SelfType opCall(ValueType)(ValueType val)
  39. {
  40. SelfType var;
  41. var.opAssign!(ValueType)(val);
  42. return var;
  43. }
  44. public int which()
  45. {
  46. return m_which;
  47. }
  48. public ValueType opAssign(ValueType)(ValueType rhs)
  49. {
  50. const auto i = IndexOf!(ValueType, TypeList);
  51. static assert(i >= 0);
  52. ValueType* heldPtr = cast(ValueType*)m_held.ptr;
  53. *heldPtr = rhs;
  54. m_which = i;
  55. return rhs;
  56. }
  57. public bool opEquals(ValueType)(ValueType rhs)
  58. {
  59. assert(!empty);
  60. static if(is(ValueType == SelfType))
  61. {
  62. foreach(T; TypeList)
  63. {
  64. const int i = IndexOf!(T, TypeList);
  65. if(i == which)
  66. {
  67. return (rhs.which == which) && (get!(T) == rhs.get!(T));
  68. }
  69. }
  70. }
  71. else
  72. {
  73. const int i = IndexOf!(ValueType, TypeList);
  74. static assert(i >= 0);
  75. return get!(ValueType)() == rhs;
  76. }
  77. }
  78. public int opCmp(ValueType)(ValueType rhs) //used for hash or something else
  79. out(result)
  80. {
  81. assert(result == 0 || result == 1 || result == -1);
  82. }
  83. body
  84. {
  85. if(rhs == *this)return 0;
  86. static if(is(ValueType == SelfType))
  87. {
  88. foreach(T; TypeList)
  89. {
  90. const int i = IndexOf!(T, TypeList);
  91. if((i == which) && (rhs.which == which))
  92. {
  93. return get!(T) < rhs.get!(T) ? -1 : 1;
  94. }
  95. }
  96. }
  97. else
  98. {
  99. const int i = IndexOf!(ValueType, TypeList);
  100. static assert(i >= 0);
  101. return get!(ValueType)() < rhs ? -1 : 1;
  102. }
  103. }
  104. public TypeInfo type()
  105. {
  106. if(which < 0)return typeid(void);
  107. foreach(T; TypeList)
  108. {
  109. const int i = IndexOf!(T, TypeList);
  110. if(i == which)
  111. {
  112. return typeid(TypeList[i]);
  113. }
  114. }
  115. }
  116. public ValueType get(ValueType)()
  117. {
  118. if(indexof!(ValueType) != which)
  119. throw new BadCastException("Invalid type");
  120. return *(cast(ValueType*)m_held.ptr);
  121. }
  122. //An nice name stolen from std.variant
  123. public ValueType* peek(ValueType)()
  124. {
  125. //hey, I say again, we need the ref!
  126. if(indexof!(ValueType) != which)
  127. return null;
  128. return cast(ValueType*)m_held.ptr;
  129. }
  130. public bool empty()
  131. {
  132. return m_which < 0;
  133. }
  134. public void swap(inout SelfType var)
  135. {
  136. Holder h;
  137. h[] = m_held[];
  138. int w = which;
  139. m_held[] = var.m_held[];
  140. m_which = var.which;
  141. var.m_held[] = h[];
  142. var.m_which = w;
  143. }
  144. public hash_t toHash()
  145. {
  146. return type.getHash(m_held.ptr);
  147. }
  148. //TODO: Make it sense.
  149. public string toString()
  150. {
  151. return "variant";
  152. }
  153. //overloading for arithmetic operators, copied from Tango :)
  154. typeof(T+T) opAdd(T)( T rhs ) { return get!(T) + rhs; }
  155. typeof(T+T) opAdd_r(T)( T lhs ) { return lhs + get!(T); }
  156. typeof(T-T) opSub(T)( T rhs ) { return get!(T) - rhs; }
  157. typeof(T-T) opSub_r(T)( T lhs ) { return lhs - get!(T); }
  158. typeof(T*T) opMul(T)( T rhs ) { return get!(T) * rhs; }
  159. typeof(T*T) opMul_r(T)( T lhs ) { return lhs * get!(T); }
  160. typeof(T/T) opDiv(T)( T rhs ) { return get!(T) / rhs; }
  161. typeof(T/T) opDiv_r(T)( T lhs ) { return lhs / get!(T); }
  162. typeof(T%T) opMod(T)( T rhs ) { return get!(T) % rhs; }
  163. typeof(T%T) opMod_r(T)( T lhs ) { return lhs % get!(T); }
  164. typeof(T&T) opAnd(T)( T rhs ) { return get!(T) & rhs; }
  165. typeof(T&T) opAnd_r(T)( T lhs ) { return lhs & get!(T); }
  166. typeof(T|T) opOr(T)( T rhs ) { return get!(T) | rhs; }
  167. typeof(T|T) opOr_r(T)( T lhs ) { return lhs | get!(T); }
  168. typeof(T^T) opXor(T)( T rhs ) { return get!(T) ^ rhs; }
  169. typeof(T^T) opXor_r(T)( T lhs ) { return lhs ^ get!(T); }
  170. typeof(T<<T) opShl(T)( T rhs ) { return get!(T) << rhs; }
  171. typeof(T<<T) opShl_r(T)( T lhs ) { return lhs << get!(T); }
  172. typeof(T>>T) opShr(T)( T rhs ) { return get!(T) >> rhs; }
  173. typeof(T>>T) opShr_r(T)( T lhs ) { return lhs >> get!(T); }
  174. typeof(T>>>T) opUShr(T)( T rhs ) { return get!(T) >>> rhs; }
  175. typeof(T>>>T) opUShr_r(T)( T lhs ) { return lhs >>> get!(T); }
  176. typeof(T~T) opCat(T)( T rhs ) { return get!(T) ~ rhs; }
  177. typeof(T~T) opCat_r(T)( T lhs ) { return lhs ~ get!(T); }
  178. T opAddAssign(T)( T rhs ) { return (*this = get!(T) + rhs); }
  179. T opSubAssign(T)( T rhs ) { return (*this = get!(T) - rhs); }
  180. T opMulAssign(T)( T rhs ) { return (*this = get!(T) * rhs); }
  181. T opDivAssign(T)( T rhs ) { return (*this = get!(T) / rhs); }
  182. T opModAssign(T)( T rhs ) { return (*this = get!(T) % rhs); }
  183. T opAndAssign(T)( T rhs ) { return (*this = get!(T) & rhs); }
  184. T opOrAssign(T)( T rhs ) { return (*this = get!(T) | rhs); }
  185. T opXorAssign(T)( T rhs ) { return (*this = get!(T) ^ rhs); }
  186. T opShlAssign(T)( T rhs ) { return (*this = get!(T) << rhs); }
  187. T opShrAssign(T)( T rhs ) { return (*this = get!(T) >> rhs); }
  188. T opUShrAssign(T)( T rhs ) { return (*this = get!(T) >>> rhs); }
  189. T opCatAssign(T)( T rhs ) { return (*this = get!(T) ~ rhs); }
  190. T opIndex(T, K)(K key) { return get!(T)[key]; }
  191. T opIndexAssign(T, K)(T rhs, K key) { return get!(T)[key] = rhs; }
  192. }