Selaa lähdekoodia

Fix Variant and VariantMap bindings to Lua. Close #820.
Add Lua bindings to return VariantVector as table of Variant.
Fix Lua database demo. It is in full working condition now.
[ci only: database, OSX]

Yao Wei Tjong 姚伟忠 10 vuotta sitten
vanhempi
sitoutus
8acb9e6441

+ 8 - 7
Source/ThirdParty/toluapp/src/lib/tolua_map.c

@@ -12,6 +12,8 @@
 ** enhancements, or modifications.
 */
 
+// Modified by Yao Wei Tjong for Urho3D
+
 #include "tolua++.h"
 #include "tolua_event.h"
 #include "lauxlib.h"
@@ -25,7 +27,7 @@
 /* Create metatable
 	* Create and register new metatable
 */
-static int tolua_newmetatable (lua_State* L, char* name)
+static int tolua_newmetatable (lua_State* L, const char* name)	// Urho3D - const correctness
 {
 	int r = luaL_newmetatable(L,name);
 
@@ -257,7 +259,7 @@ static int tolua_bnd_setpeer(lua_State* L) {
 		lua_pushstring(L, "Invalid argument #1 to setpeer: userdata expected.");
 		lua_error(L);
 	};
-	
+
 	if (lua_isnil(L, -1)) {
 
 		lua_pop(L, 1);
@@ -395,8 +397,7 @@ TOLUA_API void tolua_usertype (lua_State* L, const char* type)
  strncat(ctype,type,120);
 
  /* create both metatables */
- // Modified by Aster Jian for Urho3D.
- if (tolua_newmetatable(L,ctype) && tolua_newmetatable(L,(char*)type))
+ if (tolua_newmetatable(L,ctype) && tolua_newmetatable(L,type))
 	 mapsuper(L,type,ctype);             /* 'type' is also a 'const type' */
 }
 
@@ -533,7 +534,7 @@ TOLUA_API void tolua_cclass (lua_State* L, const char* lname, const char* name,
 	mapsuper(L,name,base);
 
 	lua_pushstring(L,lname);
-	
+
 	push_collector(L, name, col);
 	/*
 	luaL_getmetatable(L,name);
@@ -542,7 +543,7 @@ TOLUA_API void tolua_cclass (lua_State* L, const char* lname, const char* name,
 
 	lua_rawset(L,-3);
 	*/
-	
+
 	luaL_getmetatable(L,name);
 	lua_rawset(L,-3);              /* assign class metatable to module */
 
@@ -556,7 +557,7 @@ TOLUA_API void tolua_cclass (lua_State* L, const char* lname, const char* name,
 	lua_rawset(L,-3);
 	lua_pop(L,1);
 	*/
-	
+
 
 }
 

+ 11 - 11
Source/Urho3D/Core/Variant.cpp

@@ -35,7 +35,7 @@ const ResourceRef Variant::emptyResourceRef;
 const ResourceRefList Variant::emptyResourceRefList;
 const VariantMap Variant::emptyVariantMap;
 const VariantVector Variant::emptyVariantVector;
-const Vector<String> Variant::emptyStringVector;
+const StringVector Variant::emptyStringVector;
 
 static const char* typeNames[] =
 {
@@ -93,7 +93,7 @@ Variant& Variant::operator =(const Variant& rhs)
         break;
 
     case VAR_STRINGVECTOR:
-        *(reinterpret_cast<Vector<String>*>(&value_)) = *(reinterpret_cast<const Vector<String>*>(&rhs.value_));
+        *(reinterpret_cast<StringVector*>(&value_)) = *(reinterpret_cast<const StringVector*>(&rhs.value_));
         break;
 
     case VAR_VARIANTMAP:
@@ -171,7 +171,7 @@ bool Variant::operator ==(const Variant& rhs) const
         return *(reinterpret_cast<const VariantVector*>(&value_)) == *(reinterpret_cast<const VariantVector*>(&rhs.value_));
 
     case VAR_STRINGVECTOR:
-        return *(reinterpret_cast<const Vector<String>*>(&value_)) == *(reinterpret_cast<const Vector<String>*>(&rhs.value_));
+        return *(reinterpret_cast<const StringVector*>(&value_)) == *(reinterpret_cast<const StringVector*>(&rhs.value_));
 
     case VAR_VARIANTMAP:
         return *(reinterpret_cast<const VariantMap*>(&value_)) == *(reinterpret_cast<const VariantMap*>(&rhs.value_));
@@ -269,7 +269,7 @@ void Variant::FromString(VariantType type, const char* value)
 
     case VAR_RESOURCEREF:
     {
-        Vector<String> values = String::Split(value, ';');
+        StringVector values = String::Split(value, ';');
         if (values.Size() == 2)
         {
             SetType(VAR_RESOURCEREF);
@@ -282,7 +282,7 @@ void Variant::FromString(VariantType type, const char* value)
 
     case VAR_RESOURCEREFLIST:
     {
-        Vector<String> values = String::Split(value, ';');
+        StringVector values = String::Split(value, ';');
         if (values.Size() >= 1)
         {
             SetType(VAR_RESOURCEREFLIST);
@@ -459,8 +459,8 @@ bool Variant::IsZero() const
 
     case VAR_RESOURCEREFLIST:
     {
-        const Vector<String>& names = reinterpret_cast<const ResourceRefList*>(&value_)->names_;
-        for (Vector<String>::ConstIterator i = names.Begin(); i != names.End(); ++i)
+        const StringVector& names = reinterpret_cast<const ResourceRefList*>(&value_)->names_;
+        for (StringVector::ConstIterator i = names.Begin(); i != names.End(); ++i)
         {
             if (!i->Empty())
                 return false;
@@ -472,7 +472,7 @@ bool Variant::IsZero() const
         return reinterpret_cast<const VariantVector*>(&value_)->Empty();
 
     case VAR_STRINGVECTOR:
-        return reinterpret_cast<const Vector<String>*>(&value_)->Empty();
+        return reinterpret_cast<const StringVector*>(&value_)->Empty();
 
     case VAR_VARIANTMAP:
         return reinterpret_cast<const VariantMap*>(&value_)->Empty();
@@ -531,7 +531,7 @@ void Variant::SetType(VariantType newType)
         break;
 
     case VAR_STRINGVECTOR:
-        (reinterpret_cast<Vector<String>*>(&value_))->~Vector<String>();
+        (reinterpret_cast<StringVector*>(&value_))->~StringVector();
         break;
 
     case VAR_VARIANTMAP:
@@ -583,7 +583,7 @@ void Variant::SetType(VariantType newType)
         break;
 
     case VAR_STRINGVECTOR:
-        new(reinterpret_cast<Vector<String>*>(&value_)) Vector<String>();
+        new(reinterpret_cast<StringVector*>(&value_)) StringVector();
         break;
 
     case VAR_VARIANTMAP:
@@ -726,7 +726,7 @@ template <> VariantVector Variant::Get<VariantVector>() const
     return GetVariantVector();
 }
 
-template <> Vector<String> Variant::Get<Vector<String> >() const
+template <> StringVector Variant::Get<StringVector >() const
 {
     return GetStringVector();
 }

+ 24 - 21
Source/Urho3D/Core/Variant.h

@@ -96,6 +96,17 @@ struct VariantValue
     };
 };
 
+class Variant;
+
+/// Vector of variants.
+typedef Vector<Variant> VariantVector;
+
+/// Vector of strings.
+typedef Vector<String> StringVector;
+
+/// Map of variants.
+typedef HashMap<StringHash, Variant> VariantMap;
+
 /// Typed resource reference.
 struct URHO3D_API ResourceRef
 {
@@ -151,7 +162,7 @@ struct URHO3D_API ResourceRefList
     }
 
     /// Construct with type and id list.
-    ResourceRefList(StringHash type, const Vector<String>& names) :
+    ResourceRefList(StringHash type, const StringVector& names) :
         type_(type),
         names_(names)
     {
@@ -160,7 +171,7 @@ struct URHO3D_API ResourceRefList
     /// Object type.
     StringHash type_;
     /// List of object names.
-    Vector<String> names_;
+    StringVector names_;
 
     /// Test for equality with another reference list.
     bool operator ==(const ResourceRefList& rhs) const { return type_ == rhs.type_ && names_ == rhs.names_; }
@@ -169,14 +180,6 @@ struct URHO3D_API ResourceRefList
     bool operator !=(const ResourceRefList& rhs) const { return type_ != rhs.type_ || names_ != rhs.names_; }
 };
 
-class Variant;
-
-/// Vector of variants.
-typedef Vector<Variant> VariantVector;
-
-/// Map of variants.
-typedef HashMap<StringHash, Variant> VariantMap;
-
 /// Variable that supports a fixed set of types.
 class URHO3D_API Variant
 {
@@ -321,7 +324,7 @@ public:
     }
 
     /// Construct from a string vector.
-    Variant(const Vector<String>& value) :
+    Variant(const StringVector& value) :
         type_ (VAR_NONE)
     {
         *this = value;
@@ -564,10 +567,10 @@ public:
     }
 
     // Assign from a string vector.
-    Variant& operator =(const Vector<String>& rhs)
+    Variant& operator =(const StringVector& rhs)
     {
         SetType(VAR_STRINGVECTOR);
-        *(reinterpret_cast<Vector<String>*>(&value_)) = rhs;
+        *(reinterpret_cast<StringVector*>(&value_)) = rhs;
         return *this;
     }
 
@@ -717,9 +720,9 @@ public:
     }
 
     /// Test for equality with a string vector. To return true, both the type and value must match.
-    bool operator ==(const Vector<String>& rhs) const
+    bool operator ==(const StringVector& rhs) const
     {
-        return type_ == VAR_STRINGVECTOR ? *(reinterpret_cast<const Vector<String>*>(&value_)) == rhs : false;
+        return type_ == VAR_STRINGVECTOR ? *(reinterpret_cast<const StringVector*>(&value_)) == rhs : false;
     }
 
     /// Test for equality with a variant map. To return true, both the type and value must match.
@@ -821,7 +824,7 @@ public:
     bool operator !=(const VariantVector& rhs) const { return !(*this == rhs); }
 
     /// Test for inequality with a string vector.
-    bool operator !=(const Vector<String>& rhs) const { return !(*this == rhs); }
+    bool operator !=(const StringVector& rhs) const { return !(*this == rhs); }
 
     /// Test for inequality with a variant map.
     bool operator !=(const VariantMap& rhs) const { return !(*this == rhs); }
@@ -933,9 +936,9 @@ public:
     }
 
     /// Return a string vector or empty on type mismatch.
-    const Vector<String>& GetStringVector() const
+    const StringVector& GetStringVector() const
     {
-        return type_ == VAR_STRINGVECTOR ? *reinterpret_cast<const Vector<String>*>(&value_) : emptyStringVector;
+        return type_ == VAR_STRINGVECTOR ? *reinterpret_cast<const StringVector*>(&value_) : emptyStringVector;
     }
 
     /// Return a variant map or empty on type mismatch.
@@ -1003,7 +1006,7 @@ public:
     VariantVector* GetVariantVectorPtr() { return type_ == VAR_VARIANTVECTOR ? reinterpret_cast<VariantVector*>(&value_) : 0; }
 
     /// Return a pointer to a modifiable string vector or null on type mismatch.
-    Vector<String>* GetStringVectorPtr() { return type_ == VAR_STRINGVECTOR ? reinterpret_cast<Vector<String>*>(&value_) : 0; }
+    StringVector* GetStringVectorPtr() { return type_ == VAR_STRINGVECTOR ? reinterpret_cast<StringVector*>(&value_) : 0; }
 
     /// Return a pointer to a modifiable variant map or null on type mismatch.
     VariantMap* GetVariantMapPtr() { return type_ == VAR_VARIANTMAP ? reinterpret_cast<VariantMap*>(&value_) : 0; }
@@ -1028,7 +1031,7 @@ public:
     /// Empty variant vector.
     static const VariantVector emptyVariantVector;
     /// Empty string vector.
-    static const Vector<String> emptyStringVector;
+    static const StringVector emptyStringVector;
 
 private:
     /// Set new type and allocate/deallocate memory as necessary.
@@ -1076,7 +1079,7 @@ template <> inline VariantType GetVariantType<ResourceRefList>() { return VAR_RE
 
 template <> inline VariantType GetVariantType<VariantVector>() { return VAR_VARIANTVECTOR; }
 
-template <> inline VariantType GetVariantType<Vector<String> >() { return VAR_STRINGVECTOR; }
+template <> inline VariantType GetVariantType<StringVector >() { return VAR_STRINGVECTOR; }
 
 template <> inline VariantType GetVariantType<VariantMap>() { return VAR_VARIANTMAP; }
 

+ 1 - 1
Source/Urho3D/Database/DatabaseEvents.h

@@ -36,7 +36,7 @@ EVENT(E_DBCURSOR, DbCursor)
     PARAM(P_SQL, SQL);                      // String
     PARAM(P_NUMCOLS, NumCols);              // unsigned
     PARAM(P_COLVALUES, ColValues);          // VariantVector
-    PARAM(P_COLHEADERS, ColHeaders);        // Vector<String>
+    PARAM(P_COLHEADERS, ColHeaders);        // StringVector
     PARAM(P_FILTER, Filter);                // bool [in]
     PARAM(P_ABORT, Abort);                  // bool [in]
 }

+ 1 - 1
Source/Urho3D/Database/ODBC/ODBCConnection.cpp

@@ -151,7 +151,7 @@ DbResult DbConnection::Execute(const String& sql, bool useCursorEvent)
 
 void DbConnection::HandleRuntimeError(const char* message, const char* cause)
 {
-    Vector<String> tokens = (String(cause) + "::").Split(':');      // Added "::" as sentinels against unexpected cause format
+    StringVector tokens = (String(cause) + "::").Split(':');      // Added "::" as sentinels against unexpected cause format
     LOGERRORF("%s: nanodbc:%s:%s", message, tokens[1].CString(), tokens[2].CString());
 }
 

+ 2 - 2
Source/Urho3D/Database/ODBC/ODBCResult.h

@@ -54,7 +54,7 @@ public:
     const nanodbc::result& GetResultImpl() const { return resultImpl_; }
 
     /// Return the column headers string collection.
-    const Vector<String>& GetColumns() const { return columns_; }
+    const StringVector& GetColumns() const { return columns_; }
 
     /// Return fetched rows collection. Filtered rows are not included in the collection.
     const Vector<VariantVector>& GetRows() const { return rows_; }
@@ -63,7 +63,7 @@ private:
     /// The underlying implementation connection object.
     nanodbc::result resultImpl_;
     /// Column headers from the resultset.
-    Vector<String> columns_;
+    StringVector columns_;
     /// Fetched rows from the resultset.
     Vector<VariantVector> rows_;
     /// Number of affected rows by recent DML query.

+ 2 - 2
Source/Urho3D/Database/SQLite/SQLiteResult.h

@@ -51,14 +51,14 @@ public:
     long GetNumAffectedRows() const { return numAffectedRows_; }
 
     /// Return the column headers string collection.
-    const Vector<String>& GetColumns() const { return columns_; }
+    const StringVector& GetColumns() const { return columns_; }
 
     /// Return fetched rows collection. Filtered rows are not included in the collection.
     const Vector<VariantVector>& GetRows() const { return rows_; }
 
 private:
     /// Column headers from the resultset.
-    Vector<String> columns_;
+    StringVector columns_;
     /// Fetched rows from the resultset.
     Vector<VariantVector> rows_;
     /// Number of affected rows by recent DML query.

+ 63 - 0
Source/Urho3D/LuaScript/ToluaUtils.cpp

@@ -93,6 +93,31 @@ template <> int ToluaIsVector<String>(lua_State* L, int lo, const char* type, in
     return 0;
 }
 
+template <> int ToluaIsVector<Variant>(lua_State* L, int lo, const char* type, int def, tolua_Error* err)
+{
+    if (lua_istable(L, lo))
+    {
+        size_t length = lua_objlen(L, lo);
+        for (int i = 1; i <= length; ++i)
+        {
+            lua_pushinteger(L, i);
+            lua_gettable(L, lo);
+            if (!tolua_isusertype(L, -1, "Variant", 0, err))
+            {
+                lua_pop(L, 1);
+                return 0;
+            }
+            lua_pop(L, 1);
+        }
+        return 1;
+    }
+
+    err->index = lo;
+    err->array = 0;
+    err->type = type;
+    return 0;
+}
+
 template <> void* ToluaToVector<String>(lua_State* L, int narg, void* def)
 {
     if (!lua_istable(L, narg))
@@ -122,6 +147,32 @@ template <> void* ToluaToVector<String>(lua_State* L, int narg, void* def)
     return &result;
 }
 
+template <> void* ToluaToVector<Variant>(lua_State* L, int narg, void* def)
+{
+    if (!lua_istable(L, narg))
+        return 0;
+
+    static Vector<Variant> result;
+    result.Clear();
+
+    size_t length = lua_objlen(L, narg);
+    for (int i = 1; i <= length; ++i)
+    {
+        lua_pushinteger(L, i);
+        lua_gettable(L, narg);
+        tolua_Error error;
+        if (!tolua_isusertype(L, -1, "Variant", 0, &error))
+        {
+            lua_pop(L, 1);
+            return 0;
+        }
+        result.Push((Variant*) tolua_tousertype(L, -1, 0));
+        lua_pop(L, 1);
+    }
+
+    return &result;
+}
+
 template <> int ToluaPushVector<String>(lua_State* L, void* data, const char* type)
 {
     const Vector<String>& vectorstring = *((const Vector<String>*)data);
@@ -146,6 +197,18 @@ template <> int ToluaPushVector<StringHash>(lua_State* L, void* data, const char
     return 1;
 }
 
+template <> int ToluaPushVector<Variant>(lua_State* L, void* data, const char* type)
+{
+    lua_newtable(L);
+    Vector<Variant>& vector = *reinterpret_cast<Vector<Variant>*>(data);
+    for (unsigned i = 0; i < vector.Size(); ++i)
+    {
+        tolua_pushusertype(L, &vector[i], "Variant");
+        lua_rawseti(L, -2, i + 1);
+    }
+    return 1;
+}
+
 template <> int ToluaIsPODVector<unsigned>(lua_State* L, int lo, const char* type, int def, tolua_Error* err)
 {
     if (lua_istable(L, lo))

+ 154 - 450
Source/Urho3D/LuaScript/pkgs/Core/Variant.pkg

@@ -71,62 +71,54 @@ class Variant
     Variant(const Color& value);
     Variant(const String value);
     Variant(const char* value);
+    tolua_outside void VariantConstructFromBuffer @ Variant(const VectorBuffer& value);
+    Variant(void* value);
     Variant(const ResourceRef& value);
     Variant(const ResourceRefList& value);
+    Variant(const Vector<Variant>& value);
+//variantmap
+    Variant(const Vector<String>& value);
     Variant(const IntRect& value);
     Variant(const IntVector2& value);
+//refcounted*
     Variant(const Matrix3& value);
     Variant(const Matrix3x4& value);
     Variant(const Matrix4& value);
     Variant(const String type, const String value);
     Variant(VariantType type, const String value);
+    Variant(const char* type, const char* value);
     Variant(VariantType type, const char* value);
     Variant(const Variant& value);
     ~Variant();
 
     void Clear();
 
-    bool operator == (const Variant& rhs) const;
-    bool operator == (int rhs) const;
-    bool operator == (unsigned rhs) const;
-    bool operator == (bool rhs) const;
-    bool operator == (float rhs) const;
-    bool operator == (double rhs) const;
-    bool operator == (const Vector2& rhs);
-    bool operator == (const Vector3& rhs) const;
-    bool operator == (const Vector4& rhs) const;
-    bool operator == (const Quaternion& rhs) const;
-    bool operator == (const Color& rhs) const;
-    bool operator == (const String rhs) const;
-    bool operator == (const ResourceRef& rhs) const;
-    bool operator == (const ResourceRefList& rhs) const;
-    bool operator == (const IntRect& rhs) const;
-    bool operator == (const IntVector2& rhs) const;
-    bool operator == (const StringHash& rhs) const;
-    bool operator == (const Matrix3& rhs) const;
-    bool operator == (const Matrix3x4& rhs) const;
-    bool operator == (const Matrix4& rhs) const;
-
-    tolua_outside void VariantSetInt @ SetInt(int value);
-    tolua_outside void VariantSetUint @ SetUint(unsigned value);
-    tolua_outside void VariantSetStringHash @ SetStringHash(const StringHash& value);
-    tolua_outside void VariantSetBool @ SetBool(bool value);
-    tolua_outside void VariantSetFloat @ SetFloat(float value);
-    tolua_outside void VariantSetDouble @ SetDouble(double value);
-    tolua_outside void VariantSetVector2 @ SetVector2(const Vector2& value);
-    tolua_outside void VariantSetVector3 @ SetVector3(const Vector3& value);
-    tolua_outside void VariantSetVector4 @ SetVector4(const Vector4& value);
-    tolua_outside void VariantSetQuaternion @ SetQuaternion(const Quaternion& value);
-    tolua_outside void VariantSetColor @ SetColor(const Color& value);
-    tolua_outside void VariantSetString @ SetString(const String value);
-    tolua_outside void VariantSetBuffer @ SetBuffer(const VectorBuffer& value);
-    tolua_outside void VariantSetResourceRef @ SetResourceRef(const ResourceRef& value);
-    tolua_outside void VariantSetResourceRefList @ SetResourceRefList(const ResourceRefList& value);
-    tolua_outside void VariantSetIntRect @ SetIntRect(const IntRect& value);
-    tolua_outside void VariantSetIntVector2 @ SetIntVector2(const IntVector2& value);
-    tolua_outside void VariantSetMatrix3 @ SetMatrix3(const Matrix3& value);
-    tolua_outside void VariantSetMatrix3x4 @ SetMatrix3x4(const Matrix3x4& value);
-    tolua_outside void VariantSetMatrix4 @ SetMatrix4(const Matrix4& value);
+    bool operator ==(const Variant& rhs) const;
+    bool operator ==(int rhs) const;
+    bool operator ==(unsigned rhs) const;
+    bool operator ==(bool rhs) const;
+    bool operator ==(float rhs) const;
+    bool operator ==(double rhs) const;
+    bool operator ==(const Vector2& rhs);
+    bool operator ==(const Vector3& rhs) const;
+    bool operator ==(const Vector4& rhs) const;
+    bool operator ==(const Quaternion& rhs) const;
+    bool operator ==(const Color& rhs) const;
+    bool operator ==(const String rhs) const;
+    tolua_outside bool VariantEqualWithBuffer @ operator ==(const VectorBuffer& rhs) const;
+//void*
+    bool operator ==(const ResourceRef& rhs) const;
+    bool operator ==(const ResourceRefList& rhs) const;
+    bool operator ==(const Vector<Variant>& rhs) const;
+//variantmap
+    bool operator ==(const Vector<String>& rhs) const;
+    bool operator ==(const IntRect& rhs) const;
+    bool operator ==(const IntVector2& rhs) const;
+    bool operator ==(const StringHash& rhs) const;
+//refcounted*
+    bool operator ==(const Matrix3& rhs) const;
+    bool operator ==(const Matrix3x4& rhs) const;
+    bool operator ==(const Matrix4& rhs) const;
 
     int GetInt() const;
     unsigned GetUInt() const;
@@ -141,10 +133,15 @@ class Variant
     const Color& GetColor() const;
     const String GetString() const;
     tolua_outside VectorBuffer VariantGetBuffer @ GetBuffer() const;
+//void*
     const ResourceRef& GetResourceRef() const;
     const ResourceRefList& GetResourceRefList() const;
+    const Vector<Variant>& GetVariantVector() const;
+//variantmap
+    const Vector<String>& GetStringVector() const;
     const IntRect& GetIntRect() const;
     const IntVector2& GetIntVector2() const;
+//refcounted*
     const Matrix3& GetMatrix3() const;
     const Matrix3x4& GetMatrix3x4() const;
     const Matrix4& GetMatrix4() const;
@@ -161,158 +158,16 @@ class Variant
     tolua_readonly tolua_property__is_set bool empty;
 };
 
-class VariantMap
-{
-    VariantMap();
-    ~VariantMap();
-
-    tolua_outside void VariantMapSetInt @ SetInt(const String key, int value);
-    tolua_outside void VariantMapSetUInt @ SetUInt(const String key, unsigned value);
-    tolua_outside void VariantMapSetStringHash @ SetStringHash(const String key, const StringHash& value);
-    tolua_outside void VariantMapSetBool @ SetBool(const String key, bool value);
-    tolua_outside void VariantMapSetFloat @ SetFloat(const String key, float value);
-    tolua_outside void VariantMapSetDouble @ SetDouble(const String key, double value);
-    tolua_outside void VariantMapSetVector2 @ SetVector2(const String key, const Vector2 value);
-    tolua_outside void VariantMapSetVector3 @ SetVector3(const String key, const Vector3 value);
-    tolua_outside void VariantMapSetVector4 @ SetVector4(const String key, const Vector4 value);
-    tolua_outside void VariantMapSetQuaternion @ SetQuaternion(const String key, const Quaternion value);
-    tolua_outside void VariantMapSetColor @ SetColor(const String key, const Color value);
-    tolua_outside void VariantMapSetString @ SetString(const String key, const String value);
-    tolua_outside void VariantMapSetBuffer @ SetBuffer(const String key, const VectorBuffer& value);
-    tolua_outside void VariantMapSetResourceRef @ SetResourceRef(const String key, const ResourceRef value);
-    tolua_outside void VariantMapSetResourceRefList @ SetResourceRefList(const String key, const ResourceRefList value);
-    tolua_outside void VariantMapSetVariantVector @ SetVariantVector(const String key, const VariantVector& value);
-    tolua_outside void VariantMapSetIntRect @ SetIntRect(const String key, const IntRect value);
-    tolua_outside void VariantMapSetIntVector2 @ SetIntVector2(const String key, const IntVector2 value);
-    tolua_outside void VariantMapSetPtr @ SetPtr(const String key, void* value);
-    tolua_outside void VariantMapSetMatrix3 @ SetMatrix3(const String key, const Matrix3 value);
-    tolua_outside void VariantMapSetMatrix3x4 @ SetMatrix3x4(const String key, const Matrix3x4 value);
-    tolua_outside void VariantMapSetMatrix4 @ SetMatrix4(const String key, const Matrix4 value);
-
-    tolua_outside int VariantMapGetInt @ GetInt(const String key);
-    tolua_outside int VariantMapGetUInt @ GetUInt(const String key);
-    tolua_outside StringHash VariantMapGetStringHash @ GetStringHash(const String key);
-    tolua_outside bool VariantMapGetBool @ GetBool(const String key);
-    tolua_outside float VariantMapGetFloat @ GetFloat(const String key);
-    tolua_outside double VariantMapGetDouble @ GetDouble(const String key);
-    tolua_outside const Vector2& VariantMapGetVector2 @ GetVector2(const String key);
-    tolua_outside const Vector3& VariantMapGetVector3 @ GetVector3(const String key);
-    tolua_outside const Vector4& VariantMapGetVector4 @ GetVector4(const String key);
-    tolua_outside const Quaternion& VariantMapGetQuaternion @ GetQuaternion(const String key);
-    tolua_outside const Color& VariantMapGetColor @ GetColor(const String key);
-    tolua_outside const String VariantMapGetString @ GetString(const String key);
-    tolua_outside VectorBuffer VariantMapGetBuffer @ GetBuffer(const String key);
-    tolua_outside const ResourceRef& VariantMapGetResourceRef @ GetResourceRef(const String key);
-    tolua_outside const ResourceRefList& VariantMapGetResourceRefList @ GetResourceRefList(const String key);
-    tolua_outside const VariantVector VariantMapGetVariantVector @ GetVariantVector(const String key);
-//    const Vector<String>& GetStringVector() const;
-    tolua_outside const IntRect& VariantMapGetIntRect @ GetIntRect(const String key);
-    tolua_outside const IntVector2& VariantMapGetIntVector2 @ GetIntVector2(const String key);
-    tolua_outside const void* VariantMapGetPtr @ GetPtr(const String type, const String key);
-    tolua_outside const Matrix3& VariantMapGetMatrix3 @ GetMatrix3(const String key);
-    tolua_outside const Matrix3x4& VariantMapGetMatrix3x4 @ GetMatrix3x4(const String key);
-    tolua_outside const Matrix4& VariantMapGetMatrix4 @ GetMatrix4(const String key);
-};
-
 ${
-static void VariantSetInt(Variant* variant, int value)
-{
-    *variant = value;
-}
-
-static void VariantSetUint(Variant* variant, unsigned value)
-{
-    *variant = value;
-}
-
-static void VariantSetStringHash(Variant* variant, const StringHash& value)
-{
-    *variant = value;
-}
-
-static void VariantSetBool(Variant* variant, bool value)
-{
-    *variant = value;
-}
-
-static void VariantSetFloat(Variant* variant, float value)
-{
-    *variant = value;
-}
-
-static void VariantSetDouble(Variant* variant, double value)
-{
-    *variant = value;
-}
-
-static void VariantSetVector2(Variant* variant, const Vector2& value)
-{
-    *variant = value;
-}
-
-static void VariantSetVector3(Variant* variant, const Vector3& value)
-{
-    *variant = value;
-}
-
-static void VariantSetVector4(Variant* variant, const Vector4& value)
-{
-    *variant = value;
-}
-
-static void VariantSetQuaternion(Variant* variant, const Quaternion& value)
-{
-    *variant = value;
-}
-
-static void VariantSetColor(Variant* variant, const Color& value)
-{
-    *variant = value;
-}
-
-static void VariantSetString(Variant* variant, const String value)
-{
-    *variant = value;
-}
-
-static void VariantSetBuffer(Variant* variant, const VectorBuffer& value)
-{
-    variant->SetBuffer(value.GetData(), value.GetBuffer().Size());
-}
-
-static void VariantSetResourceRef(Variant* variant, const ResourceRef& value)
-{
-    *variant = value;
-}
-
-static void VariantSetResourceRefList(Variant* variant, const ResourceRefList& value)
-{
-    *variant = value;
-}
 
-static void VariantSetIntRect(Variant* variant, const IntRect& value)
+static void VariantConstructFromBuffer(Variant* variant, const VectorBuffer& value)
 {
-    *variant = value;
+    *variant = value.GetBuffer();
 }
 
-static void VariantSetIntVector2(Variant* variant, const IntVector2& value)
+static bool VariantEqualWithBuffer(const Variant* variant, const VectorBuffer& rhs)
 {
-    *variant = value;
-}
-
-static void VariantSetMatrix3(Variant* variant, const Matrix3& value)
-{
-    *variant = value;
-}
-
-static void VariantSetMatrix3x4(Variant* variant, const Matrix3x4& value)
-{
-    *variant = value;
-}
-
-static void VariantSetMatrix4(Variant* variant, const Matrix4& value)
-{
-    *variant = value;
+    return variant->operator ==(rhs.GetBuffer());
 }
 
 static VectorBuffer VariantGetBuffer(const Variant* variant)
@@ -320,292 +175,141 @@ static VectorBuffer VariantGetBuffer(const Variant* variant)
     return VectorBuffer(variant->GetBuffer());
 }
 
-static void VariantMapSetInt(VariantMap* vmap, const String& key, int value)
-{
-    (*vmap)[StringHash(key)] = value;
-}
-
-static void VariantMapSetUInt(VariantMap* vmap, const String& key, unsigned value)
-{
-    (*vmap)[StringHash(key)] = value;
-}
-
-static void VariantMapSetStringHash(VariantMap* vmap, const String& key, const StringHash& value)
-{
-    (*vmap)[StringHash(key)] = value;
-}
-
-static void VariantMapSetBool(VariantMap* vmap, const String& key, bool value)
-{
-    (*vmap)[StringHash(key)] = value;
-}
-
-static void VariantMapSetFloat(VariantMap* vmap, const String& key, float value)
-{
-    (*vmap)[StringHash(key)] = value;
-}
-
-static void VariantMapSetDouble(VariantMap* vmap, const String& key, double value)
-{
-    (*vmap)[StringHash(key)] = value;
-}
-
-static void VariantMapSetVector2(VariantMap* vmap, const String& key, const Vector2& value)
-{
-    (*vmap)[StringHash(key)] = value;
-}
-
-static void VariantMapSetVector3(VariantMap* vmap, const String& key, const Vector3& value)
-{
-    (*vmap)[StringHash(key)] = value;
-}
-
-static void VariantMapSetVector4(VariantMap* vmap, const String& key, const Vector4& value)
-{
-    (*vmap)[StringHash(key)] = value;
-}
-
-static void VariantMapSetQuaternion(VariantMap* vmap, const String& key, const Quaternion& value)
-{
-    (*vmap)[StringHash(key)] = value;
-}
-
-static void VariantMapSetColor(VariantMap* vmap, const String& key, const Color& value)
-{
-    (*vmap)[StringHash(key)] = value;
-}
-
-static void VariantMapSetString(VariantMap* vmap, const String& key, const String& value)
-{
-    (*vmap)[StringHash(key)] = value;
-}
-
-static void VariantMapSetBuffer(VariantMap* vmap, const String& key, const VectorBuffer& value)
-{
-    (*vmap)[StringHash(key)].SetBuffer(value.GetData(), value.GetBuffer().Size());
-}
-
-static void VariantMapSetResourceRef(VariantMap* vmap, const String& key, const ResourceRef& value)
-{
-    (*vmap)[StringHash(key)] = value;
-}
-
-static void VariantMapSetResourceRefList(VariantMap* vmap, const String& key, const ResourceRefList& value)
-{
-    (*vmap)[StringHash(key)] = value;
-}
-
-static void VariantMapSetVariantVector(VariantMap* vmap, const String& key, const VariantVector& value)
-{
-    (*vmap)[StringHash(key)] = value;
-}
-
-static void VariantMapSetIntRect(VariantMap* vmap, const String& key, const IntRect& value)
-{
-    (*vmap)[StringHash(key)] = value;
-}
-
-static void VariantMapSetIntVector2(VariantMap* vmap, const String& key, const IntVector2& value)
-{
-    (*vmap)[StringHash(key)] = value;
-}
-
-static void VariantMapSetPtr(VariantMap* vmap, const String& key, void* value)
-{
-    (*vmap)[StringHash(key)] = value;
-}
-
-static void VariantMapSetMatrix3(VariantMap* vmap, const String& key, const Matrix3& value)
-{
-    (*vmap)[StringHash(key)] = value;
-}
-
-static void VariantMapSetMatrix3x4(VariantMap* vmap, const String& key, const Matrix3x4& value)
-{
-    (*vmap)[StringHash(key)] = value;
-}
-
-static void VariantMapSetMatrix4(VariantMap* vmap, const String& key, const Matrix4& value)
-{
-    (*vmap)[StringHash(key)] = value;
-}
-
-static const Variant& FindVariant(const VariantMap* vmap, const String& key)
-{
-    VariantMap::ConstIterator i = vmap->Find(StringHash(key));
-    return i != vmap->End() ? i->second_ : Variant::EMPTY;
-}
-
-static int VariantMapGetInt(const VariantMap* vmap, const String& key)
-{
-    return FindVariant(vmap, key).GetInt();
-}
-
-static unsigned VariantMapGetUInt(const VariantMap* vmap, const String& key)
-{
-    return FindVariant(vmap, key).GetUInt();
-}
-
-static StringHash VariantMapGetStringHash(const VariantMap* vmap, const String& key)
-{
-    return FindVariant(vmap, key).GetStringHash();
-}
-
-static bool VariantMapGetBool(const VariantMap* vmap, const String& key)
-{
-    return FindVariant(vmap, key).GetBool();
-}
-
-static float VariantMapGetFloat(const VariantMap* vmap, const String& key)
-{
-    return FindVariant(vmap, key).GetFloat();
-}
-
-static double VariantMapGetDouble(const VariantMap* vmap, const String& key)
-{
-    return FindVariant(vmap, key).GetDouble();
-}
-
-static const Vector2& VariantMapGetVector2(const VariantMap* vmap, const String& key)
-{
-    return FindVariant(vmap, key).GetVector2();
-}
-
-static const Vector3& VariantMapGetVector3(const VariantMap* vmap, const String& key)
-{
-    return FindVariant(vmap, key).GetVector3();
-}
-
-static const Vector4& VariantMapGetVector4(const VariantMap* vmap, const String& key)
-{
-    return FindVariant(vmap, key).GetVector4();
-}
-
-static const Quaternion& VariantMapGetQuaternion(const VariantMap* vmap, const String& key)
-{
-    return FindVariant(vmap, key).GetQuaternion();
-}
-
-static const Color& VariantMapGetColor(const VariantMap* vmap, const String& key)
-{
-    return FindVariant(vmap, key).GetColor();
-}
-
-static const String& VariantMapGetString(const VariantMap* vmap, const String& key)
-{
-    return FindVariant(vmap, key).GetString();
-}
-
-static VectorBuffer VariantMapGetBuffer(const VariantMap* vmap, const String key)
-{
-    const PODVector<unsigned char>& buffer = FindVariant(vmap, key).GetBuffer();
-    return VectorBuffer(buffer);
-}
-
-static const ResourceRef& VariantMapGetResourceRef(const VariantMap* vmap, const String& key)
-{
-    return FindVariant(vmap, key).GetResourceRef();
-}
-
-static const ResourceRefList& VariantMapGetResourceRefList(const VariantMap* vmap, const String& key)
-{
-    return FindVariant(vmap, key).GetResourceRefList();
-}
-
-static const VariantVector VariantMapGetVariantVector(const VariantMap* vmap, const String& key)
-{
-    // Return a new copy
-    return VariantVector(FindVariant(vmap, key).GetVariantVector());
-}
-
-static const IntRect& VariantMapGetIntRect(const VariantMap* vmap, const String& key)
-{
-    return FindVariant(vmap, key).GetIntRect();
-}
+$}
 
-static const IntVector2& VariantMapGetIntVector2(const VariantMap* vmap, const String& key)
+class VariantMap
 {
-    return FindVariant(vmap, key).GetIntVector2();
-}
+    VariantMap();
+    ~VariantMap();
 
-static const Matrix3& VariantMapGetMatrix3(const VariantMap* vmap, const String& key)
-{
-    return FindVariant(vmap, key).GetMatrix3();
-}
+    static void _SetupIndex(const char* type);
+};
 
-static const Matrix3x4& VariantMapGetMatrix3x4(const VariantMap* vmap, const String& key)
-{
-    return FindVariant(vmap, key).GetMatrix3x4();
-}
+$[
+    -- Call the setup method and then hide it immediately
+    VariantMap:_SetupIndex("VariantMap")
+    VariantMap:_SetupIndex("const VariantMap")
+    VariantMap._SetupIndex = nil
+$]
 
-static const Matrix4& VariantMapGetMatrix4(const VariantMap* vmap, const String& key)
-{
-    return FindVariant(vmap, key).GetMatrix4();
-}
+${
 
-#define TOLUA_DISABLE_tolua_CoreLuaAPI_VariantMap_SetPtr00
-static int tolua_CoreLuaAPI_VariantMap_SetPtr00(lua_State* tolua_S)
+static int VariantMapIndexEvent (lua_State* tolua_S)
+{
+    int t = lua_type(tolua_S, 2);
+    StringHash key;
+    if (t == LUA_TSTRING)
+        key = StringHash(lua_tostring(tolua_S, 2));
+    else if (t == LUA_TNUMBER)
+        key = StringHash(lua_tonumber(tolua_S, 2));
+    else
+    {
+        lua_pushnil(tolua_S);
+        return 1;
+    }
+    Variant* variant = static_cast<const VariantMap*>(tolua_tousertype(tolua_S, 1, 0))->operator [](key);
+    if (variant)
+        tolua_pushusertype(tolua_S, variant, "Variant");
+    else
+        lua_pushnil(tolua_S);
+    return 1;
+}
+
+static int VariantMapNewIndexEvent (lua_State* tolua_S)
+{
+    int t = lua_type(tolua_S, 2);
+    StringHash key;
+    if (t == LUA_TSTRING)
+        key = StringHash(lua_tostring(tolua_S, 2));
+    else if (t == LUA_TNUMBER)
+        key = StringHash(lua_tonumber(tolua_S, 2));
+    else
+        return 0;
+    Variant& variant = static_cast<VariantMap*>(tolua_tousertype(tolua_S, 1, 0))->operator [](key);     // autovivification
+    switch (lua_type(tolua_S, 3))   // Use the type of lua object to determine the final variant type
+    {
+    case LUA_TNIL:
+        variant = Variant::EMPTY;
+        break;
+
+    case LUA_TBOOLEAN:
+        variant = (bool)lua_toboolean(tolua_S, 3);     // Still need to cast to bool as Lua/LuaJIT return it as int
+        break;
+
+    case LUA_TNUMBER:
+        {
+            // Use the original variant type to further determine the final variant type
+            // CAVEAT:
+            // If lhs has integral data type and double is desired then lhs needs to be reset first before assigning
+            double value = lua_tonumber(tolua_S, 3);
+            switch (variant.GetType())
+            {
+            case VAR_INT:
+                variant = (int)value;
+                break;
+
+            case VAR_BOOL:
+                variant = value != 0.0f;
+                break;
+
+            case VAR_FLOAT:
+                variant = (float)value;
+                break;
+
+            default:
+                variant = value;
+            }
+        }
+        break;
+
+    case LUA_TSTRING:
+        variant = lua_tostring(tolua_S, 3);
+        break;
+
+    case LUA_TUSERDATA:
+    case LUA_TLIGHTUSERDATA:
+    case LUA_TTABLE:
+    case LUA_TFUNCTION:
+    case LUA_TTHREAD:
+        printf("TODO: VariantMapIndexEvent does not yet support Lua type %d", lua_type(tolua_S, 3));
+        break;
+    }
+    return 0;
+}
+
+#define TOLUA_DISABLE_tolua_CoreLuaAPI_VariantMap__SetupIndex00
+static int tolua_CoreLuaAPI_VariantMap__SetupIndex00(lua_State* tolua_S)
 {
 #ifndef TOLUA_RELEASE
  tolua_Error tolua_err;
  if (
- !tolua_isusertype(tolua_S,1,"VariantMap",0,&tolua_err) ||
- !tolua_isurho3dstring(tolua_S,2,0,&tolua_err) ||
- !tolua_isuserdata(tolua_S,3,0,&tolua_err) ||
- !tolua_isnoobj(tolua_S,4,&tolua_err)
+ !tolua_isusertable(tolua_S,1,"VariantMap",0,&tolua_err) ||
+ !tolua_isstring(tolua_S,2,0,&tolua_err) ||
+ !tolua_isnoobj(tolua_S,3,&tolua_err)
  )
  goto tolua_lerror;
  else
 #endif
  {
-  VariantMap* self = (VariantMap*)  tolua_tousertype(tolua_S,1,0);
-  const String key = ((const String)  tolua_tourho3dstring(tolua_S,2,0));
-  void* value = ((void*) tolua_tousertype(tolua_S,3,0));
-#ifndef TOLUA_RELEASE
- if (!self) tolua_error(tolua_S,"invalid 'self' in function 'VariantMapSetPtr'", NULL);
-#endif
+  const char* type = ((const char*)  tolua_tostring(tolua_S,2,0));
  {
-  VariantMapSetPtr(self,key,value);
+  // Register our own version of metamethod to handle index and new-index events
+  luaL_getmetatable(tolua_S, type);
+  lua_pushstring(tolua_S, "__index");
+  lua_pushcfunction(tolua_S, VariantMapIndexEvent);
+  lua_rawset(tolua_S, -3);
+  lua_pushstring(tolua_S, "__newindex");
+  lua_pushcfunction(tolua_S, VariantMapNewIndexEvent);
+  lua_rawset(tolua_S, -3);
+  lua_pop(tolua_S, 1);
  }
  }
  return 0;
 #ifndef TOLUA_RELEASE
  tolua_lerror:
- tolua_error(tolua_S,"#ferror in function 'SetPtr'.",&tolua_err);
+ tolua_error(tolua_S,"#ferror in function '_SetupIndex'.",&tolua_err);
  return 0;
 #endif
 }
 
-#define TOLUA_DISABLE_tolua_CoreLuaAPI_VariantMap_GetPtr00
-
-static int tolua_CoreLuaAPI_VariantMap_GetPtr00(lua_State* tolua_S)
-{
-#ifndef TOLUA_RELEASE
- tolua_Error tolua_err;
- if (!tolua_isusertype(tolua_S,1,"VariantMap",0,&tolua_err) ||
-  !tolua_isurho3dstring(tolua_S,2,0,&tolua_err) ||
-  !tolua_isurho3dstring(tolua_S,3,0,&tolua_err) ||
-  !tolua_isnoobj(tolua_S,4,&tolua_err))
-  goto tolua_lerror;
- else
-#endif
- {
-  VariantMap* self = (VariantMap*)  tolua_tousertype(tolua_S,1,0);
-  const String type = ((const String)  tolua_tourho3dstring(tolua_S,2,0));
-  const String key = ((const String)  tolua_tourho3dstring(tolua_S,3,0));
-#ifndef TOLUA_RELEASE
-  if (!self) tolua_error(tolua_S,"invalid 'self' in function 'VariantMapGetPtr'", NULL);
-#endif
-  {
-   void* tolua_ret = (void*)FindVariant(self, key).GetVoidPtr();
-   tolua_pushusertype(tolua_S,tolua_ret, type.CString());
-  }
- }
- return 1;
-#ifndef TOLUA_RELEASE
-tolua_lerror:
- tolua_error(tolua_S,"#ferror in function 'GetPtr'.",&tolua_err);
- return 0;
-#endif
-}
 $}

+ 14 - 10
Source/Urho3D/LuaScript/pkgs/ToDoxHook.lua

@@ -74,7 +74,7 @@ end
 function classEnumerate:print(ident,close)
   local enumerate = {}
   enumerate.name = self.name
-  
+
   local i = 1
   while self[i] do
     if self[i] ~= "" then
@@ -182,7 +182,7 @@ function classVariable:print(ident,close)
   property.name = self.lname
   property.def  = self.def
   property.ret  = self.ret
-  
+
   if currentClass == nil then
     if property.mod:find("tolua_property__") == nil then
       table.insert(globalConstants, property)
@@ -198,7 +198,7 @@ function classVariable:print(ident,close)
   end
 end
 
-function classVerbatim:print(ident,close)  
+function classVerbatim:print(ident,close)
 end
 
 function sortByName(t)
@@ -512,7 +512,11 @@ function writeEnumerates(file)
   end
 end
 
-function writeFunction(file, func)  
+function writeFunction(file, func)
+  if func.name:match("^_") then
+    -- Skip internal functions
+    return
+  end
   local line = "- "
   -- construct function
   if func.type == "" and func.ptr == "" then
@@ -536,7 +540,7 @@ function writeFunction(file, func)
 
       if i ~= count then
         line = line .. ", "
-      end      
+      end
     end
   end
 
@@ -558,12 +562,12 @@ function writeGlobalConstants(file)
     file:write(line .. "\n")
   end
 
-  file:write("\n")  
+  file:write("\n")
 end
 
-function writeGlobalFunctions(file)  
+function writeGlobalFunctions(file)
   sortByName(globalFunctions)
-  file:write("\n\\section LuaScriptAPI_GlobalFunctions Global functions\n")  
+  file:write("\n\\section LuaScriptAPI_GlobalFunctions Global functions\n")
 
   for i, func in ipairs(globalFunctions) do
     writeFunction(file, func)
@@ -593,7 +597,7 @@ end
 
 function classPackage:print()
   curDir = getCurrentDirectory()
-  
+
   if flags.o == nil then
     print("Invalid output filename");
     return
@@ -622,7 +626,7 @@ function classPackage:print()
   writeGlobalFunctions(file)
   writeGlobalProperties(file)
   writeGlobalConstants(file)
-  
+
   file:write("*/\n")
   file:write("\n")
   file:write("}\n")

+ 35 - 37
bin/Data/LuaScripts/41_DatabaseDemo.lua

@@ -75,8 +75,8 @@ For example:]])
 end
 
 function HandleConsoleCommand(eventType, eventData)
