Code archives/Miscellaneous/keefpersistence
This code has been declared by its author to be Public Domain code.
Download source code
| |||||
| This is the same as bruceys persistence module except: this persistence library simply doesnt store zeroes or nulls for a much smaller file size and faster loading time. | |||||
Strict
Module keef.keefpersistence
Import bah.libxml
Import brl.map
Import brl.reflection
Global object_Map:TMap
Function save_obj(i:Object, filename$)
object_map=New Tmap
Global doc:TxmlDoc = TxmlDoc.newdoc("1.0")
Local root:TxmlNode = TxmlNode.newnode("root")
doc.setrootelement(root)
Local thisnode:TxmlNode=root.addchild("object")
serialize_obj(thisnode,i )
doc.saveFile(filename)
EndFunction
Function serialize_obj(node:TxmlNode, i:Object)
Local tid:TTypeId = TTypeId.ForObject(i)
'Print "saving " + tid.Name()
Local thename:String=tid.name()
node.setattribute("type",thename)
Local objRef:String = GetObjRef(i)
node.setAttribute("ref", objRef)
object_Map.Insert(objRef, objRef)
If thename="TList"
node.setAttribute("type", theName)
Local listy:TList=TList(i)
For Local ob:Object=EachIn listy
Local tid2:TTypeId = TTypeId.ForObject(ob)
Local thisnode:TxmlNode = node.addchild("listelement")
thisnode.setattribute("type",tid2.name())
serialize_obj(thisnode,ob)
Next
Return
EndIf
If theName.endswith("[]")
'Local thisnode:TxmlNode = node.addchild("array")
Local size:Int
size = tid.ArrayLength(i)
node.setAttribute("type", theName)
node.setAttribute("size", size)
If size > 0 Then
saveArray(i, size, node, tid)
Else
node.setattribute("value","null")
End If
EndIf
If thename = "TMap"
' special case for TMaps
' They have a Global "nil" object which needs to be referenced properly.
' We add a specific reference to nil, which we'll use to re-reference when we de-serialize.
Local ref:String = GetObjRef(New TMap._root)
If Not object_Map.ValueForKey(ref) Then
'Local node:TxmlNode = parent.addChild("TMap_nil")
node.setAttribute("nil", ref)
object_Map.Insert(ref, ref)
End If
EndIf
For Local f:TField = EachIn tid.EnumFields()
' Print "field name: " + f.Name()
If f.MetaData("nopersist") Then
Continue
End If
Local fieldType:TTypeId = f.TypeId()
Local fieldNode:TxmlNode
Select fieldType
Case ByteTypeId
If f.getint(i)=Null Or f.getint(i)=0
Continue
EndIf
fieldnode= node.addChild("field")
fieldNode.setattribute("value", f.GetInt(i))
Case ShortTypeId
If f.getint(i)=Null Or f.getint(i)=0
Continue
EndIf
fieldNode.setattribute("value", f.GetInt(i))
Case IntTypeId
If f.getint(i)=Null Or f.getint(i)=0
Continue
EndIf
fieldnode= node.addChild("field")
fieldNode.setattribute("value", f.GetInt(i))
Case LongTypeId
If f.getlong(i)=Null Or f.getlong(i)=0
Continue
EndIf
fieldnode= node.addChild("field")
fieldNode.setattribute("value", f.GetLong(i))
Case FloatTypeId
If f.getfloat(i)=Null Or f.getfloat(i)=0
Continue
EndIf
fieldnode= node.addChild("field")
fieldNode.setattribute("value", f.GetFloat(i))
Case DoubleTypeId
If f.getdouble(i)=Null Or f.getdouble(i)=0
Continue
EndIf
fieldnode= node.addChild("field")
fieldNode.setattribute("value", f.GetDouble(i))
Case StringTypeId
If f.getstring(i)=Null Or f.getstring(i)="0" Or f.getstring(i)=""
Continue
EndIf
fieldnode= node.addChild("field")
Local s:String = f.GetString(i)
If s Then
fieldNode.setattribute("value", s)
End If
Default
If fieldtype.name().EndsWith("[]")
' Local thisnode:TxmlNode = node.addchild("array")
Local size:Int
size=fieldType.ArrayLength(f.Get(i))
If size > 0
fieldnode= node.addChild("field")
Fieldnode.setAttribute("size", size)
fieldnode.setattribute("type",fieldtype.name())
'saveArray(f, size, fieldnode, fieldType)
saveArray(f.get(i), size, fieldnode, fieldType)
End If
Else
'Print ("get object from field")
Local fieldObject:Object = f.Get(i)
Local fieldRef:String = GetObjRef(fieldObject)
If fieldObject <> Null
fieldNode = node.addChild("field")
fieldnode.setattribute("type",fieldtype.name())
If Not object_Map.Contains(fieldref) Then
serialize_obj(fieldNode, fieldObject)
Else
fieldNode.setAttribute("ref", fieldref)
End If
Else
Continue
End If
End If
End Select
fieldNode.setAttribute("name", f.Name())
fieldnode.setAttribute("type",fieldtype.name())
Next
EndFunction
Function saveArray(arrayObject:Object, size:Int, node:TxmlNode, typeId:TTypeId)
Local elementType:TTypeId = typeId.ElementType()
Select elementType
Case ByteTypeId, ShortTypeId, IntTypeId, LongTypeId, FloatTypeId, DoubleTypeId
Local content:String = ""
For Local i:Int = 0 Until size
Local aObj:Object = typeId.GetArrayElement(arrayObject, i)
'Print String(aobj)
content=String(aobj)
Local content2:Int=content.toint()
If Not content2=0
Local thisnode:TxmlNode=node.addchild("arrayelement")
thisnode.addattribute("pos",String(i))
thisnode.addattribute("value",String(aobj))
EndIf
Next
Default
Local content:String = ""
Select elementType
Case StringTypeId
For Local i:Int = 0 Until size
Local aObj:Object = typeId.GetArrayElement(arrayObject, i)
content = String(aobj)
If Not content = "0"
Local thisnode:TxmlNode = node.addchild("arrayelement")
thisnode.addattribute("pos", String(i))
thisnode.addattribute("value", content)
EndIf
Next
Default
For Local i:Int = 0 Until size
Local aObj:Object = typeId.GetArrayElement(arrayObject, i)
If aobj<>Null
Local thisnode:TxmlNode = node.addchild("arrayelement")
thisnode.addattribute("pos", String(i))
thisnode.addattribute("type", typeId.elementType().Name())
'If typeId.elementType().Name().endswith("[]")
'Local thisnode2:TxmlNode=TxmlNode(thisnode.getfirstchild())
'serialize_obj(thisNode2, aObj)
'Else
serialize_obj(thisNode, aObj)
'EndIf
EndIf
Next
End Select
End Select
EndFunction
Function load_object:Object(filename$)
object_map=New tmap
' Print "loading object " + filename
Local doc:TxmlDoc = TxmlDoc.parseFile(filename)
Local obby:Object
If doc
'Print "doc is not null"
Local root:TxmlNode = doc.GetRootElement()
For Local thisnode:TxmlNode=EachIn root.getchildren()
obby:Object = DeSerializeObject("", thisnode,doc)
doc.Free()
doc = Null
Next
Else
'Print "doc is null"
End If
Local arr:Int[] = Int[] obby
For Local x:Int = 0 To arr.length - 1
'Print arr[x]
Next
Return obby
EndFunction
Function DeSerializeObject:Object(text:String, node:TxmlNode = Null,doc:TxmlDoc)
'If node.getattribute("type")="map_square"
'DebugLog "deserializing map square"
'EndIf
'DebugLog "argh fuck "+node.getname()
Local obj:Object
'Local nodelist:TList = node.getchildren()
Local ref:String = Node.getAttribute("ref")
If ref
Local objRef:Object = object_Map.ValueForKey(ref)
If objRef
Return objref
EndIf
EndIf
Local objType:TTypeId = TTypeId.ForName(node.getattribute("type"))
If node.getattribute("type").endswith("[]")
'If node.getattribute("type")="map_square[]"
'DebugLog "creating array in deserialize object "+node.getattribute("type")
'EndIf
obj = Create_array(node, doc)
'If node.getattribute("type")="map_square[]"
'If obj=Null
'DebugLog "returning null array"
'Else
'DebugLog "returning full array"
'EndIf
'EndIf
Else
If node.getattribute("type")="TList"
'Print "deserializing list:"
Local listy:TList= New TList
obj=Object(listy)
object_Map.Insert(node.getAttribute("ref"), obj)
Local listy2:TList=node.getchildren()
If listy2<>Null
For Local c:TxmlNode=EachIn listy2
If c.getattribute("type")="String"
listy.addlast(c.getattribute("value"))
Else
listy.addlast(deSerializeObject("", c,doc))
EndIf
Next
EndIf
Return obj
EndIf
If node.getattribute("type") = "TMap"
' special case for TMaps
' They have a Global "nil" object which needs to be referenced properly.
Local attr:String = node.getAttribute("nil")
If attr Then
object_Map.Insert(attr, New TMap._root)
End If
End If
obj=objType.NewObject()
object_Map.Insert(node.getAttribute("ref"), obj)
Local listy:TList=node.getchildren()
If listy <> Null Then
For Local fieldNode:TxmlNode = EachIn listy
If fieldNode.GetName() = "field"
Local fieldObj:TField = objType.FindField(fieldnode.getAttribute("name"))
If fieldobj<>Null
Local fieldType:String = fieldNode.getAttribute("type")
Select fieldType
Case "Byte", "Short", "Int"
fieldObj.SetInt(obj, fieldNode.getattribute("value").toInt())
'If node.getattribute("type")="map_square"
'DebugLog fieldNode.getattribute("value")+" "+ fieldNode.getattribute("name")
'EndIf
Case "Long"
fieldObj.SetLong(obj, fieldNode.getattribute("value").toLong())
Case "Float"
fieldObj.SetFloat(obj, fieldNode.getattribute("value").toFloat())
Case "Double"
fieldObj.SetDouble(obj, fieldNode.getattribute("value").toDouble())
Case "String"
fieldObj.SetString(obj, fieldnode.getattribute("value"))
Default
Local ref:String = fieldNode.getAttribute("ref")
If ref Then
Local objRef:Object = object_Map.ValueForKey(ref)
If objRef Then
fieldObj.Set(obj, objRef)
Else
fieldObj.Set(obj, DeSerializeObject("", fieldNode,doc))
End If
Else
fieldObj.Set(obj, DeSerializeObject("", fieldNode,doc))
End If
EndSelect
EndIf
EndIf
Next
EndIf
EndIf
'If node.getattribute("type")="map_square"
'DebugLog "returning obj"
'EndIf
Return obj
End Function
Function Create_array:Object(node:TxmlNode, doc:TxmlDoc)
'If node.getattribute("type")="map_square[]"
'DebugLog "Create array function"
'EndIf
Local objType:TTypeId = TTypeId.ForName(node.getAttribute("type"))
Local size:Int = node.getAttribute("size").toInt()
Local obj:Object = objType.NewArray(size)
If node.getattribute("type")="map_square[]"
If obj=Null
DebugLog "array object is null"
EndIf
EndIf
If obj<>Null
'If node.getattribute("type")="map_square[]"
'DebugLog "array object is not null:"
'EndIf
If size > 0
If node.getattribute("type")="map_square[]"
DebugLog "array size is bigger than zero:"+size
EndIf
Local arrayElementType:TTypeId = objType.ElementType()
'Print "array is: "+arrayelementtype.name()
Select arrayElementType
Case ByteTypeId, ShortTypeId, IntTypeId, LongTypeId, FloatTypeId, DoubleTypeId
'Print"array element is int"
Local arraylist:TList = node.getChildren()
Local arraynode:TxmlNode
If arraylist<>Null
For arraynode = EachIn arraylist
'Print arraynode.getAttribute("value")
'Print arraynode.getAttribute("pos")
If Int arraynode.getAttribute("value") <> 0
objType.SetArrayElement(obj, Int arraynode.getAttribute("pos") , Object arraynode.getAttribute("value"))
EndIf
Next
EndIf
Default
Local arrayList:TList = node.getChildren()
If arrayList
Local i:Int
For Local arrayNode:TxmlNode = EachIn arrayList
Select arrayElementType
Case StringTypeId
If arrayNode.Getattribute("value")<>""
objType.SetArrayElement(obj, Int arraynode.getAttribute("pos"), arrayNode.Getattribute("value"))
EndIf
Default
objType.SetArrayElement(obj, Int arraynode.getAttribute("pos"), DeSerializeObject("", arrayNode, doc))
End Select
i:+ 1
Next
EndIf
End Select
EndIf
End If
Return obj
EndFunction
Function GetObjRef:String(obj:Object)
Return Base36(Int(Byte Ptr(obj)))
End Function
Function Base36:String( val:Int )
Local buf:Short[6]
For Local k:Int=5 To 0 Step -1
Local n:Int=(val Mod 36) + 48
If n > 57 n:+ 7
buf[k]=n
val = val / 36
Next
Return String.FromShorts( buf,6 )
End Function |
Comments
| ||
| Deleted. |
| ||
| I love arrays. EDIT: Wait a minute, this is BlitzMax - my bad. EDIT: I edited my post and it created a new one - just in case anyone thinks I was spamming. EDIT: It must have been one of those double posts and when I edited it, it edited the second post. Still, ignore me - pretend I am not here. |
| ||
| you edited the second post... |
Code Archives Forum