rtl.js 7.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262
  1. "use strict";
  2. if (typeof Uint16Array == "undefined"){
  3. global.Uint16Array = function(length){
  4. Array.call(this, length);
  5. for(var i = 0; i < length; ++i)
  6. this[i] = 0;
  7. };
  8. }
  9. function applyMap(from, to){
  10. for(var p in from)
  11. to[p] = from[p];
  12. }
  13. function Class(){}
  14. Class.extend = function extend(methods){
  15. function Type(){
  16. applyMap(methods, this);
  17. }
  18. Type.prototype = this.prototype;
  19. var result = methods.init;
  20. result.prototype = new Type(); // inherit this.prototype
  21. result.prototype.constructor = result; // to see constructor name in diagnostic
  22. result.extend = extend;
  23. return result;
  24. };
  25. var methods = {
  26. extend: function(cons, base, scope){
  27. function Type(){}
  28. Type.prototype = base.prototype;
  29. cons.prototype = new Type();
  30. cons.prototype.constructor = cons;
  31. cons.prototype.$scope = scope;
  32. },
  33. typeGuard: function(from, to){
  34. if (!from)
  35. return from;
  36. if (!(from instanceof to)){
  37. var fromStr;
  38. var toStr;
  39. var scope;
  40. if (from && from.constructor && from.constructor.name){
  41. var name = from.constructor.name;
  42. scope = from.$scope;
  43. fromStr = scope ? scope + "." + name : name;
  44. }
  45. else
  46. fromStr = "" + from;
  47. if (to.name){
  48. toStr = "" + to.name;
  49. scope = to.prototype.$scope;
  50. toStr = scope ? scope + "." + toStr : toStr;
  51. }
  52. else
  53. toStr = "" + to;
  54. var msg = "cannot cast";
  55. if (fromStr || toStr)
  56. msg += " to '" + toStr + "' from '" + fromStr + "'";
  57. throw new Error(msg);
  58. }
  59. return from;
  60. },
  61. charAt: function(s, index){
  62. if (index >= 0 && index < s.length)
  63. return s.charCodeAt(index);
  64. throw new Error("index out of bounds: " + index);
  65. },
  66. getAt: function(where, index){
  67. if (index >= 0 && index < where.length)
  68. return where[index];
  69. throw new Error("index out of bounds: " + index);
  70. },
  71. putAt: function(where, index, what){
  72. if (index >= 0 && index < where.length)
  73. where[index] = what;
  74. else
  75. throw new Error("index out of bounds: " + index);
  76. },
  77. makeArray: function(/*dimensions, initializer*/){
  78. var forward = Array.prototype.slice.call(arguments);
  79. var result = new Array(forward.shift());
  80. var i;
  81. if (forward.length == 1){
  82. var init = forward[0];
  83. if (typeof init == "function")
  84. for(i = 0; i < result.length; ++i)
  85. result[i] = init();
  86. else
  87. for(i = 0; i < result.length; ++i)
  88. result[i] = init;
  89. }
  90. else
  91. for(i = 0; i < result.length; ++i)
  92. result[i] = this.makeArray.apply(this, forward);
  93. return result;
  94. },
  95. __setupCharArrayMethods: function(a){
  96. var rtl = this;
  97. a.charCodeAt = function(i){return this[i];};
  98. a.slice = function(){
  99. var result = Array.prototype.slice.apply(this, arguments);
  100. rtl.__setupCharArrayMethods(result);
  101. return result;
  102. };
  103. a.toString = function(){
  104. return String.fromCharCode.apply(this, this);
  105. };
  106. },
  107. __makeCharArray: function(length){
  108. var result = new Uint16Array(length);
  109. this.__setupCharArrayMethods(result);
  110. return result;
  111. },
  112. makeCharArray: function(/*dimensions*/){
  113. var forward = Array.prototype.slice.call(arguments);
  114. var length = forward.pop();
  115. if (!forward.length)
  116. return this.__makeCharArray(length);
  117. function makeArray(){
  118. var forward = Array.prototype.slice.call(arguments);
  119. var result = new Array(forward.shift());
  120. var i;
  121. if (forward.length == 1){
  122. var init = forward[0];
  123. for(i = 0; i < result.length; ++i)
  124. result[i] = init();
  125. }
  126. else
  127. for(i = 0; i < result.length; ++i)
  128. result[i] = makeArray.apply(undefined, forward);
  129. return result;
  130. }
  131. forward.push(this.__makeCharArray.bind(this, length));
  132. return makeArray.apply(undefined, forward);
  133. },
  134. makeSet: function(/*...*/){
  135. var result = 0;
  136. function checkBit(b){
  137. if (b < 0 || b > 31)
  138. throw new Error("integers between 0 and 31 expected, got " + b);
  139. }
  140. function setBit(b){
  141. checkBit(b);
  142. result |= 1 << b;
  143. }
  144. for(var i = 0; i < arguments.length; ++i){
  145. var b = arguments[i];
  146. if (b instanceof Array){
  147. var from = b[0];
  148. var to = b[1];
  149. if (to < from)
  150. throw new Error("invalid SET diapason: " + from + ".." + to);
  151. for(var bi = from; bi <= to; ++bi)
  152. setBit(bi);
  153. }
  154. else
  155. setBit(b);
  156. }
  157. return result;
  158. },
  159. makeRef: function(obj, prop){
  160. return {set: function(v){ obj[prop] = v; },
  161. get: function(){ return obj[prop]; }};
  162. },
  163. setInclL: function(l, r){return (l & r) == l;},
  164. setInclR: function(l, r){return (l & r) == r;},
  165. assignArrayFromString: function(a, s){
  166. var i;
  167. for(i = 0; i < s.length; ++i)
  168. a[i] = s.charCodeAt(i);
  169. for(i = s.length; i < a.length; ++i)
  170. a[i] = 0;
  171. },
  172. strCmp: function(s1, s2){
  173. var cmp = 0;
  174. var i = 0;
  175. while (!cmp && i < s1.length && i < s2.length){
  176. cmp = s1.charCodeAt(i) - s2.charCodeAt(i);
  177. ++i;
  178. }
  179. return cmp ? cmp : s1.length - s2.length;
  180. },
  181. copy: function(from, to, type){
  182. var r = type.record;
  183. if (r){
  184. for(var f in r){
  185. var fieldType = r[f];
  186. if (fieldType)
  187. this.copy(from[f], to[f], fieldType);
  188. else
  189. to[f] = from[f];
  190. }
  191. return;
  192. }
  193. var a = type.array;
  194. if (a !== undefined ){
  195. if (a === null)
  196. // shallow copy
  197. Array.prototype.splice.apply(to, [0, to.length].concat(from));
  198. else {
  199. // deep copy
  200. to.splice(0, to.length);
  201. for(var i = 0; i < from.length; ++i)
  202. to.push(this.clone(from[i], a));
  203. }
  204. }
  205. },
  206. clone: function(from, type, recordCons){
  207. var result;
  208. var r = type.record;
  209. if (r){
  210. var Ctr = recordCons || from.constructor;
  211. result = new Ctr();
  212. this.copy(from, result, type);
  213. return result;
  214. }
  215. var a = type.array;
  216. if (a !== undefined ){
  217. if (a === null)
  218. // shallow clone
  219. return from.slice();
  220. // deep clone
  221. var length = from.length;
  222. result = new Array(length);
  223. for(var i = 0; i < length; ++i)
  224. result[i] = this.clone(from[i], a);
  225. return result;
  226. }
  227. },
  228. assert: function(condition){
  229. if (!condition)
  230. throw new Error("assertion failed");
  231. }
  232. };
  233. exports.Class = Class;
  234. exports.rtl = {
  235. dependencies: {
  236. "copy": ["clone"],
  237. "clone": ["copy"],
  238. "makeCharArray": ["__makeCharArray"],
  239. "__makeCharArray": ["__setupCharArrayMethods"]
  240. },
  241. methods: methods,
  242. nodejsModule: "rtl.js"
  243. };
  244. exports.applyMap = applyMap;
  245. applyMap(methods, exports);