-    if eventData:GetString("Id") == "LuaScriptEventInvoker" then
-        HandleInput(eventData:GetString("Command"))
+    if eventData["Id"]:GetString() == "LuaScriptEventInvoker" then
+        HandleInput(eventData["Command"]:GetString())
     end
 end
 
@@ -90,7 +90,7 @@ end
 
 function HandleEscKeyDown(eventType, eventData)
     -- Unlike the other samples, exiting the engine when ESC is pressed instead of just closing the console
-    if eventData:GetInt("Key") == KEY_ESC then
+    if eventData["Key"]:GetInt() == KEY_ESC then
         engine:Exit()
     end
 end
@@ -98,19 +98,18 @@ end
 function HandleDbCursor(eventType, eventData)
     -- In a real application the P_SQL can be used to do the logic branching in a shared event handler
     -- However, this is not required in this sample demo
-    local numCols = eventData:GetUInt("NumCols")
---    local colValues = eventData:GetVariantVector("ColValues")
---    local colHeaders = eventData:GetStringVector("ColHeaders")
+    local colValues = eventData["ColValues"]:GetVariantVector()
+    local colHeaders = eventData["ColHeaders"]:GetStringVector()
 
     -- In this sample demo we just use db cursor to dump each row immediately so we can filter out the row to conserve memory
     -- In a real application this can be used to perform the client-side filtering logic
