sqstdstream.cpp 8.8 KB

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