sqstdio.cpp 16 KB

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