Browse Source

sq_getinstanceup adds throwerror parameter

albertodemichelis 4 years ago
parent
commit
8d57d6056b

+ 2 - 1
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:
 .. _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 HSQUIRRELVM v: the target VM
     :param SQInteger idx: an index in the stack
     :param SQInteger idx: an index in the stack
     :param SQUserPointer * up: a pointer to the userpointer that will store the result
     :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 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
     :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.
 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.

+ 1 - 1
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_getclosurename(HSQUIRRELVM v,SQInteger idx);
 SQUIRREL_API SQRESULT sq_setnativeclosurename(HSQUIRRELVM v,SQInteger idx,const SQChar *name);
 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_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_setclassudsize(HSQUIRRELVM v, SQInteger idx, SQInteger udsize);
 SQUIRREL_API SQRESULT sq_newclass(HSQUIRRELVM v,SQBool hasbase);
 SQUIRREL_API SQRESULT sq_newclass(HSQUIRRELVM v,SQBool hasbase);
 SQUIRREL_API SQRESULT sq_createinstance(HSQUIRRELVM v,SQInteger idx);
 SQUIRREL_API SQRESULT sq_createinstance(HSQUIRRELVM v,SQInteger idx);

+ 5 - 5
sqstdlib/sqstdblob.cpp

@@ -14,7 +14,7 @@
 
 
 #define SETUP_BLOB(v) \
 #define SETUP_BLOB(v) \
     SQBlob *self = NULL; \
     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"));  } \
         return sq_throwerror(v,_SC("invalid type tag"));  } \
     if(!self || !self->IsValid())  \
     if(!self || !self->IsValid())  \
         return sq_throwerror(v,_SC("the blob is invalid"));
         return sq_throwerror(v,_SC("the blob is invalid"));
@@ -152,7 +152,7 @@ static SQInteger _blob__cloned(HSQUIRRELVM v)
 {
 {
     SQBlob *other = NULL;
     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;
             return SQ_ERROR;
     }
     }
     //SQBlob *thisone = new SQBlob(other->Len());
     //SQBlob *thisone = new SQBlob(other->Len());