-    eventData:SetBool("Filter", true)
+    eventData["Filter"] = true
     -- In this sample demo we abort the further cursor movement when maximum rows being dumped has been reached
     row = row + 1
-    eventData:SetBool("Abort", row >= maxRows)
+    eventData["Abort"] = row >= maxRows
 
-    for i = 1, numCols do
---        Print("Row #" .. row .. ": " .. colHeaders[i] .. " = " .. colValues[i]:ToString())
+    for i, colHeader in pairs(colHeaders) do
+        Print("Row #" .. row .. ": " .. colHeader .. " = " .. colValues[i]:ToString())
     end
 end
 
@@ -120,33 +119,32 @@ function HandleInput(input)
     row = 0
     if input == "quit" or input == "exit" then
         engine:Exit()
---    elseif input:StartsWith("set") or input:StartsWith("get") then
---        -- We expect a key/value pair for 'set' command
---        local tokens = input:Substring(3):Split(' ')
---        local setting = tokens.length > 0 and tokens[0] or ""
---        if input:StartsWith("set") and tokens.length > 1 then
---            if setting == "maxrows" then
---                maxRows = Max(tokens[1]:ToUInt(), 1)
---            elseif (setting == "connstr") then
---                local newConnectionString = String(input:Substring(input:Find(" ", input:Find("connstr")) + 1))
---                local newConnection = database:Connect(newConnectionString)
---                if newConnection ~= nil then
---                    database:Disconnect(connection)
---                    connection = newConnection
---                end
---            end
---        end
---        if tokens.length > 0 then
---            if setting == "maxrows" then
---                Print("maximum rows is set to " + maxRows)
---            elseif setting == "connstr" then
---                Print("connection string is set to " + connection.connectionString)
---            else
---                Print("Unrecognized setting: " + setting)
---            end
---        else
---            Print("Missing setting paramater. Recognized settings are: maxrows, connstr")
---        end
+    elseif input:find("set") or input:find("get") then
+        -- We expect a key/value pair for 'set' command
+        local command, setting, value
+        _, _, command, setting, value = input:find("([gs]et)%s*(%a*)%s*(.*)")
+        if command == "set" and value ~= nil then
+            if setting == "maxrows" then
+                maxRows = Max(value, 1)
+            elseif (setting == "connstr") then
+                local newConnection = database:Connect(value)
+                if newConnection ~= nil then
+                    database:Disconnect(connection)
+                    connection = newConnection
+                end
+            end
+        end
+        if setting ~= nil then
+            if setting == "maxrows" then
+                Print("maximum rows is set to " .. maxRows)
+            elseif setting == "connstr" then
+                Print("connection string is set to " .. connection.connectionString)
+            else
+                Print("Unrecognized setting: " .. setting)
+            end
+        else
+            Print("Missing setting paramater. Recognized settings are: maxrows, connstr")
+        end
     else
         -- In this sample demo we use the dbCursor event to loop through each row as it is being fetched
         -- Regardless of this event is being used or not, all the fetched rows will be made available in the DbResult object,