Code archives/Miscellaneous/lua_objectfromtable

This code has been declared by its author to be Public Domain code.

Download source code

lua_objectfromtable by N2009
There's not really a whole lot to say about this aside from how it determines how to set a value.

Provided the key in the KV pair of the table is a string, the first thing the method will do is check for a field with the same name as the key. If no field is found, it checks for a setter method matching "set<key>". If no method is found, it checks for _key, where the key is prefixed with an underscore.

If a field is found in either the first or the last case, the method checks to see if the value's type will work when assigning it to the field, and if it does the value of the field is set to that.

If a method is found, the last case will not occur. The method (referring to lua_objectfromtable) will check to make sure the value will work with the first argument of the found method. If it does, the method is called and presumably something is set.

When assigning a value to something that takes an object of any type (excluding arrays and strings) and the value is a table, the function will attempt to create an object from the table.

If any value cannot be assigned because the type of the field and the value being assigned are incompatible, an exception will be thrown. If you attempt to create an array with the method, an exception will be thrown. If you do not provide a type for the object or the value at the index provided is not a table, Null is returned.

No values are pushed onto the stack.
Strict

Import Brl.Reflection
Import LuGI.Core

Function lua_objectfromtable:Object(L@Ptr, index%, as:TTypeID)
	Local reset% = lua_gettop(L)
	
	If Not (lua_istable(L, index) And as) Then
		Return Null
	EndIf
	
	Assert as._class <> ArrayTypeID._class Else "Cannot use lua_objectfromtable to create an array"
	
	lua_pushvalue(L, index)
	lua_pushnil(L)
	
	Local obj:Object = as.NewObject()

	' poor man's profiling
'	Local findtime%=0
'	Local fsettime%=0
'	Local msettime%=0
	
'	Local _t%, _t2%, _t3%
	
	While lua_next(L, -2)
		If lua_isstring(L, -2) Then
'			_t=millisecs()
			Local key$ = lua_tostring(L, -2)
			Local f:TField = as.FindField(key)
			If Not f Then
				Local m:TMethod = as.FindMethod("set"+key)
				If m Then
'					_t2 = Millisecs()
					Select m.ArgTypes()[0]
						Case ByteTypeID, ShortTypeID, IntTypeID, LongTypeID
							Assert lua_isnumber(L, -1) Else "Invalid value for integer setter argument"
							m.Invoke(obj, [Object(String(lua_tointeger(L, -1)))])
						Case FloatTypeID, DoubleTypeID
							Assert lua_isnumber(L, -1) Else "Invalid value for float/double setter argument"
							m.Invoke(obj, [Object(String(lua_tonumber(L, -1)))])
						Case StringTypeID
							Assert lua_isstring(L, -1) Else "Invalid value for string setter argument"
						Default
							If lua_istable(L, -1) And f.TypeID()._class <> ArrayTypeID._class Then
								m.Invoke(obj, [lua_objectfromtable(L, -1, f.TypeID())])
							Else
								Assert lua_isbmaxobject(L, -1) Else "Invalid value for object setter argument"
								m.Invoke(obj, [lua_tobmaxobject(L, -1)])
							EndIf
					End Select
'					_t2 = Millisecs()-_t2
'					msettime :+ _t2
'					findtime :- _t2
				Else
					f = as.FindField("_"+key)
				EndIf
			EndIf
'			findtime :+ Millisecs()-_t
			
			If f Then
'				_t = Millisecs()
				Select f.TypeID()
					Case ByteTypeID, ShortTypeID, IntTypeID
						Assert lua_isnumber(L, -1) Else "Invalid value for integer field"
						f.SetInt(obj, lua_tointeger(L, -1))
					Case LongTypeID
						Assert lua_isnumber(L, -1) Else "Invalid value for long field"
						f.SetLong(obj, lua_tointeger(L, -1))
					Case FloatTypeID
						Assert lua_isnumber(L, -1) Else "Invalid value for float field"
						f.SetFloat(obj, lua_tonumber(L, -1))
					Case DoubleTypeID
						Assert lua_isnumber(L, -1) Else "Invalid value for double field"
						f.SetDouble(obj, lua_tonumber(L, -1))
					Case StringTypeID
						Assert lua_isstring(L, -1) Else "Invalid value for string field"
						f.Set(obj, lua_tostring(L, -1))
					Default
						If lua_istable(L, -1) And f.TypeID()._class <> ArrayTypeID._class Then
							f.Set(obj, lua_objectfromtable(L, -1, f.TypeID()))
						Else
							Assert lua_isbmaxobject(L, -1) Else "Invalid value for object field"
							f.Set(obj, lua_tobmaxobject(L, -1))
						EndIf
				End Select
'				fsettime :+ Millisecs()-_t
			EndIf
		EndIf
		
		lua_pop(L, 1)
	Wend
	
'	DebugLog "find time:       "+findtime+"ms"
'	DebugLog "method set time: "+msettime+"ms"
'	DebugLog "field set time:  "+fsettime+"ms"
	
	lua_settop(L, reset)
	
	Return obj
End Function

Comments

None.

Code Archives Forum