sqstdstream.cpp 8.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371
  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 size;
  116. SETUP_STREAM(v);
  117. if(SQ_FAILED(sq_tostring(v,2)))
  118. return sq_throwerror(v,_SC("invalid parameter"));
  119. sq_getstring(v,-1,&str);
  120. size = sq_getsize(v,-1);
  121. if(self->Write((SQChar*)str,size) != size)
  122. return sq_throwerror(v,_SC("io error"));
  123. sq_poptop(v); //remove converted string
  124. sq_pushinteger(v,size);
  125. return 1;
  126. }
  127. SQInteger _stream_writeblob(HSQUIRRELVM v)
  128. {
  129. SQUserPointer data;
  130. SQInteger size;
  131. SETUP_STREAM(v);
  132. if(SQ_FAILED(sqstd_getblob(v,2,&data)))
  133. return sq_throwerror(v,_SC("invalid parameter"));
  134. size = sqstd_getblobsize(v,2);
  135. if(self->Write(data,size) != size)
  136. return sq_throwerror(v,_SC("io error"));
  137. sq_pushinteger(v,size);
  138. return 1;
  139. }
  140. SQInteger _stream_writen(HSQUIRRELVM v)
  141. {
  142. SETUP_STREAM(v);
  143. SQInteger format, ti;
  144. SQFloat tf;
  145. sq_getinteger(v, 3, &format);
  146. switch(format) {
  147. case 'l': {
  148. SQInteger i;
  149. sq_getinteger(v, 2, &ti);
  150. i = ti;
  151. self->Write(&i, sizeof(SQInteger));
  152. }
  153. break;
  154. case 'i': {
  155. SQInt32 i;
  156. sq_getinteger(v, 2, &ti);
  157. i = (SQInt32)ti;
  158. self->Write(&i, sizeof(SQInt32));
  159. }
  160. break;
  161. case 's': {
  162. short s;
  163. sq_getinteger(v, 2, &ti);
  164. s = (short)ti;
  165. self->Write(&s, sizeof(short));
  166. }
  167. break;
  168. case 'w': {
  169. unsigned short w;
  170. sq_getinteger(v, 2, &ti);
  171. w = (unsigned short)ti;
  172. self->Write(&w, sizeof(unsigned short));
  173. }
  174. break;
  175. case 'c': {
  176. char c;
  177. sq_getinteger(v, 2, &ti);
  178. c = (char)ti;
  179. self->Write(&c, sizeof(char));
  180. }
  181. break;
  182. case 'b': {
  183. unsigned char b;
  184. sq_getinteger(v, 2, &ti);
  185. b = (unsigned char)ti;
  186. self->Write(&b, sizeof(unsigned char));
  187. }
  188. break;
  189. case 'f': {
  190. float f;
  191. sq_getfloat(v, 2, &tf);
  192. f = (float)tf;
  193. self->Write(&f, sizeof(float));
  194. }
  195. break;
  196. case 'd': {
  197. double d;
  198. sq_getfloat(v, 2, &tf);
  199. d = tf;
  200. self->Write(&d, sizeof(double));
  201. }
  202. break;
  203. default:
  204. return sq_throwerror(v, _SC("invalid format"));
  205. }
  206. return 0;
  207. }
  208. SQInteger _stream_seek(HSQUIRRELVM v)
  209. {
  210. SETUP_STREAM(v);
  211. SQInteger offset, origin = SQ_SEEK_SET;
  212. sq_getinteger(v, 2, &offset);
  213. if(sq_gettop(v) > 2) {
  214. SQInteger t;
  215. sq_getinteger(v, 3, &t);
  216. switch(t) {
  217. case 'b': origin = SQ_SEEK_SET; break;
  218. case 'c': origin = SQ_SEEK_CUR; break;
  219. case 'e': origin = SQ_SEEK_END; break;
  220. default: return sq_throwerror(v,_SC("invalid origin"));
  221. }
  222. }
  223. sq_pushinteger(v, self->Seek(offset, origin));
  224. return 1;
  225. }
  226. SQInteger _stream_tell(HSQUIRRELVM v)
  227. {
  228. SETUP_STREAM(v);
  229. sq_pushinteger(v, self->Tell());
  230. return 1;
  231. }
  232. SQInteger _stream_len(HSQUIRRELVM v)
  233. {
  234. SETUP_STREAM(v);
  235. sq_pushinteger(v, self->Len());
  236. return 1;
  237. }
  238. SQInteger _stream_flush(HSQUIRRELVM v)
  239. {
  240. SETUP_STREAM(v);
  241. if(!self->Flush())
  242. sq_pushinteger(v, 1);
  243. else
  244. sq_pushnull(v);
  245. return 1;
  246. }
  247. SQInteger _stream_eos(HSQUIRRELVM v)
  248. {
  249. SETUP_STREAM(v);
  250. if(self->EOS())
  251. sq_pushinteger(v, 1);
  252. else
  253. sq_pushnull(v);
  254. return 1;
  255. }
  256. SQInteger _stream__cloned(HSQUIRRELVM v)
  257. {
  258. return sq_throwerror(v,_SC("this object cannot be cloned"));
  259. }
  260. static SQRegFunction _stream_methods[] = {
  261. _DECL_STREAM_FUNC(read,2,_SC("xn")),
  262. _DECL_STREAM_FUNC(readblob,2,_SC("xn")),
  263. _DECL_STREAM_FUNC(readn,2,_SC("xn")),
  264. _DECL_STREAM_FUNC(write,2,_SC("x.")),
  265. _DECL_STREAM_FUNC(writeblob,-2,_SC("xx")),
  266. _DECL_STREAM_FUNC(writen,3,_SC("xnn")),
  267. _DECL_STREAM_FUNC(seek,-2,_SC("xnn")),
  268. _DECL_STREAM_FUNC(tell,1,_SC("x")),
  269. _DECL_STREAM_FUNC(len,1,_SC("x")),
  270. _DECL_STREAM_FUNC(eos,1,_SC("x")),
  271. _DECL_STREAM_FUNC(flush,1,_SC("x")),
  272. _DECL_STREAM_FUNC(_cloned,0,NULL),
  273. {0,0}
  274. };
  275. void init_streamclass(HSQUIRRELVM v)
  276. {
  277. sq_pushregistrytable(v);
  278. sq_pushstring(v,_SC("std_stream"),-1);
  279. if(SQ_FAILED(sq_get(v,-2))) {
  280. sq_pushstring(v,_SC("std_stream"),-1);
  281. sq_newclass(v,SQFalse);
  282. sq_settypetag(v,-1,(SQUserPointer)SQSTD_STREAM_TYPE_TAG);
  283. SQInteger i = 0;
  284. while(_stream_methods[i].name != 0) {
  285. SQRegFunction &f = _stream_methods[i];
  286. sq_pushstring(v,f.name,-1);
  287. sq_newclosure(v,f.f,0);
  288. sq_setparamscheck(v,f.nparamscheck,f.typemask);
  289. sq_newslot(v,-3,SQFalse);
  290. i++;
  291. }
  292. sq_newslot(v,-3,SQFalse);
  293. sq_pushroottable(v);
  294. sq_pushstring(v,_SC("stream"),-1);
  295. sq_pushstring(v,_SC("std_stream"),-1);
  296. sq_get(v,-4);
  297. sq_newslot(v,-3,SQFalse);
  298. sq_pop(v,1);
  299. }
  300. else {
  301. sq_pop(v,1); //result
  302. }
  303. sq_pop(v,1);
  304. }
  305. SQRESULT declare_stream(HSQUIRRELVM v,const SQChar* name,SQUserPointer typetag,const SQChar* reg_name,SQRegFunction *methods,SQRegFunction *globals)
  306. {
  307. if(sq_gettype(v,-1) != OT_TABLE)
  308. return sq_throwerror(v,_SC("table expected"));
  309. SQInteger top = sq_gettop(v);
  310. //create delegate
  311. init_streamclass(v);
  312. sq_pushregistrytable(v);
  313. sq_pushstring(v,reg_name,-1);
  314. sq_pushstring(v,_SC("std_stream"),-1);
  315. if(SQ_SUCCEEDED(sq_get(v,-3))) {
  316. sq_newclass(v,SQTrue);
  317. sq_settypetag(v,-1,typetag);
  318. SQInteger i = 0;
  319. while(methods[i].name != 0) {
  320. SQRegFunction &f = methods[i];
  321. sq_pushstring(v,f.name,-1);
  322. sq_newclosure(v,f.f,0);
  323. sq_setparamscheck(v,f.nparamscheck,f.typemask);
  324. sq_setnativeclosurename(v,-1,f.name);
  325. sq_newslot(v,-3,SQFalse);
  326. i++;
  327. }
  328. sq_newslot(v,-3,SQFalse);
  329. sq_pop(v,1);
  330. i = 0;
  331. while(globals[i].name!=0)
  332. {
  333. SQRegFunction &f = globals[i];
  334. sq_pushstring(v,f.name,-1);
  335. sq_newclosure(v,f.f,0);
  336. sq_setparamscheck(v,f.nparamscheck,f.typemask);
  337. sq_setnativeclosurename(v,-1,f.name);
  338. sq_newslot(v,-3,SQFalse);
  339. i++;
  340. }
  341. //register the class in the target table
  342. sq_pushstring(v,name,-1);
  343. sq_pushregistrytable(v);
  344. sq_pushstring(v,reg_name,-1);
  345. sq_get(v,-2);
  346. sq_remove(v,-2);
  347. sq_newslot(v,-3,SQFalse);
  348. sq_settop(v,top);
  349. return SQ_OK;
  350. }
  351. sq_settop(v,top);
  352. return SQ_ERROR;
  353. }