Boot.hx 8.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280
  1. /*
  2. * Copyright (C)2005-2012 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 lua;
  23. import lua.Table;
  24. import haxe.Constraints.Function;
  25. using lua.PairTools;
  26. class Boot {
  27. // Used temporarily for bind()
  28. static var _;
  29. static var _fid = 0;
  30. static function __unhtml(s : String)
  31. return s.split("&").join("&amp;").split("<").join("&lt;").split(">").join("&gt;");
  32. public static function patternQuote(str:String)
  33. return lua.StringTools.gsub(str, "[%(%)%.%%%+%-%*%?%[%]%^%$]", function(c:String){ return "%" + c; });
  34. public inline static function tableToArray<T>(t:Table<Int,T>, ?length:Int) : Array<T> {
  35. if (length == null) length = Table.maxn(t);
  36. return cast defArray(t,length);
  37. }
  38. public static function luaIteratorToArray<T>(itr:Void->T) : Array<T> {
  39. var i: T = null;
  40. var ret : Array<T> = [];
  41. while({i = itr(); i != null;}){
  42. ret.push(i);
  43. }
  44. return ret;
  45. }
  46. @:keep
  47. public static function bind(o:Dynamic, m: Function) : Function{
  48. if (m == null) return null;
  49. // if (m.__id.__ == nil) m.__id__ = _fid + 1;
  50. var f: Function = null;
  51. if ( o.hx__closures__ == null ) o.hx__closures__ = {};
  52. else untyped f = o.hx__closures__[m];
  53. if (f == null){
  54. f = untyped __lua__("function(...) return m(o, ...) end");
  55. untyped o.hx__closures__[m] = f;
  56. }
  57. return f;
  58. }
  59. static inline public function isClass(o:Dynamic) : Bool {
  60. if (Lua.type(o) != "table") return false;
  61. else return untyped __define_feature__("lua.Boot.isClass", o.__name__);
  62. }
  63. static inline public function isEnum(e:Dynamic) : Bool {
  64. if (Lua.type(e) != "table") return false;
  65. else return untyped __define_feature__("lua.Boot.isEnum", e.__ename__);
  66. }
  67. static inline public function getClass(o:Dynamic) : Dynamic {
  68. if (Std.is(o, Array)) return Array;
  69. else {
  70. var cl = untyped __define_feature__("lua.Boot.getClass", o.__class__);
  71. if (cl != null) return cl;
  72. else return null;
  73. }
  74. }
  75. @:ifFeature("typed_catch")
  76. private static function __instanceof(o : Dynamic,cl : Dynamic) {
  77. if( cl == null ) return false;
  78. switch( cl ) {
  79. case Int:
  80. // TODO: matching js behavior here, but js behavior clamps. Is that correct?
  81. return (untyped __type__(o) == "number" && clamp(o) == o);
  82. case Float:
  83. return untyped __type__(o) == "number";
  84. case Bool:
  85. return untyped __type__(o) == "boolean";
  86. case String:
  87. return untyped __type__(o) == "string";
  88. case Array:
  89. return untyped __type__(o) == "table"
  90. && lua.Lua.getmetatable(o) != null
  91. && lua.Lua.getmetatable(o).__index == Array.prototype;
  92. case Table:
  93. return untyped __type__(o) == "table";
  94. case Dynamic:
  95. return true;
  96. default: {
  97. if (o == null) {
  98. return false;
  99. } else if ( untyped o.__enum__ != null ){
  100. return o.__enum__ == cl;
  101. } else if ( untyped __type__(o) == "table"
  102. && untyped __type__(cl) == "table"){
  103. while (Lua.getmetatable(o) != null && Lua.getmetatable(o).__index != null){
  104. if (Lua.getmetatable(o).__index == cl.prototype) return true;
  105. o = Lua.getmetatable(o).__index;
  106. }
  107. return false;
  108. }
  109. return false;
  110. }
  111. }
  112. }
  113. @:ifFeature("typed_cast")
  114. private static function __cast(o : Dynamic, t : Dynamic) {
  115. if (__instanceof(o, t)) return o;
  116. else throw "Cannot cast " +Std.string(o) + " to " +Std.string(t);
  117. }
  118. @:keep
  119. public static function arrayNewIndex(tab:Dynamic, key:Dynamic, value:Dynamic){
  120. untyped rawset(tab, key, value);
  121. if (Std.is(key,Int) && key+1 > tab.length){
  122. tab.length = key + 1;
  123. }
  124. }
  125. @:keep
  126. public static function defArray(tabobj: Dynamic, length : Int) : Array<Dynamic> untyped {
  127. tabobj.length = length;
  128. setmetatable(tabobj, {
  129. __index : __lua__("Array.prototype"),
  130. __newindex : lua.Boot.arrayNewIndex
  131. });
  132. return tabobj;
  133. }
  134. public static function urlDecode(str:String){
  135. str = lua.StringTools.gsub (str, "+", " ");
  136. str = lua.StringTools.gsub (str, "%%(%x%x)",
  137. function(h) {return lua.StringTools.char(lua.Lua.tonumber(h,16));});
  138. str = lua.StringTools.gsub (str, "\r\n", "\n");
  139. return str;
  140. }
  141. public static function urlEncode(str:String){
  142. str = lua.StringTools.gsub(str, "\n", "\r\n");
  143. str = lua.StringTools.gsub(str, "([^%w %-%_%.%~])", function (c) {
  144. return lua.StringTools.format("%%%02X", lua.StringTools.byte(c) + '');
  145. });
  146. str = lua.StringTools.gsub(str, " ", "+");
  147. return str;
  148. }
  149. static function printEnum(e:Table<String,Dynamic>){
  150. var params = new Array<Dynamic>();
  151. var first = '';
  152. lua.PairTools.ipairsEach(e, function(i,x){
  153. if (i == 1) first = e[0];
  154. else params.push(x);
  155. });
  156. return '$first(${params.join(",")})';
  157. }
  158. static function printClass(c:Table<String,Dynamic>, s : Int) : String {
  159. return '{${printClassRec(c,'',s)}}';
  160. }
  161. static function printClassRec(c:Table<String,Dynamic>, result='', s : Int) : String {
  162. c.pairsEach(function(k,v){
  163. if (result != "")
  164. result += ", ";
  165. result += '$k: ${__string_rec(v, s + 1)}';
  166. });
  167. return result;
  168. }
  169. @:ifFeature("has_enum")
  170. static function __string_rec(o : Dynamic, s = 0) {
  171. return switch(untyped __type__(o)){
  172. case "nil": "null";
  173. case "number" : {
  174. if (o == std.Math.POSITIVE_INFINITY) "Infinity";
  175. else if (o == std.Math.NEGATIVE_INFINITY) "-Infinity";
  176. else if (o != o) "NaN";
  177. else untyped tostring(o);
  178. }
  179. case "boolean" : untyped tostring(o);
  180. case "string" : o;
  181. case "userdata": "<userdata>";
  182. case "function": "<function>";
  183. case "thread" : "<thread>";
  184. case "table": {
  185. if (Reflect.hasField(o,"__enum__")) printEnum(o);
  186. else if (o.toString != null && !__instanceof(o,Array)) o.toString();
  187. else if (__instanceof(o, Array)) {
  188. if (s > 5) "[...]"
  189. else '[${[for (i in cast(o,Array<Dynamic>)) __string_rec(i,s+1)].join(",")}]';
  190. } else if (s > 5){
  191. "{...}";
  192. }
  193. else if (Reflect.hasField(o,"__tostring")) Lua.tostring(o);
  194. else if (Reflect.hasField(o,"__class__")) printClass(o,s+1);
  195. else if (Lua.next(o) == null) "{}";
  196. else {
  197. var fields = Reflect.fields(o);
  198. var buffer = new StringBuf();
  199. for (f in fields){
  200. buffer.add('${Std.string(f)} : ${untyped Std.string(o[f])}');
  201. }
  202. buffer.toString();
  203. }
  204. };
  205. default : {
  206. throw "Unknown Lua type";
  207. null;
  208. }
  209. }
  210. }
  211. public static function dateStr( date : std.Date ) : String {
  212. var m = date.getMonth() + 1;
  213. var d = date.getDate();
  214. var h = date.getHours();
  215. var mi = date.getMinutes();
  216. var s = date.getSeconds();
  217. return date.getFullYear()
  218. +"-"+(if( m < 10 ) "0"+m else ""+m)
  219. +"-"+(if( d < 10 ) "0"+d else ""+d)
  220. +" "+(if( h < 10 ) "0"+h else ""+h)
  221. +":"+(if( mi < 10 ) "0"+mi else ""+mi)
  222. +":"+(if( s < 10 ) "0"+s else ""+s);
  223. }
  224. public static function clamp(x:Int){
  225. return (x & 2147483647) - (x & cast 2147483648);
  226. }
  227. public static function strDate( s : String ) : std.Date {
  228. switch( s.length ) {
  229. case 8: // hh:mm:ss
  230. var k = s.split(":");
  231. var t = lua.Os.time({
  232. year : 0,
  233. month : 1,
  234. day : 1,
  235. hour : Std.parseInt(k[0]),
  236. min : Std.parseInt(k[1]),
  237. sec : Std.parseInt(k[2])
  238. });
  239. return std.Date.fromTime(t);
  240. case 10: // YYYY-MM-DD
  241. var k = s.split("-");
  242. return new std.Date(Std.parseInt(k[0]), Std.parseInt(k[1]) - 1, Std.parseInt(k[2]),0,0,0);
  243. case 19: // YYYY-MM-DD hh:mm:ss
  244. var k = s.split(" ");
  245. var y = k[0].split("-");
  246. var t = k[1].split(":");
  247. return new std.Date(cast y[0],Std.parseInt(y[1]) - 1, Std.parseInt(y[2]),Std.parseInt(t[0]),Std.parseInt(t[1]),Std.parseInt(t[2]));
  248. default:
  249. throw "Invalid date format : " + s;
  250. }
  251. }
  252. }