StringMap.hx 3.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148
  1. /*
  2. * Copyright (C)2005-2017 Haxe Foundation
  3. *
  4. * Permission is hereby granted, free of charge, to any person obtaining a
  5. * copy of this software and associated documentation files (the "Software"),
  6. * to deal in the Software without restriction, including without limitation
  7. * the rights to use, copy, modify, merge, publish, distribute, sublicense,
  8. * and/or sell copies of the Software, and to permit persons to whom the
  9. * Software is furnished to do so, subject to the following conditions:
  10. *
  11. * The above copyright notice and this permission notice shall be included in
  12. * all copies or substantial portions of the Software.
  13. *
  14. * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  15. * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  16. * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
  17. * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
  18. * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
  19. * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
  20. * DEALINGS IN THE SOFTWARE.
  21. */
  22. package haxe.ds;
  23. private class StringMapIterator<T> {
  24. var map : StringMap<T>;
  25. var keys : Array<String>;
  26. var index : Int;
  27. var count : Int;
  28. public inline function new(map:StringMap<T>, keys:Array<String>) {
  29. this.map = map;
  30. this.keys = keys;
  31. this.index = 0;
  32. this.count = keys.length;
  33. }
  34. public inline function hasNext() {
  35. return index < count;
  36. }
  37. public inline function next() {
  38. return map.get(keys[index++]);
  39. }
  40. }
  41. @:coreApi class StringMap<T> implements haxe.Constraints.IMap<String,T> {
  42. private var h : Dynamic;
  43. private var rh : Dynamic;
  44. public inline function new() : Void {
  45. h = {};
  46. }
  47. inline function isReserved(key:String) : Bool {
  48. return untyped __js__("__map_reserved")[key] != null;
  49. }
  50. public inline function set( key : String, value : T ) : Void {
  51. if( isReserved(key) )
  52. setReserved(key, value);
  53. else
  54. h[cast key] = value;
  55. }
  56. public inline function get( key : String ) : Null<T> {
  57. if( isReserved(key) )
  58. return getReserved(key);
  59. return h[cast key];
  60. }
  61. public inline function exists( key : String ) : Bool {
  62. if( isReserved(key) )
  63. return existsReserved(key);
  64. return h.hasOwnProperty(key);
  65. }
  66. function setReserved( key : String, value : T ) : Void {
  67. if( rh == null ) rh = {};
  68. rh[cast "$"+key] = value;
  69. }
  70. function getReserved( key : String ) : Null<T> {
  71. return rh == null ? null : rh[cast "$"+key];
  72. }
  73. function existsReserved( key : String ) : Bool {
  74. if( rh == null ) return false;
  75. return untyped rh.hasOwnProperty("$"+key);
  76. }
  77. public function remove( key : String ) : Bool {
  78. if( isReserved(key) ) {
  79. key = "$" + key;
  80. if( rh == null || !rh.hasOwnProperty(key) ) return false;
  81. untyped __js__("delete")(rh[key]);
  82. return true;
  83. } else {
  84. if( !h.hasOwnProperty(key) )
  85. return false;
  86. untyped __js__("delete")(h[key]);
  87. return true;
  88. }
  89. }
  90. public function keys() : Iterator<String> {
  91. return arrayKeys().iterator();
  92. }
  93. function arrayKeys() : Array<String> {
  94. var out = [];
  95. untyped {
  96. __js__("for( var key in this.h ) {");
  97. if( h.hasOwnProperty(key) )
  98. out.push(key);
  99. __js__("}");
  100. }
  101. if( rh != null ) untyped {
  102. __js__("for( var key in this.rh ) {");
  103. if( key.charCodeAt(0) == "$".code )
  104. out.push(key.substr(1));
  105. __js__("}");
  106. }
  107. return out;
  108. }
  109. public inline function iterator() : Iterator<T> {
  110. return new StringMapIterator(this, arrayKeys());
  111. }
  112. public function toString() : String {
  113. var s = new StringBuf();
  114. s.add("{");
  115. var keys = arrayKeys();
  116. for( i in 0...keys.length ) {
  117. var k = keys[i];
  118. s.add(k);
  119. s.add(" => ");
  120. s.add(Std.string(get(k)));
  121. if( i < keys.length-1 )
  122. s.add(", ");
  123. }
  124. s.add("}");
  125. return s.toString();
  126. }
  127. static function __init__() : Void {
  128. untyped __js__("var __map_reserved = {};");
  129. }
  130. }