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:
 
-.. 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.

+ 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_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);

+ 5 - 5
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();
         }

+ 2 - 2
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;
     }

+ 1 - 1
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"));

+ 2 - 2
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) {

+ 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)

+ 27 - 0
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}

+ 6 - 5
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

+ 1 - 1
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;