@@ -242,7 +242,7 @@ static const SQRegFunction bloblib_funcs[]={
 SQRESULT sqstd_getblob(HSQUIRRELVM v,SQInteger idx,SQUserPointer *ptr)
 SQRESULT sqstd_getblob(HSQUIRRELVM v,SQInteger idx,SQUserPointer *ptr)
 {
 {
     SQBlob *blob;
     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 -1;
     *ptr = blob->GetBuf();
     *ptr = blob->GetBuf();
     return SQ_OK;
     return SQ_OK;
@@ -251,7 +251,7 @@ SQRESULT sqstd_getblob(HSQUIRRELVM v,SQInteger idx,SQUserPointer *ptr)
 SQInteger sqstd_getblobsize(HSQUIRRELVM v,SQInteger idx)
 SQInteger sqstd_getblobsize(HSQUIRRELVM v,SQInteger idx)
 {
 {
     SQBlob *blob;
     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 -1;
     return blob->Len();
     return blob->Len();
 }
 }
@@ -267,7 +267,7 @@ SQUserPointer sqstd_createblob(HSQUIRRELVM v, SQInteger size)
         sq_pushinteger(v,size); //size
         sq_pushinteger(v,size); //size
         SQBlob *blob = NULL;
         SQBlob *blob = NULL;
         if(SQ_SUCCEEDED(sq_call(v,2,SQTrue,SQFalse))
         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);
             sq_remove(v,-2);
             return blob->GetBuf();
             return blob->GetBuf();
         }
         }

+ 2 - 2
sqstdlib/sqstdio.cpp

@@ -154,7 +154,7 @@ static SQInteger _file_constructor(HSQUIRRELVM v)
 static SQInteger _file_close(HSQUIRRELVM v)
 static SQInteger _file_close(HSQUIRRELVM v)
 {
 {
     SQFile *self = NULL;
     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 != NULL)
     {
     {
         self->Close();
         self->Close();
@@ -200,7 +200,7 @@ SQRESULT sqstd_createfile(HSQUIRRELVM v, SQFILE file,SQBool own)
 SQRESULT sqstd_getfile(HSQUIRRELVM v, SQInteger idx, SQFILE *file)
 SQRESULT sqstd_getfile(HSQUIRRELVM v, SQInteger idx, SQFILE *file)
 {
 {
     SQFile *fileobj = NULL;
     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();
         *file = fileobj->GetHandle();
         return SQ_OK;
         return SQ_OK;
     }
     }

+ 1 - 1
sqstdlib/sqstdstream.cpp

@@ -11,7 +11,7 @@
 
 
 #define SETUP_STREAM(v) \
 #define SETUP_STREAM(v) \
     SQStream *self = NULL; \
     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")); \
         return sq_throwerror(v,_SC("invalid type tag")); \
     if(!self || !self->IsValid())  \
     if(!self || !self->IsValid())  \
         return sq_throwerror(v,_SC("the stream is invalid"));
         return sq_throwerror(v,_SC("the stream is invalid"));

+ 2 - 2
sqstdlib/sqstdstring.cpp

@@ -387,7 +387,7 @@ static SQInteger _string_endswith(HSQUIRRELVM v)
 
 
 #define SETUP_REX(v) \
 #define SETUP_REX(v) \
     SQRex *self = NULL; \
     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")); \
 		return sq_throwerror(v,_SC("invalid type tag")); \
 	}
 	}
 
 
@@ -471,7 +471,7 @@ static SQInteger _regexp_subexpcount(HSQUIRRELVM v)
 static SQInteger _regexp_constructor(HSQUIRRELVM v)
 static SQInteger _regexp_constructor(HSQUIRRELVM v)
 {
 {
 	SQRex *self = NULL;
 	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"));
 		return sq_throwerror(v, _SC("invalid type tag"));
 	}
 	}
 	if (self != NULL) {
 	if (self != NULL) {

+ 15 - 15
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)
-{
-    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;
+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 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)
 SQInteger sq_gettop(HSQUIRRELVM v)

+ 27 - 0
squirrel/sqbaselib.cpp

@@ -499,6 +499,32 @@ static SQInteger table_filter(HSQUIRRELVM v)
     return 1;
     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) \
 #define TABLE_TO_ARRAY_FUNC(_funcname_,_valname_) static SQInteger _funcname_(HSQUIRRELVM v) \
 { \
 { \
 	SQObject &o = stack_get(v, 1); \
 	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("setdelegate"),table_setdelegate,2, _SC(".t|o")},
     {_SC("getdelegate"),table_getdelegate,1, _SC(".")},
     {_SC("getdelegate"),table_getdelegate,1, _SC(".")},
     {_SC("filter"),table_filter,2, _SC("tc")},
     {_SC("filter"),table_filter,2, _SC("tc")},
+	{_SC("map"),table_map,2, _SC("tc") },
 	{_SC("keys"),table_keys,1, _SC("t") },
 	{_SC("keys"),table_keys,1, _SC("t") },
 	{_SC("values"),table_values,1, _SC("t") },
 	{_SC("values"),table_values,1, _SC("t") },
     {NULL,(SQFUNCTION)0,0,NULL}
     {NULL,(SQFUNCTION)0,0,NULL}

+ 6 - 5
squirrel/sqstring.h

@@ -4,11 +4,12 @@
 
 
 inline SQHash _hashstr (const SQChar *s, size_t l)
 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
 struct SQString : public SQRefCounted

+ 1 - 1
squirrel/sqvm.cpp

@@ -1336,7 +1336,7 @@ SQInteger SQVM::FallBackGet(const SQObjectPtr &self,const SQObjectPtr &key,SQObj
     case OT_USERDATA:
     case OT_USERDATA:
         //delegation
         //delegation
         if(_delegable(self)->_delegate) {
         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 {
         else {
             return FALLBACK_NO_MATCH;
             return FALLBACK_NO_MATCH;