sqstdstream.cpp 9.4 KB

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