sqstdstream.cpp 10 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448
  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_fmt(HSQUIRRELVM v)
  183. {
  184. const SQChar *str;
  185. SQInteger size;
  186. SETUP_STREAM(v);
  187. if(SQ_FAILED(sq_tostring(v,2)))
  188. return sq_throwerror(v,_SC("invalid parameter"));
  189. sq_getstring(v,-1,&str);
  190. size = sq_getsize(v,-1);
  191. if(self->Write((SQChar*)str,size) != size)
  192. return sq_throwerror(v,_SC("io error"));
  193. sq_poptop(v); //remove converted string
  194. sq_pushinteger(v,size);
  195. return 1;
  196. }
  197. SQInteger _stream_writeblob(HSQUIRRELVM v)
  198. {
  199. SQUserPointer data;
  200. SQInteger size;
  201. SETUP_STREAM(v);
  202. if(SQ_FAILED(sqstd_getblob(v,2,&data)))
  203. return sq_throwerror(v,_SC("invalid parameter"));
  204. size = sqstd_getblobsize(v,2);
  205. if(self->Write(data,size) != size)
  206. return sq_throwerror(v,_SC("io error"));
  207. sq_pushinteger(v,size);
  208. return 1;
  209. }
  210. SQInteger _stream_writen(HSQUIRRELVM v)
  211. {
  212. SETUP_STREAM(v);
  213. SQInteger format, ti;
  214. SQFloat tf;
  215. sq_getinteger(v, 3, &format);
  216. switch(format) {
  217. case 'l': {
  218. SQInteger i;
  219. sq_getinteger(v, 2, &ti);
  220. i = ti;
  221. self->Write(&i, sizeof(SQInteger));
  222. }
  223. break;
  224. case 'i': {
  225. SQInt32 i;
  226. sq_getinteger(v, 2, &ti);
  227. i = (SQInt32)ti;
  228. self->Write(&i, sizeof(SQInt32));
  229. }
  230. break;
  231. case 's': {
  232. short s;
  233. sq_getinteger(v, 2, &ti);
  234. s = (short)ti;
  235. self->Write(&s, sizeof(short));
  236. }
  237. break;
  238. case 'w': {
  239. unsigned short w;
  240. sq_getinteger(v, 2, &ti);
  241. w = (unsigned short)ti;
  242. self->Write(&w, sizeof(unsigned short));
  243. }
  244. break;
  245. case 'c': {
  246. char c;
  247. sq_getinteger(v, 2, &ti);
  248. c = (char)ti;
  249. self->Write(&c, sizeof(char));
  250. }
  251. break;
  252. case 'b': {
  253. unsigned char b;
  254. sq_getinteger(v, 2, &ti);
  255. b = (unsigned char)ti;
  256. self->Write(&b, sizeof(unsigned char));
  257. }
  258. break;
  259. case 'f': {
  260. float f;
  261. sq_getfloat(v, 2, &tf);
  262. f = (float)tf;
  263. self->Write(&f, sizeof(float));
  264. }
  265. break;
  266. case 'd': {
  267. double d;
  268. sq_getfloat(v, 2, &tf);
  269. d = tf;
  270. self->Write(&d, sizeof(double));
  271. }
  272. break;
  273. default:
  274. return sq_throwerror(v, _SC("invalid format"));
  275. }
  276. return 0;
  277. }
  278. SQInteger _stream_seek(HSQUIRRELVM v)
  279. {
  280. SETUP_STREAM(v);
  281. SQInteger offset, origin = SQ_SEEK_SET;
  282. sq_getinteger(v, 2, &offset);
  283. if(sq_gettop(v) > 2) {
  284. SQInteger t;
  285. sq_getinteger(v, 3, &t);
  286. switch(t) {
  287. case 'b': origin = SQ_SEEK_SET; break;
  288. case 'c': origin = SQ_SEEK_CUR; break;
  289. case 'e': origin = SQ_SEEK_END; break;
  290. default: return sq_throwerror(v,_SC("invalid origin"));
  291. }
  292. }
  293. sq_pushinteger(v, self->Seek(offset, origin));
  294. return 1;
  295. }
  296. SQInteger _stream_tell(HSQUIRRELVM v)
  297. {
  298. SETUP_STREAM(v);
  299. sq_pushinteger(v, self->Tell());
  300. return 1;
  301. }
  302. SQInteger _stream_len(HSQUIRRELVM v)
  303. {
  304. SETUP_STREAM(v);
  305. sq_pushinteger(v, self->Len());
  306. return 1;
  307. }
  308. SQInteger _stream_flush(HSQUIRRELVM v)
  309. {
  310. SETUP_STREAM(v);
  311. if(!self->Flush())
  312. sq_pushinteger(v, 1);
  313. else
  314. sq_pushnull(v);
  315. return 1;
  316. }
  317. SQInteger _stream_eos(HSQUIRRELVM v)
  318. {
  319. SETUP_STREAM(v);
  320. if(self->EOS())
  321. sq_pushinteger(v, 1);
  322. else
  323. sq_pushnull(v);
  324. return 1;
  325. }
  326. SQInteger _stream__cloned(HSQUIRRELVM v)
  327. {
  328. return sq_throwerror(v,_SC("this object cannot be cloned"));
  329. }
  330. static SQRegFunction _stream_methods[] = {
  331. _DECL_STREAM_FUNC(read_line,-1,_SC("xi")),
  332. _DECL_STREAM_FUNC(read,2,_SC("xn")),
  333. _DECL_STREAM_FUNC(readblob,2,_SC("xn")),
  334. _DECL_STREAM_FUNC(readn,2,_SC("xn")),
  335. _DECL_STREAM_FUNC(write_str,-2,_SC("xsii")),
  336. _DECL_STREAM_FUNC(write,-2,_SC("x.")),
  337. _DECL_STREAM_FUNC(writeblob,-2,_SC("xx")),
  338. _DECL_STREAM_FUNC(writen,3,_SC("xnn")),
  339. _DECL_STREAM_FUNC(seek,-2,_SC("xnn")),
  340. _DECL_STREAM_FUNC(tell,1,_SC("x")),
  341. _DECL_STREAM_FUNC(len,1,_SC("x")),
  342. _DECL_STREAM_FUNC(eos,1,_SC("x")),
  343. _DECL_STREAM_FUNC(flush,1,_SC("x")),
  344. _DECL_STREAM_FUNC(_cloned,0,NULL),
  345. {0,0}
  346. };
  347. void init_streamclass(HSQUIRRELVM v)
  348. {
  349. sq_pushregistrytable(v);
  350. sq_pushstring(v,SQSTD_STREAM_TYPE_TAG,-1);
  351. if(SQ_FAILED(sq_get(v,-2))) {
  352. sq_pushstring(v,SQSTD_STREAM_TYPE_TAG,-1);
  353. sq_newclass(v,SQFalse);
  354. sq_settypetag(v,-1,(SQUserPointer)SQSTD_STREAM_TYPE_TAG);
  355. SQInteger i = 0;
  356. while(_stream_methods[i].name != 0) {
  357. SQRegFunction &f = _stream_methods[i];
  358. sq_pushstring(v,f.name,-1);
  359. sq_newclosure(v,f.f,0);
  360. sq_setparamscheck(v,f.nparamscheck,f.typemask);
  361. sq_newslot(v,-3,SQFalse);
  362. i++;
  363. }
  364. sq_newslot(v,-3,SQFalse);
  365. sq_pushroottable(v);
  366. sq_pushstring(v,_SC("stream"),-1);
  367. sq_pushstring(v,_SC("std_stream"),-1);
  368. sq_get(v,-4);
  369. sq_newslot(v,-3,SQFalse);
  370. sq_pop(v,1);
  371. }
  372. else {
  373. sq_pop(v,1); //result
  374. }
  375. sq_pop(v,1);
  376. }
  377. SQRESULT declare_stream(HSQUIRRELVM v,const SQChar* name,SQUserPointer typetag,const SQChar* reg_name,SQRegFunction *methods,SQRegFunction *globals)
  378. {
  379. if(sq_gettype(v,-1) != OT_TABLE)
  380. return sq_throwerror(v,_SC("table expected"));
  381. SQInteger top = sq_gettop(v);
  382. //create delegate
  383. init_streamclass(v);
  384. sq_pushregistrytable(v);
  385. sq_pushstring(v,reg_name,-1);
  386. sq_pushstring(v,_SC("std_stream"),-1);
  387. if(SQ_SUCCEEDED(sq_get(v,-3))) {
  388. sq_newclass(v,SQTrue);
  389. sq_settypetag(v,-1,typetag);
  390. SQInteger i = 0;
  391. while(methods[i].name != 0) {
  392. SQRegFunction &f = methods[i];
  393. sq_pushstring(v,f.name,-1);
  394. sq_newclosure(v,f.f,0);
  395. sq_setparamscheck(v,f.nparamscheck,f.typemask);
  396. sq_setnativeclosurename(v,-1,f.name);
  397. sq_newslot(v,-3,SQFalse);
  398. i++;
  399. }
  400. sq_newslot(v,-3,SQFalse);
  401. sq_pop(v,1);
  402. i = 0;
  403. while(globals[i].name!=0)
  404. {
  405. SQRegFunction &f = globals[i];
  406. sq_pushstring(v,f.name,-1);
  407. sq_newclosure(v,f.f,0);
  408. sq_setparamscheck(v,f.nparamscheck,f.typemask);
  409. sq_setnativeclosurename(v,-1,f.name);
  410. sq_newslot(v,-3,SQFalse);
  411. i++;
  412. }
  413. //register the class in the target table
  414. sq_pushstring(v,name,-1);
  415. sq_pushregistrytable(v);
  416. sq_pushstring(v,reg_name,-1);
  417. sq_get(v,-2);
  418. sq_remove(v,-2);
  419. sq_newslot(v,-3,SQFalse);
  420. sq_settop(v,top);
  421. return SQ_OK;
  422. }
  423. sq_settop(v,top);
  424. return SQ_ERROR;
  425. }