PageRenderTime 34ms CodeModel.GetById 8ms RepoModel.GetById 0ms app.codeStats 0ms

/ext3/chx/Lib.hx

http://caffeine-hx.googlecode.com/
Haxe | 425 lines | 283 code | 29 blank | 113 comment | 29 complexity | 898544414dc07fc8dd4c9b507a20ea5b MD5 | raw file
Possible License(s): GPL-2.0, Apache-2.0, BSD-3-Clause, LGPL-2.1
  1. /*
  2. * Copyright (c) 2009, The Caffeine-hx 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 CAFFEINE-HX PROJECT CONTRIBUTORS "AS IS"
  14. * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
  15. * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
  16. * ARE DISCLAIMED. IN NO EVENT SHALL THE CAFFEINE-HX PROJECT CONTRIBUTORS
  17. * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
  18. * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
  19. * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
  20. * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
  21. * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
  22. * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
  23. * THE POSSIBILITY OF SUCH DAMAGE.
  24. */
  25. package chx;
  26. import chx.io.StringOutput;
  27. import chx.lang.FatalException;
  28. /**
  29. Common library functions.
  30. **/
  31. class Lib {
  32. /**
  33. * Load a dynamic library.
  34. * @param lib
  35. * @param prim
  36. * @param nargs
  37. * @return
  38. * @todo Flash: url loader to swf libs
  39. * @todo JS: possibilities?
  40. */
  41. public static function load( lib : String, prim : String, nargs : Int ) : Dynamic {
  42. #if cpp
  43. #if iphone
  44. return loadLazy(lib,prim,nargs);
  45. #else
  46. return untyped __global__.__loadprim(lib,prim,nargs);
  47. #end
  48. #elseif neko
  49. return untyped __dollar__loader.loadprim((lib + "@" + prim).__s, nargs);
  50. #else
  51. return null;
  52. #end
  53. }
  54. /**
  55. * Tries to load a dynamic library, and always returns a valid function,
  56. * but the function may throw if called.
  57. * @param lib
  58. * @param prim
  59. * @param nargs
  60. * @return
  61. */
  62. public static function loadLazy(lib : String, prim : String, nargs : Int) : Dynamic {
  63. #if cpp
  64. try {
  65. return untyped __global__.__loadprim(lib,prim,nargs);
  66. } catch( e : Dynamic ) {
  67. switch(nargs) {
  68. case 0 : return function() { throw e; };
  69. case 2 : return function(_1,_2) { throw e; };
  70. case 3 : return function(_1,_2,_3) { throw e; };
  71. case 4 : return function(_1,_2,_3,_4) { throw e; };
  72. case 5 : return function(_1,_2,_3,_4,_5) { throw e; };
  73. default : return function(_1) { throw e; };
  74. }
  75. }
  76. #elseif neko
  77. try {
  78. return load(lib,prim,nargs);
  79. } catch( e : Dynamic ) {
  80. return untyped __dollar__varargs(function(_) { throw e; });
  81. }
  82. #else
  83. return null;
  84. #end
  85. }
  86. /**
  87. * Rethrow an exception. This is useful when manually filtering an exception in order
  88. * to keep the previous exception stack.
  89. * @param e
  90. * @return
  91. */
  92. public static function rethrow( e : Dynamic ) : Dynamic {
  93. #if neko
  94. return untyped __dollar__rethrow(e);
  95. #elseif php
  96. if(Std.is(e, php.Exception)) {
  97. var __rtex__ = e;
  98. untyped __php__("throw $__rtex__");
  99. }
  100. else throw e;
  101. #else
  102. throw e;
  103. #end
  104. }
  105. /**
  106. * Print the specified value on the default output.
  107. * @param v
  108. * @todo better interface for traced platforms
  109. */
  110. public static function print( v : Dynamic ) : Void {
  111. #if neko
  112. untyped __dollar__print(v);
  113. #elseif cpp
  114. untyped __global__.__hxcpp_print(v);
  115. #elseif php
  116. untyped __call__("echo", Std.string(v));
  117. #else
  118. trace(v);
  119. #end
  120. }
  121. /**
  122. * Print the specified value on the default output followed by a newline character.
  123. * @param v
  124. * @todo See print
  125. */
  126. public static function println( v : Dynamic ) : Void {
  127. #if neko
  128. untyped __dollar__print(v, "\n");
  129. #elseif cpp
  130. untyped __global__.__hxcpp_println(v);
  131. #elseif php
  132. untyped __call__("echo", Std.string(v) + "\n");
  133. #else
  134. trace(v);
  135. #end
  136. }
  137. /**
  138. * Returns a string referencing the data contains in bytes.
  139. * @param b
  140. */
  141. public inline static function stringReference( b : Bytes ) {
  142. #if cpp
  143. throw b;
  144. #else
  145. return new String( cast b.getData() );
  146. #end
  147. }
  148. /**
  149. * Returns bytes referencing the content of a string.
  150. * @param s
  151. * @return
  152. * @todo test
  153. */
  154. public inline static function bytesReference( s : String ) : Bytes {
  155. #if neko
  156. return untyped new Bytes( s.length, s.__s );
  157. #elseif php
  158. return untyped new Bytes(untyped __call__("strlen", s), cast s);
  159. #else
  160. return throw new FatalException("unimplemented");
  161. #end
  162. }
  163. /**
  164. * Serialize using native serialization. This will return a Binary string that can be
  165. * stored for long term usage. The serialized data is optimized for speed and not for size.
  166. * @param v
  167. * @return
  168. */
  169. public static function serialize( v : Dynamic ) : String {
  170. #if neko
  171. return new String(__serialize(v));
  172. #elseif php
  173. return untyped __call__("serialize", v);
  174. #else
  175. var so = new StringOutput();
  176. Serializer.run(v, so);
  177. return so.toString();
  178. #end
  179. }
  180. /**
  181. * Unserialize a string using native serialization. See [serialize].
  182. * @param s
  183. * @return
  184. */
  185. public static function unserialize( s : String ) : Dynamic {
  186. #if neko
  187. return untyped __unserialize(s.__s, __dollar__loader);
  188. #elseif php
  189. return untyped __call__("unserialize", s);
  190. #else
  191. return Unserializer.run(s);
  192. #end
  193. }
  194. static var dll_init : Hash<Bool>;
  195. /**
  196. * For platforms that require initialization of loaded libraries. This is required when
  197. * using ndlls generated with hxcpp for neko
  198. * @param libName Short name for lib, without .ndll extension
  199. * @param entryFunc Library init function. If not provided, will be libName_init
  200. */
  201. public static function initDll(libName:String, entryFunc : String = null) : Void {
  202. if(dll_init == null)
  203. dll_init = new Hash();
  204. if(dll_init.exists(libName))
  205. return;
  206. var init : Dynamic = null;
  207. #if neko
  208. init = chx.Lib.load(libName, "neko_init", 5);
  209. if(init == null)
  210. throw("Could not find NekoAPI interface.");
  211. //neko_init(inNewString,inNewArray,inNull,inTrue,inFalse)
  212. init(function(s) return new String(s),
  213. function(len:Int) { var r = []; if (len > 0) r[len - 1] = null; return r; },
  214. null, true, false);
  215. #end
  216. if(entryFunc == null)
  217. entryFunc = libName + "_init";
  218. init = chx.Lib.load(libName, entryFunc, 0);
  219. if(init != null)
  220. init();
  221. dll_init.set(libName, true);
  222. }
  223. #if (neko || cpp)
  224. public static inline function nekoStringToHaxe( v : String ) : String {
  225. return
  226. #if cpp
  227. v;
  228. #elseif neko
  229. new String(v);
  230. #end
  231. }
  232. public static inline function haxeStringToNeko( v : String ) : String {
  233. return
  234. #if cpp
  235. v;
  236. #elseif neko
  237. untyped v.__s;
  238. #end
  239. }
  240. /**
  241. * Converts a Neko value to its haXe equivalent. Used for wrapping String and Arrays raw values into haXe Objects.
  242. * @param v
  243. * @return
  244. */
  245. public static function nekoToHaxe( v : Dynamic ) : Dynamic untyped {
  246. #if cpp
  247. return v;
  248. #elseif neko
  249. switch( __dollar__typeof(v) ) {
  250. case __dollar__tnull: return v;
  251. case __dollar__tint: return v;
  252. case __dollar__tfloat: return v;
  253. case __dollar__tbool: return v;
  254. case __dollar__tstring: return new String(v);
  255. case __dollar__tarray:
  256. var a = Array.new1(v,__dollar__asize(v));
  257. for( i in 0...a.length )
  258. a[i] = nekoToHaxe(a[i]);
  259. return a;
  260. case __dollar__tobject:
  261. var f = __dollar__objfields(v);
  262. var i = 0;
  263. var l = __dollar__asize(f);
  264. var o = __dollar__new(v);
  265. if( __dollar__objgetproto(v) != null )
  266. throw "Can't convert object prototype";
  267. while( i < l ) {
  268. __dollar__objset(o,f[i],nekoToHaxe(__dollar__objget(v,f[i])));
  269. i += 1;
  270. }
  271. return o;
  272. default:
  273. throw "Can't convert "+string(v);
  274. }
  275. #end
  276. }
  277. /**
  278. * Converts a Neko value to its haXe equivalent. Used to unwrap String and Arrays Objects into raw Neko values.
  279. * @param v
  280. * @return
  281. */
  282. public static function haxeToNeko( v : Dynamic ) : Dynamic untyped {
  283. #if cpp
  284. return v;
  285. #elseif neko
  286. switch( __dollar__typeof(v) ) {
  287. case __dollar__tnull: return v;
  288. case __dollar__tint: return v;
  289. case __dollar__tfloat: return v;
  290. case __dollar__tbool: return v;
  291. case __dollar__tobject:
  292. var cl = v.__class__;
  293. if( cl == String )
  294. return v.__s;
  295. if( cl == Array ) {
  296. var a = untyped __dollar__amake(v.length);
  297. for( i in 0...v.length )
  298. a[i] = haxeToNeko(v[i]);
  299. return a;
  300. }
  301. if( cl != null || __dollar__objgetproto(v) != null )
  302. throw "Can't convert "+string(v);
  303. var f = __dollar__objfields(v);
  304. var i = 0;
  305. var l = __dollar__asize(f);
  306. var o = __dollar__new(v);
  307. while( i < l ) {
  308. __dollar__objset(o,f[i],haxeToNeko(__dollar__objget(v,f[i])));
  309. i += 1;
  310. }
  311. return o;
  312. default:
  313. throw "Can't convert "+string(v);
  314. }
  315. #end
  316. }
  317. #end
  318. #if neko
  319. /**
  320. * Unserialize a string using native serialization. See [serialize].
  321. * This function assume that all the serialized data was serialized with current
  322. * module, even if the module name was different. This can happen if you are unserializing
  323. * some data into mod_neko that was serialized on a different server using a different
  324. * file path.
  325. *
  326. * @param s
  327. * @return
  328. */
  329. public static function localUnserialize( s : String ) : Dynamic {
  330. return untyped __unserialize(s.__s,{
  331. loadmodule : function(m,l) { return __dollar__exports; },
  332. loadprim : function(p,n) { return __dollar__loader.loadprim(p,n); }
  333. });
  334. }
  335. #end
  336. #if php
  337. static function appendType(o : Dynamic, path : Array<String>, t : Dynamic) {
  338. var name = path.shift();
  339. if(path.length == 0)
  340. untyped __php__("$o->$name = $t");
  341. else {
  342. var so = untyped __call__("isset", __php__("$o->$name")) ? __php__("$o->$name") : {};
  343. appendType(so, path, t);
  344. untyped __php__("$o->$name = $so");
  345. }
  346. }
  347. public static function extensionLoaded(name : String) {
  348. return untyped __call__("extension_loaded", name);
  349. }
  350. public static function isCli() : Bool {
  351. return untyped __php__("(0 == strncasecmp(PHP_SAPI, 'cli', 3))");
  352. }
  353. public static function printFile(file : String) {
  354. return untyped __call__("fpassthru", __call__("fopen", file, "r"));
  355. }
  356. public static inline function toPhpArray(a : Array<Dynamic>) : php.NativeArray {
  357. return untyped __field__(a, 'Â?a');
  358. }
  359. public static inline function toHaxeArray(a : php.NativeArray) : Array<Dynamic> {
  360. return untyped __call__("new _hx_array", a);
  361. }
  362. public static function hashOfAssociativeArray<T>(arr : php.NativeArray) : Hash<T> {
  363. var h = new Hash<T>();
  364. untyped __php__("reset($arr); while(list($k, $v) = each($arr)) $h->set($k, $v)");
  365. return h;
  366. }
  367. public static function associativeArrayOfHash(hash : Hash<Dynamic>) : php.NativeArray {
  368. return untyped hash.h;
  369. }
  370. #end
  371. /**
  372. * Returns an object containing all compiled packages and classes.
  373. * @return
  374. * @todo possible on some other platforms
  375. */
  376. public static function getClasses() : Dynamic {
  377. #if neko
  378. return untyped neko.Boot.__classes;
  379. #elseif php
  380. var path : String = null;
  381. var o = {};
  382. untyped __call__('reset', php.Boot.qtypes);
  383. while((path = untyped __call__('key', php.Boot.qtypes)) != null) {
  384. appendType(o, path.split('.'), untyped php.Boot.qtypes[path]);
  385. untyped __call__('next',php.Boot.qtypes);
  386. }
  387. return o;
  388. #else
  389. throw new FatalException("unimplemented");
  390. #end
  391. }
  392. #if neko
  393. static var __serialize = load("std","serialize",1);
  394. static var __unserialize = load("std", "unserialize", 2);
  395. #end
  396. }