sqstdstream.cpp 10 KB

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