sqstdstream.cpp 10 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458
  1. /* see copyright notice in squirrel.h */
  2. #include <new>
  3. #include <stdio.h>
  4. #include <stdlib.h>
  5. #include <string.h>
  6. #include <squirrel.h>
  7. #include <sqstdio.h>
  8. #include <sqstdblob.h>
  9. #include "sqstdstream.h"
  10. #include "sqstdblobimpl.h"
  11. static const SQChar SQSTD_STREAM_TYPE_TAG[] = _SC("std_stream");
  12. #define SETUP_STREAM(v) \
  13. SQStream *self = NULL; \
  14. if(SQ_FAILED(sq_getinstanceup(v,1,(SQUserPointer*)&self,(SQUserPointer)SQSTD_STREAM_TYPE_TAG))) \
  15. return sq_throwerror(v,_SC("invalid type tag")); \
  16. if(!self || !self->IsValid()) \
  17. return sq_throwerror(v,_SC("the stream is invalid"));
  18. SQInteger _stream_read_line(HSQUIRRELVM v) {
  19. SETUP_STREAM(v);
  20. SQChar c = _SC('\0'), nl = _SC('\n');
  21. int m = 0, len = sizeof(SQChar);
  22. SQInteger start_pos = self->Tell();
  23. SQInteger read_size = 0, size;
  24. //optional expected line size
  25. if(sq_gettop(v) > 1) sq_getinteger(v,2,&size);
  26. else size = 2048;
  27. SQChar *buf = sq_getscratchpad(v, size);
  28. while(!self->EOS() && c != nl){
  29. read_size = self->Read(buf, size);
  30. if(read_size == 0) break;
  31. for(int i=0; i<read_size; ++i){
  32. if(buf[i] == nl){
  33. read_size = i+1;
  34. c = nl;
  35. goto done;
  36. }
  37. }
  38. if(read_size == size) ++m; //end of file read_size < size ?
  39. }
  40. done:
  41. read_size += (m*size);
  42. if(read_size > 0) {
  43. if(read_size > size){
  44. buf = sq_getscratchpad(v, read_size);
  45. self->Seek(start_pos, SQ_SEEK_SET);
  46. self->Read(buf, read_size);
  47. }
  48. else self->Seek(start_pos + read_size, SQ_SEEK_SET);
  49. sq_pushstring(v, buf, c == _SC('\n') ? read_size-len : read_size);
  50. }
  51. else sq_pushnull(v);
  52. return 1;
  53. }
  54. SQInteger _stream_read(HSQUIRRELVM v)
  55. {
  56. SETUP_STREAM(v);
  57. SQChar *data;
  58. SQInteger size,res;
  59. sq_getinteger(v,2,&size);
  60. /* DAD come back here
  61. if(self->GetHandle() != stdin && size > self->Len()) {
  62. size = self->Len();
  63. }
  64. */
  65. data = sq_getscratchpad(v,size);
  66. res = self->Read(data,size);
  67. if(res <= 0)
  68. return sq_throwerror(v,_SC("no data left to read"));
  69. sq_pushstring(v,data,res);
  70. return 1;
  71. }
  72. SQInteger _stream_readblob(HSQUIRRELVM v)
  73. {
  74. SETUP_STREAM(v);
  75. SQUserPointer blobp;
  76. SQInteger size,res;
  77. sq_getinteger(v,2,&size);
  78. if(size > self->Len()) {
  79. size = self->Len();
  80. }
  81. blobp = sqstd_createblob(v,size);
  82. res = self->Read(blobp,size);
  83. if(res <= 0)
  84. return sq_throwerror(v,_SC("no data left to read"));
  85. return 1;
  86. }
  87. #define SAFE_READN(ptr,len) { \
  88. if(self->Read(ptr,len) != len) return sq_throwerror(v,_SC("io error")); \
  89. }
  90. SQInteger _stream_readn(HSQUIRRELVM v)
  91. {
  92. SETUP_STREAM(v);
  93. SQInteger format;
  94. sq_getinteger(v, 2, &format);
  95. switch(format) {
  96. case 'l': {
  97. SQInteger i;
  98. SAFE_READN(&i, sizeof(i));
  99. sq_pushinteger(v, i);
  100. }
  101. break;
  102. case 'i': {
  103. SQInt32 i;
  104. SAFE_READN(&i, sizeof(i));
  105. sq_pushinteger(v, i);
  106. }
  107. break;
  108. case 's': {
  109. short s;
  110. SAFE_READN(&s, sizeof(short));
  111. sq_pushinteger(v, s);
  112. }
  113. break;
  114. case 'w': {
  115. unsigned short w;
  116. SAFE_READN(&w, sizeof(unsigned short));
  117. sq_pushinteger(v, w);
  118. }
  119. break;
  120. case 'c': {
  121. char c;
  122. SAFE_READN(&c, sizeof(char));
  123. sq_pushinteger(v, c);
  124. }
  125. break;
  126. case 'b': {
  127. unsigned char c;
  128. SAFE_READN(&c, sizeof(unsigned char));
  129. sq_pushinteger(v, c);
  130. }
  131. break;
  132. case 'f': {
  133. float f;
  134. SAFE_READN(&f, sizeof(float));
  135. sq_pushfloat(v, f);
  136. }
  137. break;
  138. case 'd': {
  139. double d;
  140. SAFE_READN(&d, sizeof(double));
  141. sq_pushfloat(v, (SQFloat)d);
  142. }
  143. break;
  144. default:
  145. return sq_throwerror(v, _SC("invalid format"));
  146. }
  147. return 1;
  148. }
  149. SQInteger _stream_write_str(HSQUIRRELVM v)
  150. {
  151. SQ_FUNC_VARS(v);
  152. SETUP_STREAM(v);
  153. SQ_GET_STRING(v, 2, str);
  154. SQ_OPT_INTEGER(v, 3, start, 0);
  155. if(start < 0 || start > str_size) return sq_throwerror(v, _SC("start position out of range (%d)"), start);
  156. SQ_OPT_INTEGER(v, 4, len, str_size - start);
  157. if(len < 0 || len > (str_size-start)) return sq_throwerror(v, _SC("len value out of range (%d)"), len);
  158. if(self->Write(((SQChar*)str)+start, len) != len)
  159. return sq_throwerror(v,_SC("io error"));
  160. sq_pushinteger(v,len);
  161. return 1;
  162. }
  163. SQInteger _stream_write(HSQUIRRELVM v)
  164. {
  165. const SQChar *str;
  166. SQInteger total_size, size;
  167. SETUP_STREAM(v);
  168. total_size = 0;
  169. for(SQInteger i=2, len=sq_gettop(v); i <= len; ++i){
  170. if(SQ_FAILED(sq_tostring(v,i)))
  171. return sq_throwerror(v,_SC("invalid parameter"));
  172. sq_getstring(v,-1,&str);
  173. size = sq_getsize(v,-1);
  174. if(self->Write((SQChar*)str,size) != size)
  175. return sq_throwerror(v,_SC("io error"));
  176. sq_poptop(v); //remove converted string
  177. total_size += size;
  178. }
  179. sq_pushinteger(v,total_size);
  180. return 1;
  181. }
  182. SQInteger _stream_write_non_null(HSQUIRRELVM v)
  183. {
  184. if(sq_gettype(v, 2) != OT_NULL)
  185. {
  186. return _stream_write(v);
  187. }
  188. return 0;
  189. }
  190. SQInteger _stream_write_fmt(HSQUIRRELVM v)
  191. {
  192. const SQChar *str;
  193. SQInteger size;
  194. SETUP_STREAM(v);
  195. if(SQ_FAILED(sq_tostring(v,2)))
  196. return sq_throwerror(v,_SC("invalid parameter"));
  197. sq_getstring(v,-1,&str);
  198. size = sq_getsize(v,-1);
  199. if(self->Write((SQChar*)str,size) != size)
  200. return sq_throwerror(v,_SC("io error"));
  201. sq_poptop(v); //remove converted string
  202. sq_pushinteger(v,size);
  203. return 1;
  204. }
  205. SQInteger _stream_writeblob(HSQUIRRELVM v)
  206. {
  207. SQUserPointer data;
  208. SQInteger size;
  209. SETUP_STREAM(v);
  210. if(SQ_FAILED(sqstd_getblob(v,2,&data)))
  211. return sq_throwerror(v,_SC("invalid parameter"));
  212. size = sqstd_getblobsize(v,2);
  213. if(self->Write(data,size) != size)
  214. return sq_throwerror(v,_SC("io error"));
  215. sq_pushinteger(v,size);
  216. return 1;
  217. }
  218. SQInteger _stream_writen(HSQUIRRELVM v)
  219. {
  220. SETUP_STREAM(v);
  221. SQInteger format, ti;
  222. SQFloat tf;
  223. sq_getinteger(v, 3, &format);
  224. switch(format) {
  225. case 'l': {
  226. SQInteger i;
  227. sq_getinteger(v, 2, &ti);
  228. i = ti;
  229. self->Write(&i, sizeof(SQInteger));
  230. }
  231. break;
  232. case 'i': {
  233. SQInt32 i;
  234. sq_getinteger(v, 2, &ti);
  235. i = (SQInt32)ti;
  236. self->Write(&i, sizeof(SQInt32));
  237. }
  238. break;
  239. case 's': {
  240. short s;
  241. sq_getinteger(v, 2, &ti);
  242. s = (short)ti;
  243. self->Write(&s, sizeof(short));
  244. }
  245. break;
  246. case 'w': {
  247. unsigned short w;
  248. sq_getinteger(v, 2, &ti);
  249. w = (unsigned short)ti;
  250. self->Write(&w, sizeof(unsigned short));
  251. }
  252. break;
  253. case 'c': {
  254. char c;
  255. sq_getinteger(v, 2, &ti);
  256. c = (char)ti;
  257. self->Write(&c, sizeof(char));
  258. }
  259. break;
  260. case 'b': {
  261. unsigned char b;
  262. sq_getinteger(v, 2, &ti);
  263. b = (unsigned char)ti;
  264. self->Write(&b, sizeof(unsigned char));
  265. }
  266. break;
  267. case 'f': {
  268. float f;
  269. sq_getfloat(v, 2, &tf);
  270. f = (float)tf;
  271. self->Write(&f, sizeof(float));
  272. }
  273. break;
  274. case 'd': {
  275. double d;
  276. sq_getfloat(v, 2, &tf);
  277. d = tf;
  278. self->Write(&d, sizeof(double));
  279. }
  280. break;
  281. default:
  282. return sq_throwerror(v, _SC("invalid format"));
  283. }
  284. return 0;
  285. }
  286. SQInteger _stream_seek(HSQUIRRELVM v)
  287. {
  288. SETUP_STREAM(v);
  289. SQInteger offset, origin = SQ_SEEK_SET;
  290. sq_getinteger(v, 2, &offset);
  291. if(sq_gettop(v) > 2) {
  292. SQInteger t;
  293. sq_getinteger(v, 3, &t);
  294. switch(t) {
  295. case 'b': origin = SQ_SEEK_SET; break;
  296. case 'c': origin = SQ_SEEK_CUR; break;
  297. case 'e': origin = SQ_SEEK_END; break;
  298. default: return sq_throwerror(v,_SC("invalid origin"));
  299. }
  300. }
  301. sq_pushinteger(v, self->Seek(offset, origin));
  302. return 1;
  303. }
  304. SQInteger _stream_tell(HSQUIRRELVM v)
  305. {
  306. SETUP_STREAM(v);
  307. sq_pushinteger(v, self->Tell());
  308. return 1;
  309. }
  310. SQInteger _stream_len(HSQUIRRELVM v)
  311. {
  312. SETUP_STREAM(v);
  313. sq_pushinteger(v, self->Len());
  314. return 1;
  315. }
  316. SQInteger _stream_flush(HSQUIRRELVM v)
  317. {
  318. SETUP_STREAM(v);
  319. if(!self->Flush())
  320. sq_pushinteger(v, 1);
  321. else
  322. sq_pushnull(v);
  323. return 1;
  324. }
  325. SQInteger _stream_eos(HSQUIRRELVM v)
  326. {
  327. SETUP_STREAM(v);
  328. if(self->EOS())
  329. sq_pushinteger(v, 1);
  330. else
  331. sq_pushnull(v);
  332. return 1;
  333. }
  334. SQInteger _stream__cloned(HSQUIRRELVM v)
  335. {
  336. return sq_throwerror(v,_SC("this object cannot be cloned"));
  337. }
  338. static SQRegFunction _stream_methods[] = {
  339. _DECL_STREAM_FUNC(read_line,-1,_SC("xi")),
  340. _DECL_STREAM_FUNC(read,2,_SC("xn")),
  341. _DECL_STREAM_FUNC(readblob,2,_SC("xn")),
  342. _DECL_STREAM_FUNC(readn,2,_SC("xn")),
  343. _DECL_STREAM_FUNC(write_str,-2,_SC("xsii")),
  344. _DECL_STREAM_FUNC(write,-2,_SC("x.")),
  345. _DECL_STREAM_FUNC(writeblob,-2,_SC("xx")),
  346. _DECL_STREAM_FUNC(writen,3,_SC("xnn")),
  347. _DECL_STREAM_FUNC(write_non_null,2,_SC("x.")),
  348. _DECL_STREAM_FUNC(seek,-2,_SC("xnn")),
  349. _DECL_STREAM_FUNC(tell,1,_SC("x")),
  350. _DECL_STREAM_FUNC(len,1,_SC("x")),
  351. _DECL_STREAM_FUNC(eos,1,_SC("x")),
  352. _DECL_STREAM_FUNC(flush,1,_SC("x")),
  353. _DECL_STREAM_FUNC(_cloned,0,NULL),
  354. {0,0}
  355. };
  356. void init_streamclass(HSQUIRRELVM v)
  357. {
  358. sq_pushregistrytable(v);
  359. sq_pushstring(v,SQSTD_STREAM_TYPE_TAG,-1);
  360. if(SQ_FAILED(sq_get(v,-2))) {
  361. sq_pushstring(v,SQSTD_STREAM_TYPE_TAG,-1);
  362. sq_newclass(v,SQFalse);
  363. sq_settypetag(v,-1,(SQUserPointer)SQSTD_STREAM_TYPE_TAG);
  364. SQInteger i = 0;
  365. while(_stream_methods[i].name != 0) {
  366. SQRegFunction &f = _stream_methods[i];
  367. sq_pushstring(v,f.name,-1);
  368. sq_newclosure(v,f.f,0);
  369. sq_setparamscheck(v,f.nparamscheck,f.typemask);
  370. sq_newslot(v,-3,SQFalse);
  371. i++;
  372. }
  373. sq_newslot(v,-3,SQFalse);
  374. sq_pushroottable(v);
  375. sq_pushstring(v,_SC("stream"),-1);
  376. sq_pushstring(v,_SC("std_stream"),-1);
  377. sq_get(v,-4);
  378. sq_newslot(v,-3,SQFalse);
  379. sq_pop(v,1);
  380. }
  381. else {
  382. sq_pop(v,1); //result
  383. }
  384. sq_pop(v,1);
  385. }
  386. SQRESULT declare_stream(HSQUIRRELVM v,const SQChar* name,SQUserPointer typetag,const SQChar* reg_name,SQRegFunction *methods,SQRegFunction *globals)
  387. {
  388. if(sq_gettype(v,-1) != OT_TABLE)
  389. return sq_throwerror(v,_SC("table expected"));
  390. SQInteger top = sq_gettop(v);
  391. //create delegate
  392. init_streamclass(v);
  393. sq_pushregistrytable(v);
  394. sq_pushstring(v,reg_name,-1);
  395. sq_pushstring(v,_SC("std_stream"),-1);
  396. if(SQ_SUCCEEDED(sq_get(v,-3))) {
  397. sq_newclass(v,SQTrue);
  398. sq_settypetag(v,-1,typetag);
  399. SQInteger i = 0;
  400. while(methods[i].name != 0) {
  401. SQRegFunction &f = methods[i];
  402. sq_pushstring(v,f.name,-1);
  403. sq_newclosure(v,f.f,0);
  404. sq_setparamscheck(v,f.nparamscheck,f.typemask);
  405. sq_setnativeclosurename(v,-1,f.name);
  406. sq_newslot(v,-3,SQFalse);
  407. i++;
  408. }
  409. sq_newslot(v,-3,SQFalse);
  410. sq_pop(v,1);
  411. i = 0;
  412. while(globals[i].name!=0)
  413. {
  414. SQRegFunction &f = globals[i];
  415. sq_pushstring(v,f.name,-1);
  416. sq_newclosure(v,f.f,0);
  417. sq_setparamscheck(v,f.nparamscheck,f.typemask);
  418. sq_setnativeclosurename(v,-1,f.name);
  419. sq_newslot(v,-3,SQFalse);
  420. i++;
  421. }
  422. //register the class in the target table
  423. sq_pushstring(v,name,-1);
  424. sq_pushregistrytable(v);
  425. sq_pushstring(v,reg_name,-1);
  426. sq_get(v,-2);
  427. sq_remove(v,-2);
  428. sq_newslot(v,-3,SQFalse);
  429. sq_settop(v,top);
  430. return SQ_OK;
  431. }
  432. sq_settop(v,top);
  433. return SQ_ERROR;
  434. }