sqstdblob.cpp 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462
  1. /* see copyright notice in squirrel.h */
  2. #include <new>
  3. #include <squirrel.h>
  4. #include <sqstdio.h>
  5. #include <string.h>
  6. #include <sqstdblob.h>
  7. #include "sqstdstream.h"
  8. #include "sqstdblobimpl.h"
  9. //#define SQSTD_BLOB_TYPE_TAG (SQSTD_STREAM_TYPE_TAG | 0x00000002)
  10. static const SQChar SQSTD_BLOB_TYPE_TAG[] = _SC("std_stream_blob");
  11. //Blob
  12. SQUserPointer SQBlob::SQBlob_TAG = (SQUserPointer)SQSTD_BLOB_TYPE_TAG;
  13. SQBlob::SQBlob(SQInteger size, SQInteger allocated) {
  14. _size = size;
  15. _allocated = allocated > size ? allocated : size;
  16. _buf = (unsigned char *)sq_malloc(_allocated);
  17. memset(_buf, 0, _allocated);
  18. _ptr = 0;
  19. _owns = true;
  20. }
  21. SQBlob::~SQBlob() {
  22. if(_buf) sq_free(_buf, _allocated);
  23. }
  24. SQInteger SQBlob::Write(const void *buffer, SQInteger size) {
  25. if(!CanAdvance(size)) {
  26. GrowBufOf(_ptr + size - _size);
  27. }
  28. memcpy(&_buf[_ptr], buffer, size);
  29. _ptr += size;
  30. return size;
  31. }
  32. SQInteger SQBlob::WriteZstr(const char *zStr) {
  33. SQInteger size = strlen(zStr);
  34. return Write(zStr, size);
  35. }
  36. SQInteger SQBlob::WriteChar(const char c) {
  37. return Write(&c, 1);
  38. }
  39. SQInteger SQBlob::Read(void *buffer,SQInteger size) {
  40. SQInteger n = size;
  41. if(!CanAdvance(size)) {
  42. if((_size - _ptr) > 0)
  43. n = _size - _ptr;
  44. else return 0;
  45. }
  46. memcpy(buffer, &_buf[_ptr], n);
  47. _ptr += n;
  48. return n;
  49. }
  50. bool SQBlob::Resize(SQInteger n) {
  51. if(!_owns) return false;
  52. if(n != _allocated) {
  53. unsigned char *newbuf = (unsigned char *)sq_malloc(n);
  54. memset(newbuf,0,n);
  55. if(_size > n)
  56. memcpy(newbuf,_buf,n);
  57. else
  58. memcpy(newbuf,_buf,_size);
  59. sq_free(_buf,_allocated);
  60. _buf=newbuf;
  61. _allocated = n;
  62. if(_size > _allocated)
  63. _size = _allocated;
  64. if(_ptr > _size)
  65. _ptr = _size;
  66. }
  67. return true;
  68. }
  69. bool SQBlob::GrowBufOf(SQInteger n)
  70. {
  71. bool ret = true;
  72. if(_size + n > _allocated) {
  73. if(_size + n > _size * 2)
  74. ret = Resize(_size + n);
  75. else
  76. ret = Resize(_size * 2);
  77. }
  78. _size = _size + n;
  79. return ret;
  80. }
  81. SQInteger SQBlob::Seek(SQInteger offset, SQInteger origin) {
  82. switch(origin) {
  83. case SQ_SEEK_SET:
  84. if(offset > _size || offset < 0) return -1;
  85. _ptr = offset;
  86. break;
  87. case SQ_SEEK_CUR:
  88. if(_ptr + offset > _size || _ptr + offset < 0) return -1;
  89. _ptr += offset;
  90. break;
  91. case SQ_SEEK_END:
  92. if(_size + offset > _size || _size + offset < 0) return -1;
  93. _ptr = _size + offset;
  94. break;
  95. default: return -1;
  96. }
  97. return 0;
  98. }
  99. bool SQBlob::SetLen(SQInteger len){
  100. if(len <= _allocated || Resize(len)){
  101. _size = len;
  102. if(_ptr > _size)
  103. _ptr = _size;
  104. return true;
  105. }
  106. return false;
  107. }
  108. #define SETUP_BLOB(v) \
  109. SQBlob *self = NULL; \
  110. { if(SQ_FAILED(sq_getinstanceup(v,1,(SQUserPointer*)&self,(SQUserPointer)SQSTD_BLOB_TYPE_TAG))) \
  111. return sq_throwerror(v,_SC("invalid type tag")); } \
  112. if(!self || !self->IsValid()) \
  113. return sq_throwerror(v,_SC("the blob is invalid"));
  114. static SQRESULT _blob_resize(HSQUIRRELVM v)
  115. {
  116. SETUP_BLOB(v);
  117. SQInteger size;
  118. sq_getinteger(v,2,&size);
  119. if(!self->Resize(size))
  120. return sq_throwerror(v,_SC("resize failed"));
  121. return 0;
  122. }
  123. static SQRESULT _blob_reserve(HSQUIRRELVM v)
  124. {
  125. SETUP_BLOB(v);
  126. SQInteger size;
  127. sq_getinteger(v,2,&size);
  128. if(!self->GrowBufOf(size))
  129. return sq_throwerror(v,_SC("reserve failed"));
  130. return 0;
  131. }
  132. static void __swap_dword(unsigned int *n)
  133. {
  134. *n=(unsigned int)(((*n&0xFF000000)>>24) |
  135. ((*n&0x00FF0000)>>8) |
  136. ((*n&0x0000FF00)<<8) |
  137. ((*n&0x000000FF)<<24));
  138. }
  139. static void __swap_word(unsigned short *n)
  140. {
  141. *n=(unsigned short)((*n>>8)&0x00FF)| ((*n<<8)&0xFF00);
  142. }
  143. static SQRESULT _blob_swap4(HSQUIRRELVM v)
  144. {
  145. SETUP_BLOB(v);
  146. SQInteger num=(self->Len()-(self->Len()%4))>>2;
  147. unsigned int *t=(unsigned int *)self->GetBuf();
  148. for(SQInteger i = 0; i < num; i++) {
  149. __swap_dword(&t[i]);
  150. }
  151. return 0;
  152. }
  153. static SQRESULT _blob_swap2(HSQUIRRELVM v)
  154. {
  155. SETUP_BLOB(v);
  156. SQInteger num=(self->Len()-(self->Len()%2))>>1;
  157. unsigned short *t = (unsigned short *)self->GetBuf();
  158. for(SQInteger i = 0; i < num; i++) {
  159. __swap_word(&t[i]);
  160. }
  161. return 0;
  162. }
  163. static SQRESULT _blob_memset(HSQUIRRELVM v)
  164. {
  165. SQ_FUNC_VARS_NO_TOP(v);
  166. SETUP_BLOB(v);
  167. SQ_GET_INTEGER(v, 2, idx);
  168. SQ_GET_INTEGER(v, 3, val);
  169. SQ_GET_INTEGER(v, 4, size);
  170. if(idx < 0 || idx >= self->Len())
  171. return sq_throwerror(v,_SC("index out of range"));
  172. if(idx+size < 0 || idx+size >= self->Len())
  173. return sq_throwerror(v,_SC("index+size out of range"));
  174. memset(((unsigned char*)self->GetBuf())+idx, val, size);
  175. return 0;
  176. }
  177. static SQRESULT _blob__set(HSQUIRRELVM v)
  178. {
  179. SETUP_BLOB(v);
  180. SQInteger idx,val;
  181. sq_getinteger(v,2,&idx);
  182. sq_getinteger(v,3,&val);
  183. if(idx < 0 || idx >= self->Len())
  184. return sq_throwerror(v,_SC("index out of range"));
  185. ((unsigned char *)self->GetBuf())[idx] = (unsigned char) val;
  186. sq_push(v,3);
  187. return 1;
  188. }
  189. static SQRESULT _blob__get(HSQUIRRELVM v)
  190. {
  191. SETUP_BLOB(v);
  192. SQInteger idx;
  193. SQObjectType ptype = sq_gettype(v, 2);
  194. if( !(ptype & SQOBJECT_NUMERIC) ){
  195. //allow call metatable methods indexed by strings
  196. sq_reseterror(v);
  197. return SQ_ERROR;
  198. }
  199. sq_getinteger(v,2,&idx);
  200. if(idx < 0 || idx >= self->Len())
  201. return sq_throwerror(v,_SC("index out of range"));
  202. sq_pushinteger(v,((unsigned char *)self->GetBuf())[idx]);
  203. return 1;
  204. }
  205. static SQRESULT _blob__nexti(HSQUIRRELVM v)
  206. {
  207. SETUP_BLOB(v);
  208. if(sq_gettype(v,2) == OT_NULL) {
  209. sq_pushinteger(v, 0);
  210. return 1;
  211. }
  212. SQInteger idx;
  213. if(SQ_SUCCEEDED(sq_getinteger(v, 2, &idx))) {
  214. if(idx+1 < self->Len()) {
  215. sq_pushinteger(v, idx+1);
  216. return 1;
  217. }
  218. sq_pushnull(v);
  219. return 1;
  220. }
  221. return sq_throwerror(v,_SC("internal error (_nexti) wrong argument type"));
  222. }
  223. static SQRESULT _blob__typeof(HSQUIRRELVM v)
  224. {
  225. sq_pushstring(v,_SC("blob"),-1);
  226. return 1;
  227. }
  228. static SQRESULT _blob_releasehook(SQUserPointer p, SQInteger size, HSQUIRRELVM v)
  229. {
  230. SQBlob *self = (SQBlob*)p;
  231. self->~SQBlob();
  232. sq_free(self,sizeof(SQBlob));
  233. return 1;
  234. }
  235. static SQRESULT _blob_constructor(HSQUIRRELVM v)
  236. {
  237. SQInteger nparam = sq_gettop(v);
  238. SQInteger size = 0, allocate = 0;
  239. if(nparam >= 2) {
  240. sq_getinteger(v, 2, &size);
  241. }
  242. if(nparam >= 3) {
  243. sq_getinteger(v, 2, &allocate);
  244. }
  245. if(size < 0) return sq_throwerror(v, _SC("cannot create blob with negative size"));
  246. if(allocate < 0) return sq_throwerror(v, _SC("cannot create blob with negative allocate"));
  247. //SQBlob *b = new SQBlob(size);
  248. SQBlob *b = new (sq_malloc(sizeof(SQBlob)))SQBlob(size, allocate);
  249. if(SQ_FAILED(sq_setinstanceup(v,1,b))) {
  250. b->~SQBlob();
  251. sq_free(b,sizeof(SQBlob));
  252. return sq_throwerror(v, _SC("cannot create blob"));
  253. }
  254. sq_setreleasehook(v,1,_blob_releasehook);
  255. return 0;
  256. }
  257. static SQRESULT _blob__cloned(HSQUIRRELVM v)
  258. {
  259. SQBlob *other = NULL;
  260. {
  261. if(SQ_FAILED(sq_getinstanceup(v,2,(SQUserPointer*)&other,(SQUserPointer)SQSTD_BLOB_TYPE_TAG)))
  262. return SQ_ERROR;
  263. }
  264. //SQBlob *thisone = new SQBlob(other->Len());
  265. SQBlob *thisone = new (sq_malloc(sizeof(SQBlob)))SQBlob(other->Len());
  266. memcpy(thisone->GetBuf(),other->GetBuf(),thisone->Len());
  267. if(SQ_FAILED(sq_setinstanceup(v,1,thisone))) {
  268. thisone->~SQBlob();
  269. sq_free(thisone,sizeof(SQBlob));
  270. return sq_throwerror(v, _SC("cannot clone blob"));
  271. }
  272. sq_setreleasehook(v,1,_blob_releasehook);
  273. return 0;
  274. }
  275. static SQRESULT _blob__tostring(HSQUIRRELVM v)
  276. {
  277. SETUP_BLOB(v);
  278. sq_pushstring(v, (const SQChar*)self->GetBuf(), self->Len());
  279. return 1;
  280. }
  281. static SQRESULT _blob_tostring(HSQUIRRELVM v)
  282. {
  283. return _blob__tostring(v);
  284. }
  285. static SQRESULT _blob_setLen(HSQUIRRELVM v)
  286. {
  287. SQ_FUNC_VARS_NO_TOP(v);
  288. SETUP_BLOB(v);
  289. SQ_GET_INTEGER(v, 2, newLen);
  290. self->SetLen(newLen);
  291. return 0;
  292. }
  293. static SQRESULT _blob_clear(HSQUIRRELVM v)
  294. {
  295. SETUP_BLOB(v);
  296. self->SetLen(0);
  297. return 0;
  298. }
  299. #define _DECL_BLOB_FUNC(name,nparams,typecheck) {_SC(#name),_blob_##name,nparams,typecheck}
  300. static SQRegFunction _blob_methods[] = {
  301. _DECL_BLOB_FUNC(constructor,-1,_SC("xnn")),
  302. _DECL_BLOB_FUNC(resize,2,_SC("xn")),
  303. _DECL_BLOB_FUNC(reserve,2,_SC("xn")),
  304. _DECL_BLOB_FUNC(swap2,1,_SC("x")),
  305. _DECL_BLOB_FUNC(swap4,1,_SC("x")),
  306. _DECL_BLOB_FUNC(memset,4,_SC("xiii")),
  307. _DECL_BLOB_FUNC(_set,3,_SC("xnn")),
  308. _DECL_BLOB_FUNC(_get,2,_SC("x n|s")), //allow call metatable methods indexed by strings
  309. _DECL_BLOB_FUNC(_typeof,1,_SC("x")),
  310. _DECL_BLOB_FUNC(_nexti,2,_SC("x")),
  311. _DECL_BLOB_FUNC(_cloned,2,_SC("xx")),
  312. //_DECL_BLOB_FUNC(_tostring,1,_SC("x")),
  313. _DECL_BLOB_FUNC(tostring,1,_SC("x")),
  314. _DECL_BLOB_FUNC(setLen,2,_SC("xi")),
  315. _DECL_BLOB_FUNC(clear,1,_SC("x")),
  316. {0,0,0,0}
  317. };
  318. //GLOBAL FUNCTIONS
  319. static SQRESULT _g_blob_casti2f(HSQUIRRELVM v)
  320. {
  321. SQInteger i;
  322. sq_getinteger(v,2,&i);
  323. sq_pushfloat(v,*((SQFloat *)&i));
  324. return 1;
  325. }
  326. static SQRESULT _g_blob_castf2i(HSQUIRRELVM v)
  327. {
  328. SQFloat f;
  329. sq_getfloat(v,2,&f);
  330. sq_pushinteger(v,*((SQInteger *)&f));
  331. return 1;
  332. }
  333. static SQRESULT _g_blob_swap2(HSQUIRRELVM v)
  334. {
  335. SQInteger i;
  336. sq_getinteger(v,2,&i);
  337. short s=(short)i;
  338. sq_pushinteger(v,(s<<8)|((s>>8)&0x00FF));
  339. return 1;
  340. }
  341. static SQRESULT _g_blob_swap4(HSQUIRRELVM v)
  342. {
  343. SQInteger i;
  344. sq_getinteger(v,2,&i);
  345. unsigned int t4 = (unsigned int)i;
  346. __swap_dword(&t4);
  347. sq_pushinteger(v,(SQInteger)t4);
  348. return 1;
  349. }
  350. static SQRESULT _g_blob_swapfloat(HSQUIRRELVM v)
  351. {
  352. SQFloat f;
  353. sq_getfloat(v,2,&f);
  354. __swap_dword((unsigned int *)&f);
  355. sq_pushfloat(v,f);
  356. return 1;
  357. }
  358. #define _DECL_GLOBALBLOB_FUNC(name,nparams,typecheck) {_SC(#name),_g_blob_##name,nparams,typecheck}
  359. static SQRegFunction bloblib_funcs[]={
  360. _DECL_GLOBALBLOB_FUNC(casti2f,2,_SC(".n")),
  361. _DECL_GLOBALBLOB_FUNC(castf2i,2,_SC(".n")),
  362. _DECL_GLOBALBLOB_FUNC(swap2,2,_SC(".n")),
  363. _DECL_GLOBALBLOB_FUNC(swap4,2,_SC(".n")),
  364. _DECL_GLOBALBLOB_FUNC(swapfloat,2,_SC(".n")),
  365. {0,0}
  366. };
  367. SQRESULT sqstd_getblob(HSQUIRRELVM v,SQInteger idx,SQUserPointer *ptr)
  368. {
  369. SQBlob *blob;
  370. if(SQ_FAILED(sq_getinstanceup(v,idx,(SQUserPointer *)&blob,(SQUserPointer)SQSTD_BLOB_TYPE_TAG)))
  371. return -1;
  372. *ptr = blob->GetBuf();
  373. return SQ_OK;
  374. }
  375. SQInteger sqstd_getblobsize(HSQUIRRELVM v,SQInteger idx)
  376. {
  377. SQBlob *blob;
  378. if(SQ_FAILED(sq_getinstanceup(v,idx,(SQUserPointer *)&blob,(SQUserPointer)SQSTD_BLOB_TYPE_TAG)))
  379. return -1;
  380. return blob->Len();
  381. }
  382. SQInteger blob_read(SQUserPointer file,SQUserPointer buf,SQInteger size)
  383. {
  384. SQInteger ret;
  385. SQBlob *blob = (SQBlob *)file;
  386. if( ( ret = blob->Read(buf, size)) !=0 ) return ret;
  387. return -1;
  388. }
  389. SQInteger blob_write(SQUserPointer file,SQUserPointer p,SQInteger size)
  390. {
  391. SQBlob *blob = (SQBlob *)file;
  392. return blob->Write(p,size);
  393. }
  394. SQUserPointer sqstd_createblob(HSQUIRRELVM v, SQInteger size)
  395. {
  396. SQInteger top = sq_gettop(v);
  397. sq_pushregistrytable(v);
  398. sq_pushstring(v,_SC("std_blob"),-1);
  399. if(SQ_SUCCEEDED(sq_get(v,-2))) {
  400. sq_remove(v,-2); //removes the registry
  401. sq_push(v,1); // push the this
  402. sq_pushinteger(v,size); //size
  403. SQBlob *blob = NULL;
  404. if(SQ_SUCCEEDED(sq_call(v,2,SQTrue,SQFalse))
  405. && SQ_SUCCEEDED(sq_getinstanceup(v,-1,(SQUserPointer *)&blob,(SQUserPointer)SQSTD_BLOB_TYPE_TAG))) {
  406. sq_remove(v,-2);
  407. return blob->GetBuf();
  408. }
  409. }
  410. sq_settop(v,top);
  411. return NULL;
  412. }
  413. SQRESULT sqstd_register_bloblib(HSQUIRRELVM v)
  414. {
  415. return declare_stream(v,_SC("blob"),(SQUserPointer)SQSTD_BLOB_TYPE_TAG,_SC("std_blob"),_blob_methods,bloblib_funcs);
  416. }