Hash.hx 6.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230
  1. /*
  2. * Copyright (c) 2005, The haXe Project Contributors
  3. * All rights reserved.
  4. * Redistribution and use in source and binary forms, with or without
  5. * modification, are permitted provided that the following conditions are met:
  6. *
  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. *
  13. * THIS SOFTWARE IS PROVIDED BY THE HAXE PROJECT CONTRIBUTORS "AS IS" AND ANY
  14. * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
  15. * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
  16. * DISCLAIMED. IN NO EVENT SHALL THE HAXE PROJECT CONTRIBUTORS BE LIABLE FOR
  17. * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
  18. * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
  19. * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
  20. * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
  21. * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
  22. * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
  23. * DAMAGE.
  24. */
  25. /**
  26. Hashtable over a set of elements, using [String] as keys.
  27. Other kind of keys are not possible on all platforms since they
  28. can't always be implemented efficiently.
  29. **/
  30. class Hash<T> {
  31. private var h : #if flash9 flash.utils.Dictionary #elseif php ArrayAccess<T> #else Dynamic #end;
  32. /**
  33. Creates a new empty hashtable.
  34. **/
  35. public function new() : Void {
  36. #if flash9
  37. h = new flash.utils.Dictionary();
  38. #elseif flash
  39. h = untyped __new__(_global["Object"]);
  40. #elseif neko
  41. h = untyped __dollar__hnew(0);
  42. #elseif js
  43. untyped {
  44. h = __js__("{}");
  45. if( h.__proto__ != null ) {
  46. h.__proto__ = null;
  47. __js__("delete")(h.__proto__);
  48. }
  49. }
  50. #elseif php
  51. h = untyped __call__('array');
  52. #end
  53. }
  54. /**
  55. Set a value for the given key.
  56. **/
  57. public function set( key : String, value : T ) : Void {
  58. #if flash
  59. untyped h["$"+key] = value;
  60. #elseif js
  61. untyped h["$"+key] = value;
  62. #elseif neko
  63. untyped __dollar__hset(h,key.__s,value,null);
  64. #elseif php
  65. untyped __php__("$this->h[$key] = $value");
  66. #end
  67. }
  68. /**
  69. Get a value for the given key.
  70. **/
  71. public function get( key : String ) : Null<T> {
  72. #if flash
  73. return untyped h["$"+key];
  74. #elseif js
  75. return untyped h["$"+key];
  76. #elseif neko
  77. return untyped __dollar__hget(h,key.__s,null);
  78. #elseif php
  79. if(!exists(key)) return null;
  80. return untyped h[key];
  81. #else
  82. return null;
  83. #end
  84. }
  85. /**
  86. Tells if a value exists for the given key.
  87. In particular, it's useful to tells if a key has
  88. a [null] value versus no value.
  89. **/
  90. public function exists( key : String ) : Bool {
  91. #if flash9
  92. return untyped h.hasOwnProperty("$"+key);
  93. #elseif flash
  94. return untyped h["hasOwnProperty"]("$"+key);
  95. #elseif js
  96. try {
  97. key = "$"+key;
  98. return untyped this.hasOwnProperty.call(h,key);
  99. }catch(e:Dynamic){
  100. untyped __js__("
  101. for(var i in this.h)
  102. if( i == key ) return true;
  103. ");
  104. return false;
  105. }
  106. #elseif neko
  107. return untyped __dollar__hmem(h,key.__s,null);
  108. #elseif php
  109. return untyped __php__("array_key_exists")(key, h);
  110. #else
  111. return false;
  112. #end
  113. }
  114. /**
  115. Removes a hashtable entry. Returns [true] if
  116. there was such entry.
  117. **/
  118. public function remove( key : String ) : Bool {
  119. #if flash9
  120. key = "$"+key;
  121. if( untyped !h.hasOwnProperty(key) ) return false;
  122. untyped __delete__(h,key);
  123. return true;
  124. #elseif flash
  125. key = "$"+key;
  126. if( untyped !h["hasOwnProperty"](key) ) return false;
  127. untyped __delete__(h,key);
  128. return true;
  129. #elseif js
  130. if( !exists(key) )
  131. return false;
  132. untyped __js__("delete")(h["$"+key]);
  133. return true;
  134. #elseif neko
  135. return untyped __dollar__hremove(h,key.__s,null);
  136. #elseif php
  137. return untyped __call__("_hx_array_remove_at", h, key);
  138. #else
  139. return false;
  140. #end
  141. }
  142. /**
  143. Returns an iterator of all keys in the hashtable.
  144. **/
  145. public function keys() : Iterator<String> {
  146. #if flash9
  147. return untyped (__hkeys__(h)).iterator();
  148. #elseif flash
  149. return untyped (__hkeys__(h))["iterator"]();
  150. #elseif js
  151. var a = new Array<String>();
  152. untyped __js__("
  153. for(var i in this.h)
  154. a.push(i.substr(1));
  155. ");
  156. return a.iterator();
  157. #elseif neko
  158. var l = new List<String>();
  159. untyped __dollar__hiter(h,function(k,_) { l.push(new String(k)); });
  160. return l.iterator();
  161. #elseif php
  162. return untyped __call__("_hx_array_iterator", __call__("array_keys", h));
  163. #else
  164. return null;
  165. #end
  166. }
  167. /**
  168. Returns an iterator of all values in the hashtable.
  169. **/
  170. public function iterator() : Iterator<T> {
  171. #if flash9
  172. return untyped {
  173. ref : h,
  174. it : __keys__(h).iterator(),
  175. hasNext : function() { return this.it.hasNext(); },
  176. next : function() { var i : Dynamic = this.it.next(); return this.ref[i]; }
  177. };
  178. #elseif flash
  179. return untyped {
  180. ref : h,
  181. it : __keys__(h)["iterator"](),
  182. hasNext : function() { return this.it[__unprotect__("hasNext")](); },
  183. next : function() { var i = this.it[__unprotect__("next")](); return this.ref[i]; }
  184. };
  185. #elseif js
  186. return untyped {
  187. ref : h,
  188. it : keys(),
  189. hasNext : function() { return this.it.hasNext(); },
  190. next : function() { var i = this.it.next(); return this.ref["$"+i]; }
  191. };
  192. #elseif neko
  193. var l = new List<T>();
  194. untyped __dollar__hiter(h,function(_,v) { l.push(v); });
  195. return l.iterator();
  196. #elseif php
  197. return untyped __call__("_hx_array_iterator", __call__("array_values", h));
  198. #else
  199. return null;
  200. #end
  201. }
  202. /**
  203. Returns an displayable representation of the hashtable content.
  204. **/
  205. public function toString() {
  206. var s = new StringBuf();
  207. s.add("{");
  208. var it = keys();
  209. for( i in it ) {
  210. s.add(i);
  211. s.add(" => ");
  212. s.add(Std.string(get(i)));
  213. if( it.hasNext() )
  214. s.add(", ");
  215. }
  216. s.add("}");
  217. return s.toString();
  218. }
  219. }