From 8d57d6056b0cf18f71478009e24177cf4e438a64 Mon Sep 17 00:00:00 2001 From: albertodemichelis Date: Tue, 22 Jun 2021 17:56:46 +0800 Subject: [PATCH] sq_getinstanceup adds throwerror parameter --- .../api/object_creation_and_handling.rst | 3 +- include/squirrel.h | 2 +- sqstdlib/sqstdblob.cpp | 10 +++---- sqstdlib/sqstdio.cpp | 4 +-- sqstdlib/sqstdstream.cpp | 2 +- sqstdlib/sqstdstring.cpp | 4 +-- squirrel/sqapi.cpp | 28 +++++++++---------- squirrel/sqbaselib.cpp | 27 ++++++++++++++++++ squirrel/sqstring.h | 11 ++++---- squirrel/sqvm.cpp | 2 +- 10 files changed, 61 insertions(+), 32 deletions(-) diff --git a/doc/source/reference/api/object_creation_and_handling.rst b/doc/source/reference/api/object_creation_and_handling.rst index 8f714f8..fd00915 100644 --- a/doc/source/reference/api/object_creation_and_handling.rst +++ b/doc/source/reference/api/object_creation_and_handling.rst @@ -140,12 +140,13 @@ returns the hash key of a value at the idx position in the stack. .. _sq_getinstanceup: -.. c:function:: SQRESULT sq_getinstanceup(HSQUIRRELVM v, SQInteger idx, SQUserPointer * up, SQUSerPointer typetag) +.. c:function:: SQRESULT sq_getinstanceup(HSQUIRRELVM v, SQInteger idx, SQUserPointer * up, SQUSerPointer typetag,SQBool throwerror) :param HSQUIRRELVM v: the target VM :param SQInteger idx: an index in the stack :param SQUserPointer * up: a pointer to the userpointer that will store the result :param SQUSerPointer typetag: the typetag that has to be checked, if this value is set to 0 the typetag is ignored. + :param SQBool throwerror: if SQTrue the function sets the last error string in case of failure :returns: a SQRESULT gets the userpointer of the class instance at position idx in the stack. if the parameter 'typetag' is different than 0, the function checks that the class or a base class of the instance is tagged with the specified tag; if not the function fails. If 'typetag' is 0 the function will ignore the tag check. diff --git a/include/squirrel.h b/include/squirrel.h index 1714e5a..0e4fecd 100644 --- a/include/squirrel.h +++ b/include/squirrel.h @@ -280,7 +280,7 @@ SQUIRREL_API SQRESULT sq_getclosureinfo(HSQUIRRELVM v,SQInteger idx,SQInteger *n SQUIRREL_API SQRESULT sq_getclosurename(HSQUIRRELVM v,SQInteger idx); SQUIRREL_API SQRESULT sq_setnativeclosurename(HSQUIRRELVM v,SQInteger idx,const SQChar *name); SQUIRREL_API SQRESULT sq_setinstanceup(HSQUIRRELVM v, SQInteger idx, SQUserPointer p); -SQUIRREL_API SQRESULT sq_getinstanceup(HSQUIRRELVM v, SQInteger idx, SQUserPointer *p,SQUserPointer typetag); +SQUIRREL_API SQRESULT sq_getinstanceup(HSQUIRRELVM v, SQInteger idx, SQUserPointer *p,SQUserPointer typetag,SQBool throwerror); SQUIRREL_API SQRESULT sq_setclassudsize(HSQUIRRELVM v, SQInteger idx, SQInteger udsize); SQUIRREL_API SQRESULT sq_newclass(HSQUIRRELVM v,SQBool hasbase); SQUIRREL_API SQRESULT sq_createinstance(HSQUIRRELVM v,SQInteger idx); diff --git a/sqstdlib/sqstdblob.cpp b/sqstdlib/sqstdblob.cpp index 776a968..22df0cf 100644 --- a/sqstdlib/sqstdblob.cpp +++ b/sqstdlib/sqstdblob.cpp @@ -14,7 +14,7 @@ #define SETUP_BLOB(v) \ SQBlob *self = NULL; \ - { if(SQ_FAILED(sq_getinstanceup(v,1,(SQUserPointer*)&self,(SQUserPointer)SQSTD_BLOB_TYPE_TAG))) \ + { if(SQ_FAILED(sq_getinstanceup(v,1,(SQUserPointer*)&self,(SQUserPointer)SQSTD_BLOB_TYPE_TAG,SQFalse))) \ return sq_throwerror(v,_SC("invalid type tag")); } \ if(!self || !self->IsValid()) \ return sq_throwerror(v,_SC("the blob is invalid")); @@ -152,7 +152,7 @@ static SQInteger _blob__cloned(HSQUIRRELVM v) { SQBlob *other = NULL; { - if(SQ_FAILED(sq_getinstanceup(v,2,(SQUserPointer*)&other,(SQUserPointer)SQSTD_BLOB_TYPE_TAG))) + if(SQ_FAILED(sq_getinstanceup(v,2,(SQUserPointer*)&other,(SQUserPointer)SQSTD_BLOB_TYPE_TAG,SQFalse))) return SQ_ERROR; } //SQBlob *thisone = new SQBlob(other->Len()); @@ -242,7 +242,7 @@ static const SQRegFunction bloblib_funcs[]={ SQRESULT sqstd_getblob(HSQUIRRELVM v,SQInteger idx,SQUserPointer *ptr) { SQBlob *blob; - if(SQ_FAILED(sq_getinstanceup(v,idx,(SQUserPointer *)&blob,(SQUserPointer)SQSTD_BLOB_TYPE_TAG))) + if(SQ_FAILED(sq_getinstanceup(v,idx,(SQUserPointer *)&blob,(SQUserPointer)SQSTD_BLOB_TYPE_TAG,SQTrue))) return -1; *ptr = blob->GetBuf(); return SQ_OK; @@ -251,7 +251,7 @@ SQRESULT sqstd_getblob(HSQUIRRELVM v,SQInteger idx,SQUserPointer *ptr) SQInteger sqstd_getblobsize(HSQUIRRELVM v,SQInteger idx) { SQBlob *blob; - if(SQ_FAILED(sq_getinstanceup(v,idx,(SQUserPointer *)&blob,(SQUserPointer)SQSTD_BLOB_TYPE_TAG))) + if(SQ_FAILED(sq_getinstanceup(v,idx,(SQUserPointer *)&blob,(SQUserPointer)SQSTD_BLOB_TYPE_TAG,SQTrue))) return -1; return blob->Len(); } @@ -267,7 +267,7 @@ SQUserPointer sqstd_createblob(HSQUIRRELVM v, SQInteger size) sq_pushinteger(v,size); //size SQBlob *blob = NULL; if(SQ_SUCCEEDED(sq_call(v,2,SQTrue,SQFalse)) - && SQ_SUCCEEDED(sq_getinstanceup(v,-1,(SQUserPointer *)&blob,(SQUserPointer)SQSTD_BLOB_TYPE_TAG))) { + && SQ_SUCCEEDED(sq_getinstanceup(v,-1,(SQUserPointer *)&blob,(SQUserPointer)SQSTD_BLOB_TYPE_TAG,SQTrue))) { sq_remove(v,-2); return blob->GetBuf(); } diff --git a/sqstdlib/sqstdio.cpp b/sqstdlib/sqstdio.cpp index 52cd515..ec6ee07 100644 --- a/sqstdlib/sqstdio.cpp +++ b/sqstdlib/sqstdio.cpp @@ -154,7 +154,7 @@ static SQInteger _file_constructor(HSQUIRRELVM v) static SQInteger _file_close(HSQUIRRELVM v) { SQFile *self = NULL; - if(SQ_SUCCEEDED(sq_getinstanceup(v,1,(SQUserPointer*)&self,(SQUserPointer)SQSTD_FILE_TYPE_TAG)) + if(SQ_SUCCEEDED(sq_getinstanceup(v,1,(SQUserPointer*)&self,(SQUserPointer)SQSTD_FILE_TYPE_TAG, SQTrue)) && self != NULL) { self->Close(); @@ -200,7 +200,7 @@ SQRESULT sqstd_createfile(HSQUIRRELVM v, SQFILE file,SQBool own) SQRESULT sqstd_getfile(HSQUIRRELVM v, SQInteger idx, SQFILE *file) { SQFile *fileobj = NULL; - if(SQ_SUCCEEDED(sq_getinstanceup(v,idx,(SQUserPointer*)&fileobj,(SQUserPointer)SQSTD_FILE_TYPE_TAG))) { + if(SQ_SUCCEEDED(sq_getinstanceup(v,idx,(SQUserPointer*)&fileobj,(SQUserPointer)SQSTD_FILE_TYPE_TAG,SQFalse))) { *file = fileobj->GetHandle(); return SQ_OK; } diff --git a/sqstdlib/sqstdstream.cpp b/sqstdlib/sqstdstream.cpp index b5c47cf..605a56c 100644 --- a/sqstdlib/sqstdstream.cpp +++ b/sqstdlib/sqstdstream.cpp @@ -11,7 +11,7 @@ #define SETUP_STREAM(v) \ SQStream *self = NULL; \ - if(SQ_FAILED(sq_getinstanceup(v,1,(SQUserPointer*)&self,(SQUserPointer)((SQUnsignedInteger)SQSTD_STREAM_TYPE_TAG)))) \ + if(SQ_FAILED(sq_getinstanceup(v,1,(SQUserPointer*)&self,(SQUserPointer)((SQUnsignedInteger)SQSTD_STREAM_TYPE_TAG),SQFalse))) \ return sq_throwerror(v,_SC("invalid type tag")); \ if(!self || !self->IsValid()) \ return sq_throwerror(v,_SC("the stream is invalid")); diff --git a/sqstdlib/sqstdstring.cpp b/sqstdlib/sqstdstring.cpp index 5747d8e..ca3df3e 100644 --- a/sqstdlib/sqstdstring.cpp +++ b/sqstdlib/sqstdstring.cpp @@ -387,7 +387,7 @@ static SQInteger _string_endswith(HSQUIRRELVM v) #define SETUP_REX(v) \ SQRex *self = NULL; \ - if(SQ_FAILED(sq_getinstanceup(v,1,(SQUserPointer *)&self,rex_typetag))) { \ + if(SQ_FAILED(sq_getinstanceup(v,1,(SQUserPointer *)&self,rex_typetag,SQFalse))) { \ return sq_throwerror(v,_SC("invalid type tag")); \ } @@ -471,7 +471,7 @@ static SQInteger _regexp_subexpcount(HSQUIRRELVM v) static SQInteger _regexp_constructor(HSQUIRRELVM v) { SQRex *self = NULL; - if (SQ_FAILED(sq_getinstanceup(v, 1, (SQUserPointer *)&self, rex_typetag))) { + if (SQ_FAILED(sq_getinstanceup(v, 1, (SQUserPointer *)&self, rex_typetag, SQFalse))) { return sq_throwerror(v, _SC("invalid type tag")); } if (self != NULL) { diff --git a/squirrel/sqapi.cpp b/squirrel/sqapi.cpp index a322150..54eecac 100644 --- a/squirrel/sqapi.cpp +++ b/squirrel/sqapi.cpp @@ -807,21 +807,21 @@ SQRESULT sq_setclassudsize(HSQUIRRELVM v, SQInteger idx, SQInteger udsize) } -SQRESULT sq_getinstanceup(HSQUIRRELVM v, SQInteger idx, SQUserPointer *p,SQUserPointer typetag) +SQRESULT sq_getinstanceup(HSQUIRRELVM v, SQInteger idx, SQUserPointer *p, SQUserPointer typetag, SQBool throwerror) { - SQObjectPtr &o = stack_get(v,idx); - if(sq_type(o) != OT_INSTANCE) return sq_throwerror(v,_SC("the object is not a class instance")); - (*p) = _instance(o)->_userpointer; - if(typetag != 0) { - SQClass *cl = _instance(o)->_class; - do{ - if(cl->_typetag == typetag) - return SQ_OK; - cl = cl->_base; - }while(cl != NULL); - return sq_throwerror(v,_SC("invalid type tag")); - } - return SQ_OK; + SQObjectPtr &o = stack_get(v, idx); + if (sq_type(o) != OT_INSTANCE) return throwerror ? sq_throwerror(v, _SC("the object is not a class instance")) : SQ_ERROR; + (*p) = _instance(o)->_userpointer; + if (typetag != 0) { + SQClass *cl = _instance(o)->_class; + do { + if (cl->_typetag == typetag) + return SQ_OK; + cl = cl->_base; + } while (cl != NULL); + return throwerror ? sq_throwerror(v, _SC("invalid type tag")) : SQ_ERROR; + } + return SQ_OK; } SQInteger sq_gettop(HSQUIRRELVM v) diff --git a/squirrel/sqbaselib.cpp b/squirrel/sqbaselib.cpp index 5c03e83..8eff97c 100644 --- a/squirrel/sqbaselib.cpp +++ b/squirrel/sqbaselib.cpp @@ -499,6 +499,32 @@ static SQInteger table_filter(HSQUIRRELVM v) return 1; } +static SQInteger table_map(HSQUIRRELVM v) +{ + SQObject &o = stack_get(v, 1); + SQTable *tbl = _table(o); + SQInteger nitr, n = 0; + SQInteger nitems = tbl->CountUsed(); + SQObjectPtr ret = SQArray::Create(_ss(v), nitems); + SQObjectPtr itr, key, val; + while ((nitr = tbl->Next(false, itr, key, val)) != -1) { + itr = (SQInteger)nitr; + + v->Push(o); + v->Push(key); + v->Push(val); + if (SQ_FAILED(sq_call(v, 3, SQTrue, SQFalse))) { + return SQ_ERROR; + } + _array(ret)->Set(n, v->GetUp(-1)); + v->Pop(); + n++; + } + + v->Push(ret); + return 1; +} + #define TABLE_TO_ARRAY_FUNC(_funcname_,_valname_) static SQInteger _funcname_(HSQUIRRELVM v) \ { \ SQObject &o = stack_get(v, 1); \ @@ -536,6 +562,7 @@ const SQRegFunction SQSharedState::_table_default_delegate_funcz[]={ {_SC("setdelegate"),table_setdelegate,2, _SC(".t|o")}, {_SC("getdelegate"),table_getdelegate,1, _SC(".")}, {_SC("filter"),table_filter,2, _SC("tc")}, + {_SC("map"),table_map,2, _SC("tc") }, {_SC("keys"),table_keys,1, _SC("t") }, {_SC("values"),table_values,1, _SC("t") }, {NULL,(SQFUNCTION)0,0,NULL} diff --git a/squirrel/sqstring.h b/squirrel/sqstring.h index 82f1cdf..0099f3b 100644 --- a/squirrel/sqstring.h +++ b/squirrel/sqstring.h @@ -4,11 +4,12 @@ inline SQHash _hashstr (const SQChar *s, size_t l) { - SQHash h = (SQHash)l; /* seed */ - size_t step = (l>>5)|1; /* if string is too long, don't hash all its chars */ - for (; l>=step; l-=step) - h = h ^ ((h<<5)+(h>>2)+(unsigned short)*(s++)); - return h; + SQHash h = (SQHash)l; /* seed */ + size_t step = (l >> 5) + 1; /* if string is too long, don't hash all its chars */ + size_t l1; + for (l1 = l; l1 >= step; l1 -= step) + h = h ^ ((h << 5) + (h >> 2) + ((unsigned short)s[l1 - 1])); + return h; } struct SQString : public SQRefCounted diff --git a/squirrel/sqvm.cpp b/squirrel/sqvm.cpp index 6150248..5933cc9 100644 --- a/squirrel/sqvm.cpp +++ b/squirrel/sqvm.cpp @@ -1336,7 +1336,7 @@ SQInteger SQVM::FallBackGet(const SQObjectPtr &self,const SQObjectPtr &key,SQObj case OT_USERDATA: //delegation if(_delegable(self)->_delegate) { - if(Get(SQObjectPtr(_delegable(self)->_delegate),key,dest,0,DONT_FALL_BACK)) return FALLBACK_OK; + if(Get(SQObjectPtr(_delegable(self)->_delegate),key,dest, GET_FLAG_DO_NOT_RAISE_ERROR,DONT_FALL_BACK)) return FALLBACK_OK; } else { return FALLBACK_NO_MATCH;