1 (изменено: Alectric, 2025-02-24 16:52:30)

Тема: 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
}


Тема для обсуждения.

Версия для AHK v1.

Win 10 x64
AHK
                       Справка AHK v1 тебе в помощь.