0001
0002 #include <new>
0003 #include <pscript.h>
0004 #include <psstdio.h>
0005 #include <string.h>
0006 #include <psstdblob.h>
0007 #include "psstdstream.h"
0008 #include "psstdblobimpl.h"
0009
0010 #define PSSTD_BLOB_TYPE_TAG (PSSTD_STREAM_TYPE_TAG | 0x00000002)
0011
0012
0013
0014
0015 #define SETUP_BLOB(v) \
0016 PSBlob *self = NULL; \
0017 { if(PS_FAILED(ps_getinstanceup(v,1,(PSUserPointer*)&self,(PSUserPointer)PSSTD_BLOB_TYPE_TAG))) \
0018 return ps_throwerror(v,_SC("invalid type tag")); } \
0019 if(!self || !self->IsValid()) \
0020 return ps_throwerror(v,_SC("the blob is invalid"));
0021
0022
0023 static PSInteger _blob_resize(HPSCRIPTVM v)
0024 {
0025 SETUP_BLOB(v);
0026 PSInteger size;
0027 ps_getinteger(v,2,&size);
0028 if(!self->Resize(size))
0029 return ps_throwerror(v,_SC("resize failed"));
0030 return 0;
0031 }
0032
0033 static void __swap_dword(unsigned int *n)
0034 {
0035 *n=(unsigned int)(((*n&0xFF000000)>>24) |
0036 ((*n&0x00FF0000)>>8) |
0037 ((*n&0x0000FF00)<<8) |
0038 ((*n&0x000000FF)<<24));
0039 }
0040
0041 static void __swap_word(unsigned short *n)
0042 {
0043 *n=(unsigned short)((*n>>8)&0x00FF)| ((*n<<8)&0xFF00);
0044 }
0045
0046 static PSInteger _blob_swap4(HPSCRIPTVM v)
0047 {
0048 SETUP_BLOB(v);
0049 PSInteger num=(self->Len()-(self->Len()%4))>>2;
0050 unsigned int *t=(unsigned int *)self->GetBuf();
0051 for(PSInteger i = 0; i < num; i++) {
0052 __swap_dword(&t[i]);
0053 }
0054 return 0;
0055 }
0056
0057 static PSInteger _blob_swap2(HPSCRIPTVM v)
0058 {
0059 SETUP_BLOB(v);
0060 PSInteger num=(self->Len()-(self->Len()%2))>>1;
0061 unsigned short *t = (unsigned short *)self->GetBuf();
0062 for(PSInteger i = 0; i < num; i++) {
0063 __swap_word(&t[i]);
0064 }
0065 return 0;
0066 }
0067
0068 static PSInteger _blob__set(HPSCRIPTVM v)
0069 {
0070 SETUP_BLOB(v);
0071 PSInteger idx,val;
0072 ps_getinteger(v,2,&idx);
0073 ps_getinteger(v,3,&val);
0074 if(idx < 0 || idx >= self->Len())
0075 return ps_throwerror(v,_SC("index out of range"));
0076 ((unsigned char *)self->GetBuf())[idx] = (unsigned char) val;
0077 ps_push(v,3);
0078 return 1;
0079 }
0080
0081 static PSInteger _blob__get(HPSCRIPTVM v)
0082 {
0083 SETUP_BLOB(v);
0084 PSInteger idx;
0085 ps_getinteger(v,2,&idx);
0086 if(idx < 0 || idx >= self->Len())
0087 return ps_throwerror(v,_SC("index out of range"));
0088 ps_pushinteger(v,((unsigned char *)self->GetBuf())[idx]);
0089 return 1;
0090 }
0091
0092 static PSInteger _blob__nexti(HPSCRIPTVM v)
0093 {
0094 SETUP_BLOB(v);
0095 if(ps_gettype(v,2) == OT_NULL) {
0096 ps_pushinteger(v, 0);
0097 return 1;
0098 }
0099 PSInteger idx;
0100 if(PS_SUCCEEDED(ps_getinteger(v, 2, &idx))) {
0101 if(idx+1 < self->Len()) {
0102 ps_pushinteger(v, idx+1);
0103 return 1;
0104 }
0105 ps_pushnull(v);
0106 return 1;
0107 }
0108 return ps_throwerror(v,_SC("internal error (_nexti) wrong argument type"));
0109 }
0110
0111 static PSInteger _blob__typeof(HPSCRIPTVM v)
0112 {
0113 ps_pushstring(v,_SC("blob"),-1);
0114 return 1;
0115 }
0116
0117 static PSInteger _blob_releasehook(PSUserPointer p, PSInteger PS_UNUSED_ARG(size))
0118 {
0119 PSBlob *self = (PSBlob*)p;
0120 self->~PSBlob();
0121 ps_free(self,sizeof(PSBlob));
0122 return 1;
0123 }
0124
0125 static PSInteger _blob_constructor(HPSCRIPTVM v)
0126 {
0127 PSInteger nparam = ps_gettop(v);
0128 PSInteger size = 0;
0129 if(nparam == 2) {
0130 ps_getinteger(v, 2, &size);
0131 }
0132 if(size < 0) return ps_throwerror(v, _SC("cannot create blob with negative size"));
0133
0134
0135 PSBlob *b = new (ps_malloc(sizeof(PSBlob)))PSBlob(size);
0136 if(PS_FAILED(ps_setinstanceup(v,1,b))) {
0137 b->~PSBlob();
0138 ps_free(b,sizeof(PSBlob));
0139 return ps_throwerror(v, _SC("cannot create blob"));
0140 }
0141 ps_setreleasehook(v,1,_blob_releasehook);
0142 return 0;
0143 }
0144
0145 static PSInteger _blob__cloned(HPSCRIPTVM v)
0146 {
0147 PSBlob *other = NULL;
0148 {
0149 if(PS_FAILED(ps_getinstanceup(v,2,(PSUserPointer*)&other,(PSUserPointer)PSSTD_BLOB_TYPE_TAG)))
0150 return PS_ERROR;
0151 }
0152
0153 PSBlob *thisone = new (ps_malloc(sizeof(PSBlob)))PSBlob(other->Len());
0154 memcpy(thisone->GetBuf(),other->GetBuf(),thisone->Len());
0155 if(PS_FAILED(ps_setinstanceup(v,1,thisone))) {
0156 thisone->~PSBlob();
0157 ps_free(thisone,sizeof(PSBlob));
0158 return ps_throwerror(v, _SC("cannot clone blob"));
0159 }
0160 ps_setreleasehook(v,1,_blob_releasehook);
0161 return 0;
0162 }
0163
0164 #define _DECL_BLOB_FUNC(name,nparams,typecheck) {_SC(#name),_blob_##name,nparams,typecheck}
0165 static const PSRegFunction _blob_methods[] = {
0166 _DECL_BLOB_FUNC(constructor,-1,_SC("xn")),
0167 _DECL_BLOB_FUNC(resize,2,_SC("xn")),
0168 _DECL_BLOB_FUNC(swap2,1,_SC("x")),
0169 _DECL_BLOB_FUNC(swap4,1,_SC("x")),
0170 _DECL_BLOB_FUNC(_set,3,_SC("xnn")),
0171 _DECL_BLOB_FUNC(_get,2,_SC("xn")),
0172 _DECL_BLOB_FUNC(_typeof,1,_SC("x")),
0173 _DECL_BLOB_FUNC(_nexti,2,_SC("x")),
0174 _DECL_BLOB_FUNC(_cloned,2,_SC("xx")),
0175 {NULL,(PSFUNCTION)0,0,NULL}
0176 };
0177
0178
0179
0180
0181
0182 static PSInteger _g_blob_casti2f(HPSCRIPTVM v)
0183 {
0184 PSInteger i;
0185 ps_getinteger(v,2,&i);
0186 ps_pushfloat(v,*((const PSFloat *)&i));
0187 return 1;
0188 }
0189
0190 static PSInteger _g_blob_castf2i(HPSCRIPTVM v)
0191 {
0192 PSFloat f;
0193 ps_getfloat(v,2,&f);
0194 ps_pushinteger(v,*((const PSInteger *)&f));
0195 return 1;
0196 }
0197
0198 static PSInteger _g_blob_swap2(HPSCRIPTVM v)
0199 {
0200 PSInteger i;
0201 ps_getinteger(v,2,&i);
0202 short s=(short)i;
0203 ps_pushinteger(v,(s<<8)|((s>>8)&0x00FF));
0204 return 1;
0205 }
0206
0207 static PSInteger _g_blob_swap4(HPSCRIPTVM v)
0208 {
0209 PSInteger i;
0210 ps_getinteger(v,2,&i);
0211 unsigned int t4 = (unsigned int)i;
0212 __swap_dword(&t4);
0213 ps_pushinteger(v,(PSInteger)t4);
0214 return 1;
0215 }
0216
0217 static PSInteger _g_blob_swapfloat(HPSCRIPTVM v)
0218 {
0219 PSFloat f;
0220 ps_getfloat(v,2,&f);
0221 __swap_dword((unsigned int *)&f);
0222 ps_pushfloat(v,f);
0223 return 1;
0224 }
0225
0226 #define _DECL_GLOBALBLOB_FUNC(name,nparams,typecheck) {_SC(#name),_g_blob_##name,nparams,typecheck}
0227 static const PSRegFunction bloblib_funcs[]={
0228 _DECL_GLOBALBLOB_FUNC(casti2f,2,_SC(".n")),
0229 _DECL_GLOBALBLOB_FUNC(castf2i,2,_SC(".n")),
0230 _DECL_GLOBALBLOB_FUNC(swap2,2,_SC(".n")),
0231 _DECL_GLOBALBLOB_FUNC(swap4,2,_SC(".n")),
0232 _DECL_GLOBALBLOB_FUNC(swapfloat,2,_SC(".n")),
0233 {NULL,(PSFUNCTION)0,0,NULL}
0234 };
0235
0236 PSRESULT psstd_getblob(HPSCRIPTVM v,PSInteger idx,PSUserPointer *ptr)
0237 {
0238 PSBlob *blob;
0239 if(PS_FAILED(ps_getinstanceup(v,idx,(PSUserPointer *)&blob,(PSUserPointer)PSSTD_BLOB_TYPE_TAG)))
0240 return -1;
0241 *ptr = blob->GetBuf();
0242 return PS_OK;
0243 }
0244
0245 PSInteger psstd_getblobsize(HPSCRIPTVM v,PSInteger idx)
0246 {
0247 PSBlob *blob;
0248 if(PS_FAILED(ps_getinstanceup(v,idx,(PSUserPointer *)&blob,(PSUserPointer)PSSTD_BLOB_TYPE_TAG)))
0249 return -1;
0250 return blob->Len();
0251 }
0252
0253 PSUserPointer psstd_createblob(HPSCRIPTVM v, PSInteger size)
0254 {
0255 PSInteger top = ps_gettop(v);
0256 ps_pushregistrytable(v);
0257 ps_pushstring(v,_SC("std_blob"),-1);
0258 if(PS_SUCCEEDED(ps_get(v,-2))) {
0259 ps_remove(v,-2);
0260 ps_push(v,1);
0261 ps_pushinteger(v,size);
0262 PSBlob *blob = NULL;
0263 if(PS_SUCCEEDED(ps_call(v,2,PSTrue,PSFalse))
0264 && PS_SUCCEEDED(ps_getinstanceup(v,-1,(PSUserPointer *)&blob,(PSUserPointer)PSSTD_BLOB_TYPE_TAG))) {
0265 ps_remove(v,-2);
0266 return blob->GetBuf();
0267 }
0268 }
0269 ps_settop(v,top);
0270 return NULL;
0271 }
0272
0273 PSRESULT psstd_register_bloblib(HPSCRIPTVM v)
0274 {
0275 return declare_stream(v,_SC("blob"),(PSUserPointer)PSSTD_BLOB_TYPE_TAG,_SC("std_blob"),_blob_methods,bloblib_funcs);
0276 }
0277