sqstdio.cpp 16 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631
  1. /* see copyright notice in squirrel.h */
  2. #include <new>
  3. #include <stdio.h>
  4. #include <string.h>
  5. #include <squirrel.h>
  6. #include <sqstdio.h>
  7. #include <sqstdfile.h>
  8. #include "sqstdstream.h"
  9. //#define SQSTD_FILE_TYPE_TAG (SQSTD_STREAM_TYPE_TAG | 0x00000001)
  10. const SQChar SQSTD_FILE_TYPE_TAG[] = _SC("std_stream_file");
  11. const SQChar SQSTD_FILE_CLASS_TYPE_TAG[] = _SC("std_file");
  12. //basic API
  13. SQFILE sqstd_fopen(const SQChar *filename ,const SQChar *mode)
  14. {
  15. return (SQFILE)scfopen(filename,mode);
  16. }
  17. SQInteger sqstd_fread(void* buffer, SQInteger size, SQInteger count, SQFILE file)
  18. {
  19. return (SQInteger)fread(buffer,size,count,(FILE *)file);
  20. }
  21. SQChar *sqstd_fgets(SQChar* buffer, SQInteger count, SQFILE file)
  22. {
  23. return (SQChar*)fgets(buffer,count,(FILE *)file);
  24. }
  25. SQInteger sqstd_fwrite(const SQUserPointer buffer, SQInteger size, SQInteger count, SQFILE file)
  26. {
  27. return (SQInteger)fwrite(buffer,size,count,(FILE *)file);
  28. }
  29. SQInteger sqstd_fseek(SQFILE file, SQInteger offset, SQInteger origin)
  30. {
  31. SQInteger realorigin;
  32. switch(origin) {
  33. case SQ_SEEK_CUR: realorigin = SEEK_CUR; break;
  34. case SQ_SEEK_END: realorigin = SEEK_END; break;
  35. case SQ_SEEK_SET: realorigin = SEEK_SET; break;
  36. default: return -1; //failed
  37. }
  38. return fseek((FILE *)file,(long)offset,(int)realorigin);
  39. }
  40. SQInteger sqstd_ftell(SQFILE file)
  41. {
  42. return ftell((FILE *)file);
  43. }
  44. SQInteger sqstd_fflush(SQFILE file)
  45. {
  46. return fflush((FILE *)file);
  47. }
  48. SQInteger sqstd_fclose(SQFILE file)
  49. {
  50. return fclose((FILE *)file);
  51. }
  52. SQInteger sqstd_feof(SQFILE file)
  53. {
  54. return feof((FILE *)file);
  55. }
  56. struct SQPopen : public SQFile {
  57. SQPopen():SQFile() {}
  58. SQPopen(SQFILE file, bool owns):SQFile(file, owns) {}
  59. bool Open(const SQChar *filename ,const SQChar *mode) {
  60. Close();
  61. if( (_handle = popen(filename,mode)) ) {
  62. _owns = true;
  63. return true;
  64. }
  65. return false;
  66. }
  67. int PClose() {
  68. int result = 0;
  69. if(_handle && _owns) {
  70. result = pclose((FILE*)_handle);
  71. _handle = NULL;
  72. _owns = false;
  73. }
  74. return result;
  75. }
  76. void Close() {
  77. PClose();
  78. }
  79. };
  80. static SQRESULT _popen__typeof(HSQUIRRELVM v)
  81. {
  82. sq_pushstring(v,_SC("popen"),-1);
  83. return 1;
  84. }
  85. static SQRESULT _popen_releasehook(SQUserPointer p, SQInteger /*size*/, void */*ep*/)
  86. {
  87. SQPopen *self = (SQPopen*)p;
  88. self->~SQPopen();
  89. sq_free(self,sizeof(SQFile));
  90. return 1;
  91. }
  92. static SQRESULT _popen_constructor(HSQUIRRELVM v)
  93. {
  94. const SQChar *filename,*mode;
  95. bool owns = true;
  96. SQPopen *f;
  97. SQFILE newf;
  98. if(sq_gettype(v,2) == OT_STRING && sq_gettype(v,3) == OT_STRING) {
  99. sq_getstring(v, 2, &filename);
  100. sq_getstring(v, 3, &mode);
  101. newf = popen(filename, mode);
  102. if(!newf) return sq_throwerror(v, _SC("cannot open file"));
  103. } else {
  104. return sq_throwerror(v,_SC("wrong parameter"));
  105. }
  106. f = new (sq_malloc(sizeof(SQPopen)))SQPopen(newf,owns);
  107. if(SQ_FAILED(sq_setinstanceup(v,1,f))) {
  108. f->~SQPopen();
  109. sq_free(f,sizeof(SQPopen));
  110. return sq_throwerror(v, _SC("cannot create popen"));
  111. }
  112. sq_setreleasehook(v,1,_popen_releasehook);
  113. return 0;
  114. }
  115. static SQRESULT _popen_close(HSQUIRRELVM v)
  116. {
  117. SQPopen *self = NULL;
  118. if(SQ_SUCCEEDED(sq_getinstanceup(v,1,(SQUserPointer*)&self,(SQUserPointer)SQSTD_FILE_TYPE_TAG))
  119. && self != NULL)
  120. {
  121. sq_pushinteger(v, self->PClose());
  122. return 1;
  123. }
  124. return 0;
  125. }
  126. //bindings
  127. #define _DECL_FILE_FUNC(name,nparams,typecheck) {_SC(#name),_popen_##name,nparams,typecheck}
  128. static const SQRegFunction _popen_methods[] = {
  129. _DECL_FILE_FUNC(constructor,3,_SC("x")),
  130. _DECL_FILE_FUNC(_typeof,1,_SC("x")),
  131. _DECL_FILE_FUNC(close,1,_SC("x")),
  132. {NULL,(SQFUNCTION)0,0,NULL}
  133. };
  134. #undef _DECL_FILE_FUNC
  135. static SQRESULT _file__typeof(HSQUIRRELVM v)
  136. {
  137. sq_pushstring(v,_SC("file"),-1);
  138. return 1;
  139. }
  140. static SQRESULT _file_releasehook(SQUserPointer p, SQInteger /*size*/, void */*ep*/)
  141. {
  142. SQFile *self = (SQFile*)p;
  143. self->~SQFile();
  144. sq_free(self,sizeof(SQFile));
  145. return 1;
  146. }
  147. static SQRESULT _file_constructor(HSQUIRRELVM v)
  148. {
  149. const SQChar *filename,*mode;
  150. bool owns = true;
  151. SQFile *f;
  152. SQFILE newf;
  153. if(sq_gettype(v,2) == OT_STRING && sq_gettype(v,3) == OT_STRING) {
  154. sq_getstring(v, 2, &filename);
  155. sq_getstring(v, 3, &mode);
  156. newf = sqstd_fopen(filename, mode);
  157. if(!newf) return sq_throwerror(v, _SC("cannot open file"));
  158. } else if(sq_gettype(v,2) == OT_USERPOINTER) {
  159. owns = !(sq_gettype(v,3) == OT_NULL);
  160. sq_getuserpointer(v,2,&newf);
  161. } else {
  162. return sq_throwerror(v,_SC("wrong parameter"));
  163. }
  164. f = new (sq_malloc(sizeof(SQFile)))SQFile(newf,owns);
  165. if(SQ_FAILED(sq_setinstanceup(v,1,f))) {
  166. f->~SQFile();
  167. sq_free(f,sizeof(SQFile));
  168. return sq_throwerror(v, _SC("cannot create blob with negative size"));
  169. }
  170. sq_setreleasehook(v,1,_file_releasehook);
  171. return 0;
  172. }
  173. static SQRESULT _file_close(HSQUIRRELVM v)
  174. {
  175. SQFile *self = NULL;
  176. if(SQ_SUCCEEDED(sq_getinstanceup(v,1,(SQUserPointer*)&self,(SQUserPointer)SQSTD_FILE_TYPE_TAG))
  177. && self != NULL)
  178. {
  179. self->Close();
  180. }
  181. return 0;
  182. }
  183. //bindings
  184. #define _DECL_FILE_FUNC(name,nparams,typecheck) {_SC(#name),_file_##name,nparams,typecheck}
  185. static const SQRegFunction _file_methods[] = {
  186. _DECL_FILE_FUNC(constructor,3,_SC("x")),
  187. _DECL_FILE_FUNC(_typeof,1,_SC("x")),
  188. _DECL_FILE_FUNC(close,1,_SC("x")),
  189. {NULL,(SQFUNCTION)0,0,NULL}
  190. };
  191. SQRESULT sqstd_createfile(HSQUIRRELVM v, SQFILE file,SQBool own)
  192. {
  193. SQInteger top = sq_gettop(v);
  194. sq_pushregistrytable(v);
  195. sq_pushstring(v,_SC("std_file"),-1);
  196. if(SQ_SUCCEEDED(sq_get(v,-2))) {
  197. sq_remove(v,-2); //removes the registry
  198. sq_pushroottable(v); // push the this
  199. sq_pushuserpointer(v,file); //file
  200. if(own){
  201. sq_pushinteger(v,1); //true
  202. }
  203. else{
  204. sq_pushnull(v); //false
  205. }
  206. if(SQ_SUCCEEDED( sq_call(v,3,SQTrue,SQFalse) )) {
  207. sq_remove(v,-2);
  208. return SQ_OK;
  209. }
  210. }
  211. sq_settop(v,top);
  212. return SQ_ERROR;
  213. }
  214. SQRESULT sqstd_getfile(HSQUIRRELVM v, SQInteger idx, SQFILE *file)
  215. {
  216. SQFile *fileobj = NULL;
  217. if(SQ_SUCCEEDED(sq_getinstanceup(v,idx,(SQUserPointer*)&fileobj,(SQUserPointer)SQSTD_FILE_TYPE_TAG))) {
  218. *file = fileobj->GetHandle();
  219. return SQ_OK;
  220. }
  221. return sq_throwerror(v,_SC("not a file"));
  222. }
  223. #define IO_BUFFER_SIZE 2048
  224. struct IOBuffer {
  225. unsigned char buffer[IO_BUFFER_SIZE];
  226. SQInteger size;
  227. SQInteger ptr;
  228. SQFILE file;
  229. };
  230. SQInteger _read_byte(IOBuffer *iobuffer)
  231. {
  232. if(iobuffer->ptr < iobuffer->size) {
  233. SQInteger ret = iobuffer->buffer[iobuffer->ptr];
  234. iobuffer->ptr++;
  235. return ret;
  236. }
  237. else {
  238. if( (iobuffer->size = sqstd_fread(iobuffer->buffer,1,IO_BUFFER_SIZE,iobuffer->file )) > 0 )
  239. {
  240. SQInteger ret = iobuffer->buffer[0];
  241. iobuffer->ptr = 1;
  242. return ret;
  243. }
  244. }
  245. return 0;
  246. }
  247. SQInteger _read_two_bytes(IOBuffer *iobuffer)
  248. {
  249. if(iobuffer->ptr < iobuffer->size) {
  250. if(iobuffer->size < 2) return 0;
  251. SQInteger ret = *((const wchar_t*)&iobuffer->buffer[iobuffer->ptr]);
  252. iobuffer->ptr += 2;
  253. return ret;
  254. }
  255. else {
  256. if( (iobuffer->size = sqstd_fread(iobuffer->buffer,1,IO_BUFFER_SIZE,iobuffer->file )) > 0 )
  257. {
  258. if(iobuffer->size < 2) return 0;
  259. SQInteger ret = *((const wchar_t*)&iobuffer->buffer[0]);
  260. iobuffer->ptr = 2;
  261. return ret;
  262. }
  263. }
  264. return 0;
  265. }
  266. static SQInteger _io_file_lexfeed_PLAIN(SQUserPointer iobuf)
  267. {
  268. IOBuffer *iobuffer = (IOBuffer *)iobuf;
  269. return _read_byte(iobuffer);
  270. }
  271. #ifdef SQUNICODE
  272. static SQInteger _io_file_lexfeed_UTF8(SQUserPointer iobuf)
  273. {
  274. IOBuffer *iobuffer = (IOBuffer *)iobuf;
  275. #define READ(iobuf) \
  276. if((inchar = (unsigned char)_read_byte(iobuf)) == 0) \
  277. return 0;
  278. static const SQInteger utf8_lengths[16] =
  279. {
  280. 1,1,1,1,1,1,1,1, /* 0000 to 0111 : 1 byte (plain ASCII) */
  281. 0,0,0,0, /* 1000 to 1011 : not valid */
  282. 2,2, /* 1100, 1101 : 2 bytes */
  283. 3, /* 1110 : 3 bytes */
  284. 4 /* 1111 :4 bytes */
  285. };
  286. static const unsigned char byte_masks[5] = {0,0,0x1f,0x0f,0x07};
  287. unsigned char inchar;
  288. SQInteger c = 0;
  289. READ(iobuffer);
  290. c = inchar;
  291. //
  292. if(c >= 0x80) {
  293. SQInteger tmp;
  294. SQInteger codelen = utf8_lengths[c>>4];
  295. if(codelen == 0)
  296. return 0;
  297. //"invalid UTF-8 stream";
  298. tmp = c&byte_masks[codelen];
  299. for(SQInteger n = 0; n < codelen-1; n++) {
  300. tmp<<=6;
  301. READ(iobuffer);
  302. tmp |= inchar & 0x3F;
  303. }
  304. c = tmp;
  305. }
  306. return c;
  307. }
  308. #endif
  309. static SQInteger _io_file_lexfeed_UCS2_LE(SQUserPointer iobuf)
  310. {
  311. SQInteger ret;
  312. IOBuffer *iobuffer = (IOBuffer *)iobuf;
  313. if( (ret = _read_two_bytes(iobuffer)) > 0 )
  314. return ret;
  315. return 0;
  316. }
  317. static SQInteger _io_file_lexfeed_UCS2_BE(SQUserPointer iobuf)
  318. {
  319. SQInteger c;
  320. IOBuffer *iobuffer = (IOBuffer *)iobuf;
  321. if( (c = _read_two_bytes(iobuffer)) > 0 ) {
  322. c = ((c>>8)&0x00FF)| ((c<<8)&0xFF00);
  323. return c;
  324. }
  325. return 0;
  326. }
  327. SQInteger file_read(SQUserPointer file,SQUserPointer buf,SQInteger size)
  328. {
  329. SQInteger ret;
  330. if( ( ret = sqstd_fread(buf,1,size,(SQFILE)file ))!=0 )return ret;
  331. return -1;
  332. }
  333. SQInteger file_write(SQUserPointer file,SQUserPointer p,SQInteger size)
  334. {
  335. return sqstd_fwrite(p,1,size,(SQFILE)file);
  336. }
  337. SQRESULT sqstd_loadfile(HSQUIRRELVM v,const SQChar *filename,SQBool printerror,SQBool show_warnings)
  338. {
  339. SQFILE file = sqstd_fopen(filename,_SC("rb"));
  340. SQInteger ret;
  341. unsigned short us;
  342. unsigned char uc;
  343. SQLEXREADFUNC func = _io_file_lexfeed_PLAIN;
  344. if(file){
  345. ret = sqstd_fread(&us,1,2,file);
  346. if(ret != 2) {
  347. //probably an empty file
  348. us = 0;
  349. }
  350. if(us == SQ_BYTECODE_STREAM_TAG) { //BYTECODE
  351. sqstd_fseek(file,0,SQ_SEEK_SET);
  352. if(SQ_SUCCEEDED(sq_readclosure(v,file_read,file))) {
  353. sqstd_fclose(file);
  354. return SQ_OK;
  355. }
  356. }
  357. else { //SCRIPT
  358. switch(us)
  359. {
  360. //gotta swap the next 2 lines on BIG endian machines
  361. case 0xFFFE: func = _io_file_lexfeed_UCS2_BE; break;//UTF-16 little endian;
  362. case 0xFEFF: func = _io_file_lexfeed_UCS2_LE; break;//UTF-16 big endian;
  363. case 0xBBEF:
  364. if(sqstd_fread(&uc,1,sizeof(uc),file) == 0) {
  365. sqstd_fclose(file);
  366. return sq_throwerror(v,_SC("io error"));
  367. }
  368. if(uc != 0xBF) {
  369. sqstd_fclose(file);
  370. return sq_throwerror(v,_SC("Unrecognozed ecoding"));
  371. }
  372. #ifdef SQUNICODE
  373. func = _io_file_lexfeed_UTF8;
  374. #else
  375. func = _io_file_lexfeed_PLAIN;
  376. #endif
  377. break;//UTF-8 ;
  378. default: sqstd_fseek(file,0,SQ_SEEK_SET); break; // ascii
  379. }
  380. IOBuffer buffer;
  381. buffer.ptr = 0;
  382. buffer.size = 0;
  383. buffer.file = file;
  384. if(SQ_SUCCEEDED(sq_compile(v,func,&buffer,filename,printerror,show_warnings, SQ_MAX_INCLUDE_FILES))){
  385. sqstd_fclose(file);
  386. return SQ_OK;
  387. }
  388. }
  389. sqstd_fclose(file);
  390. return SQ_ERROR;
  391. }
  392. return sq_throwerror(v,_SC("cannot open the file"));
  393. }
  394. SQRESULT sqstd_dofile(HSQUIRRELVM v,const SQChar *filename,SQBool retval,SQBool printerror,SQBool show_warnings)
  395. {
  396. if(SQ_SUCCEEDED(sqstd_loadfile(v,filename,printerror,show_warnings))) {
  397. sq_push(v,-2);
  398. if(SQ_SUCCEEDED(sq_call(v,1,retval,SQTrue))) {
  399. sq_remove(v,retval?-2:-1); //removes the closure
  400. return 1;
  401. }
  402. sq_pop(v,1); //removes the closure
  403. }
  404. return SQ_ERROR;
  405. }
  406. SQRESULT sqstd_writeclosuretofile(HSQUIRRELVM v,const SQChar *filename)
  407. {
  408. SQFILE file = sqstd_fopen(filename,_SC("wb+"));
  409. if(!file) return sq_throwerror(v,_SC("cannot open the file"));
  410. if(SQ_SUCCEEDED(sq_writeclosure(v,file_write,file))) {
  411. sqstd_fclose(file);
  412. return SQ_OK;
  413. }
  414. sqstd_fclose(file);
  415. return SQ_ERROR; //forward the error
  416. }
  417. SQRESULT sqstd_writeclosuretofile_as_source(HSQUIRRELVM v,const SQChar *filename)
  418. {
  419. SQFILE file = sqstd_fopen(filename,_SC("wb+"));
  420. if(!file) return sq_throwerror(v,_SC("cannot open the file"));
  421. if(SQ_SUCCEEDED(sq_writeclosure_as_source(v,file_write,file))) {
  422. sqstd_fclose(file);
  423. return SQ_OK;
  424. }
  425. sqstd_fclose(file);
  426. return SQ_ERROR; //forward the error
  427. }
  428. SQInteger _g_io_loadfile(HSQUIRRELVM v)
  429. {
  430. SQ_FUNC_VARS(v);
  431. SQ_GET_STRING(v, 2, filename);
  432. SQ_OPT_BOOL(v, 3, printerror, SQFalse);
  433. SQ_OPT_BOOL(v, 4, show_warnings, SQTrue);
  434. if(SQ_SUCCEEDED(sqstd_loadfile(v,filename,printerror,show_warnings)))
  435. return 1;
  436. return SQ_ERROR; //propagates the error
  437. }
  438. SQInteger _g_io_writeclosuretofile(HSQUIRRELVM v)
  439. {
  440. const SQChar *filename;
  441. sq_getstring(v,2,&filename);
  442. if(SQ_SUCCEEDED(sqstd_writeclosuretofile(v,filename)))
  443. return 1;
  444. return SQ_ERROR; //propagates the error
  445. }
  446. #include "sqstdblobimpl.h"
  447. SQInteger blob_write(SQUserPointer file,SQUserPointer p,SQInteger size);
  448. SQInteger _g_io_dumpclosure(HSQUIRRELVM v)
  449. {
  450. SQBlob b(0,8192);
  451. if(SQ_SUCCEEDED(sq_writeclosure(v,blob_write,&b))) {
  452. sq_pushstring(v, (const SQChar*)b.GetBuf(), b.Len());
  453. return 1;
  454. }
  455. return SQ_ERROR; //forward the error
  456. }
  457. SQInteger blob_read(SQUserPointer file,SQUserPointer p,SQInteger size);
  458. SQInteger _g_io_loadstring(HSQUIRRELVM v)
  459. {
  460. if(sq_gettype(v, 2) != OT_STRING) return sq_throwerror(v, _SC("string expected as parameter"));
  461. SQInteger rc, size = sq_getsize(v, 2);
  462. const SQChar *dump;
  463. sq_getstring(v, 2, &dump);
  464. unsigned short tag = *((unsigned short*)dump);
  465. if(tag == SQ_BYTECODE_STREAM_TAG){
  466. SQBlob b(0, size);
  467. b.Write(dump, size);
  468. b.Seek(0, SQ_SEEK_SET);
  469. rc = sq_readclosure(v, blob_read, &b);
  470. }
  471. else
  472. {
  473. rc = sq_compilebuffer(v, dump, size, _SC("loadstring"), SQFalse, SQFalse, SQ_MAX_INCLUDE_FILES);
  474. }
  475. return rc < 0 ? rc : 1;
  476. }
  477. SQInteger _g_io_dostring(HSQUIRRELVM v)
  478. {
  479. SQ_FUNC_VARS(v);
  480. SQInteger rc = _g_io_loadstring(v);
  481. if(rc < 0) return rc;
  482. SQ_OPT_BOOL(v, 3, retval, SQFalse);
  483. sq_push(v,1); //this environment
  484. if(SQ_SUCCEEDED(sq_call(v,1,retval,SQTrue))) {
  485. sq_remove(v,retval?-2:-1); //removes the closure
  486. return 1;
  487. }
  488. sq_pop(v,1); //removes the closure
  489. return SQ_ERROR; //forward the error
  490. }
  491. SQInteger _g_io_dofile(HSQUIRRELVM v)
  492. {
  493. SQ_FUNC_VARS(v);
  494. SQ_GET_STRING(v, 2, filename);
  495. SQ_OPT_BOOL(v, 3, printerror, SQFalse);
  496. SQ_OPT_BOOL(v, 4, show_warnings, SQTrue);
  497. sq_push(v,1); //repush the this
  498. if(SQ_SUCCEEDED(sqstd_dofile(v,filename,SQTrue,printerror,show_warnings)))
  499. return 1;
  500. return SQ_ERROR; //propagates the error
  501. }
  502. SQInteger _g_io_existsfile(HSQUIRRELVM v)
  503. {
  504. SQ_FUNC_VARS_NO_TOP(v);
  505. SQ_GET_STRING(v, 2, filename);
  506. SQFile fs;
  507. sq_pushbool(v, fs.Open(filename, "rb"));
  508. return 1;
  509. }
  510. SQInteger _g_io_readfile(HSQUIRRELVM v)
  511. {
  512. SQ_FUNC_VARS_NO_TOP(v);
  513. SQ_GET_STRING(v, 2, filename);
  514. SQFile fs;
  515. if(fs.Open(filename, "rb"))
  516. {
  517. SQInteger size,res;
  518. SQChar *data;
  519. size = fs.Len();
  520. data = sq_getscratchpad(v,size);
  521. res = fs.Read(data,size);
  522. if(res <= 0)
  523. return sq_throwerror(v,_SC("no data left to read"));
  524. sq_pushstring(v,data,res);
  525. return 1;
  526. }
  527. return sq_throwerror(v,_SC("could not open file %s"), filename);
  528. }
  529. SQInteger _g_io_writefile(HSQUIRRELVM v)
  530. {
  531. SQ_FUNC_VARS_NO_TOP(v);
  532. SQ_GET_STRING(v, 2, filename);
  533. SQ_GET_STRING(v, 3, data);
  534. SQFile fs;
  535. if(fs.Open(filename, "wb"))
  536. {
  537. SQInteger res = fs.Write(data, data_size);
  538. if(res != data_size)
  539. return sq_throwerror(v,_SC("could not write to file"));
  540. return 0;
  541. }
  542. return sq_throwerror(v,_SC("could not open file %s"), filename);
  543. }
  544. #define _DECL_GLOBALIO_FUNC(name,nparams,typecheck) {_SC(#name),_g_io_##name,nparams,typecheck}
  545. static const SQRegFunction iolib_funcs[]={
  546. _DECL_GLOBALIO_FUNC(loadfile,-2,_SC(".sbb")),
  547. _DECL_GLOBALIO_FUNC(dofile,-2,_SC(".sbb")),
  548. _DECL_GLOBALIO_FUNC(writeclosuretofile,3,_SC(".sc")),
  549. _DECL_GLOBALIO_FUNC(dostring,-2,_SC(".sb")),
  550. _DECL_GLOBALIO_FUNC(loadstring,2,_SC(".s")),
  551. _DECL_GLOBALIO_FUNC(dumpclosure,3,_SC(".sc")),
  552. _DECL_GLOBALIO_FUNC(existsfile,2,_SC(".s")),
  553. _DECL_GLOBALIO_FUNC(readfile,2,_SC(".s")),
  554. _DECL_GLOBALIO_FUNC(writefile,3,_SC(".ss")),
  555. {NULL,(SQFUNCTION)0,0,NULL}
  556. };
  557. SQRESULT sqstd_register_iolib(HSQUIRRELVM v)
  558. {
  559. //create delegate
  560. declare_stream(v,_SC("popen"),(SQUserPointer)SQSTD_FILE_TYPE_TAG,SQSTD_FILE_CLASS_TYPE_TAG,_popen_methods,iolib_funcs);
  561. declare_stream(v,_SC("file"),(SQUserPointer)SQSTD_FILE_TYPE_TAG,SQSTD_FILE_CLASS_TYPE_TAG,_file_methods,iolib_funcs);
  562. sq_pushstring(v,_SC("stdout"),-1);
  563. sqstd_createfile(v,stdout,SQFalse);
  564. sq_newslot(v,-3,SQFalse);
  565. sq_pushstring(v,_SC("stdin"),-1);
  566. sqstd_createfile(v,stdin,SQFalse);
  567. sq_newslot(v,-3,SQFalse);
  568. sq_pushstring(v,_SC("stderr"),-1);
  569. sqstd_createfile(v,stderr,SQFalse);
  570. sq_newslot(v,-3,SQFalse);
  571. return SQ_OK;
  572. }