Back to home page

Enduro/X

 
 

    


0001 /* see copyright notice in pscript.h */
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 //Blob
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     //PSBlob *b = new PSBlob(size);
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     //PSBlob *thisone = new PSBlob(other->Len());
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 //GLOBAL FUNCTIONS
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); //removes the registry
0260         ps_push(v,1); // push the this
0261         ps_pushinteger(v,size); //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