Тема: AHK v2: ObjDump / ObjLoad
Функция сохранения объекта в файл или память в бинарном (RAW) виде, для последующего восстановления (загрузки) в переменную.
/* example; comment this line to try
o:={}
o.var:=1234567890
o.val:="test object property"
o.arr:=[{},{}]
o.arr[1].par:="asdf"
o.arr[1].val:=1234
o.arr[2].par:="jkl;"
o.arr[2].val:=5678
o.m:=map()
o.m.var:=123.0
o.m.val:="qwer"
o.m[11]:={}
o.m[11].par:="asdf"
o.m[11].val:=1234
o.m[22]:={}
o.m[22].par:="jkl;"
o.m[22].vasl:=5678
o.b:=Buffer(3,255)
SaveFileName:=a_desktop "\Dumped Object.test"
ObjDump(SaveFileName,o)
MyObj:=ObjLoad(SaveFileName)
msgbox MyObj.var
msgbox MyObj.val
msgbox MyObj.arr[1].par
msgbox MyObj.arr[1].val
msgbox MyObj.arr[2].par
msgbox MyObj.arr[2].val
msgbox MyObj.m.var
msgbox MyObj.m.val
msgbox MyObj.m[11].par
msgbox MyObj.m[11].val
msgbox MyObj.m[22].par
msgbox MyObj.m[22].vasl
msgbox NumGet(o.b,2,"UChar")
exitapp
esc::exitapp
/*
*/
ObjLoad(addr,&offset:=0) ; load dumped object to variable; from memory (addr is int) or from file (addr is string)
{
; #requires AutoHotkey v2.0.19
If !IsNumber(addr)
{
If !FileExist(addr)
return
sz:=FileGetSize(addr)
If !sz
return
Data:=FileRead(addr,"RAW")
addr:=Data.Ptr
sz:=NumGet(addr,"Int64")
addr+=8
obj:=0
}
; Sizes 1 1 2 2 4 4 8 8 8 x x x x x
; Type.Enum: Char.1 UChar.2 Short.3 UShort.4 Int.5 UInt.6 Int64.7 UInt64.8 Double.9 Str.10 [].11 {}.12 map().13 buffer.14
static types:=["Char","UChar","Short","UShort","Int","UInt","Int64","UInt64","Double"]
static syzes:=[ 2, 2, 3, 3, 5, 5, 9, 9, 9]
typ:=NumGet(addr,offset,"Char")
if (typ<10)
{
obj:=NumGet(addr,offset+1,types[typ])
offset+=syzes[typ]
}
else if (typ=10)
{
size:=NumGet(addr,offset+1,"Int64")
obj:=StrGet(addr+offset+9,size)
offset+=9+size
}
else if (typ=11)
{
obj:=[]
size:=NumGet(addr,offset+1,"Int64")
obj.Length:=size
offset+=9
loop size
obj[a_index]:=ObjLoad(addr,&offset)
}
else if (typ=12)
{
obj:={}
Props:=NumGet(addr,offset+1,"Int64")
offset+=9
loop Props
{
k:=ObjLoad(addr,&offset)
obj.%k%:=ObjLoad(addr,&offset)
}
}
else if (typ=13)
{
obj:=Map()
Props:=NumGet(addr,offset+1,"Int64")
Items:=NumGet(addr,offset+9,"Int64")
offset+=17
loop Props
{
k:=ObjLoad(addr,&offset)
obj.%k%:=ObjLoad(addr,&offset)
}
loop Items
{
i:=ObjLoad(addr,&offset)
obj[i]:=ObjLoad(addr,&offset)
}
}
else if (typ=14)
{
size:=NumGet(addr,offset+1,"Int64")
obj:=Buffer(size)
offset+=9
loop size
NumPut("UChar",NumGet(addr,offset+a_index-1,"UChar"),obj,a_index-1)
offset+=size
}
return obj
}
ObjDump(Path,obj) ; dump object to file
{
; #requires AutoHotkey v2.0.19
if !sz:=RawObjectSize(obj)
return
If FileExist(Path)
FileDelete Path
sz+=8
Data:=Buffer(sz,0)
ptr:=Data.Ptr
NumPut("Int64",sz-8,ptr) ;size of all data
RawObject(obj,ptr+8) ; use this for dumping to memory instead of ObjDump
f:=FileOpen(Path,"rw-rwd","CP0")
Loop (sz//65536)
f.RawWrite(ptr,65536),ptr+=65536
f.RawWrite(ptr,Mod(sz,65536))
f.Close()
return sz
}
RawObject(obj,ptr,offset:=0) ; dump object to memory
{
; #requires AutoHotkey v2.0.19
; Sizes 1 1 2 2 4 4 8 8 8 x x x x x
; Type.Enum: Char.1 UChar.2 Short.3 UShort.4 Int.5 UInt.6 Int64.7 UInt64.8 Double.9 Str.10 [].11 {}.12 map().13 buffer.14
if isObject(Obj)
{
if (Obj.base=[].base)
{
NumPut("Char",11,ptr,offset) ; type
NumPut("Int64",Obj.Length,ptr,offset+1) ; Length of array
offset+=9
loop Obj.Length
offset:=RawObject(Obj[a_index],ptr,offset)
}
else if (Obj.base={}.base)
{
NumPut("Char",12,ptr,offset) ; type
NumPut("Int64",ObjOwnPropCount(Obj),ptr,offset+1) ; num of Props
offset+=9
for k,v in Obj.OwnProps()
{
offset:=RawObject(k,ptr,offset) ; name of prop (str)
offset:=RawObject(v,ptr,offset) ; value of prop (any)
}
}
else if (Obj.base=Map().base)
{
NumPut("Char",13,ptr,offset) ; type
NumPut("Int64",ObjOwnPropCount(Obj),ptr,offset+1) ; num of Props
NumPut("Int64",Obj.Count,ptr,offset+9) ; num of items
offset+=17
for k,v in Obj.OwnProps()
{
offset:=RawObject(k,ptr,offset) ; name of prop (str)
offset:=RawObject(v,ptr,offset) ; value of prop (any)
}
for k,v in Obj
{
offset:=RawObject(k,ptr,offset) ; index of item (any)
offset:=RawObject(v,ptr,offset) ; value of item (any)
}
}
else if (Obj.base=Buffer().base)
{
NumPut("Char",14,ptr,offset) ; type
NumPut("Int64",Obj.size,ptr,offset+1) ; num of bytes
offset+=9
loop Obj.size
NumPut("UChar",NumGet(Obj,a_index-1,"UChar"),ptr,offset+a_index-1) ; Buffer content (RAW)
offset+=Obj.size
}
}
else if IsNumber(obj) ; num
{
NumPut("Char",IsFloat(Obj)?9:Obj>4294967295?8 :Obj>65535?6 :Obj>255?4 :Obj>-1?2 :Obj>-129?1 :Obj>-32769?3 :Obj>-2147483649?5 :7,ptr,offset+0)
NumPut(IsFloat(Obj)?"Double":Obj>4294967295?"UInt64":Obj>65535?"UInt":Obj>255?"UShort":Obj>-1?"UChar":Obj>-129?"Char":Obj>-32769?"Short":Obj>-2147483649?"Int":"Int64",Obj,ptr,offset+1)
offset+= IsFloat(Obj)||Obj>4294967295?9 :Obj>65535?5 :Obj>255?3 :Obj>-129?2 :Obj>-32769?3 :Obj>-2147483649?5 :9
}
else ; string
{
NumPut("Char",10,ptr,offset) ; type
NumPut("Int64",sz:=StrPut(Obj,ptr+offset+9),ptr,offset+1) ; (str size) string text
offset+=sz+9
}
return offset
}
RawObjectSize(Obj,sz:=0) ; get object's size in dumped condition
{
; #requires AutoHotkey v2.0.19
if isObject(Obj)
{
if (Obj.base=[].base)
{
sz+=9 ; 1 (type) + 8 (num of items)
loop Obj.Length
sz:=RawObjectSize(Obj[a_index],sz)
}
else if (Obj.base={}.base)
{
sz+=9 ; 1 (type) + 8 (num of prop)
for k,v in Obj.OwnProps()
{
sz:=RawObjectSize(k,sz) ; name of prop (str)
sz:=RawObjectSize(v,sz) ; value of prop (any)
}
}
else if (Obj.base=Map().base)
{
sz+=17 ; 1 (type) + 8 (size of Props) + 8 (size of array)
for k,v in Obj.OwnProps()
{
sz:=RawObjectSize(k,sz) ; name of prop (str)
sz:=RawObjectSize(v,sz) ; value of prop (any)
}
for k,v in Obj
{
sz:=RawObjectSize(k,sz) ; index
sz:=RawObjectSize(v,sz) ; value
}
}
else if (Obj.base=Buffer().base) ; sz = 1 (type) + 8 (size) + (buffer size)
sz+=9+Obj.size
else
{
MsgBox "Unsupported object type: `"" Type(obj) "`".","ObjDump",0x30
return 0
}
}
else if IsNumber(obj) ; sz = 1 (type) + (size of data type)
sz+=IsFloat(Obj)||Obj>4294967295?9:Obj>65535?5:Obj>255?3:Obj>-129?2:Obj>-32769?3:Obj>-2147483649?5:9
else ; sz = 1 (type) + 8 (size) + (str size)
sz+=9+StrPut(Obj)
return sz
}