sqstdstream.cpp 11 KB

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