sqstdstream.cpp 10.0 KB

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