<?xml version="1.0" encoding="utf-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom">
	<channel>
		<title><![CDATA[Серый форум &mdash; AHK: Сохранение массива в строку]]></title>
		<link>https://forum.script-coding.com/viewtopic.php?id=12538</link>
		<atom:link href="https://forum.script-coding.com/extern.php?action=feed&amp;tid=12538&amp;type=rss" rel="self" type="application/rss+xml" />
		<description><![CDATA[Недавние сообщения в теме «AHK: Сохранение массива в строку».]]></description>
		<lastBuildDate>Wed, 08 Mar 2017 14:20:50 +0000</lastBuildDate>
		<generator>PunBB</generator>
		<item>
			<title><![CDATA[AHK: Сохранение массива в строку]]></title>
			<link>https://forum.script-coding.com/viewtopic.php?pid=113730#p113730</link>
			<description><![CDATA[<p>Если требуется сохранить массив, например по завершении работы сохранить в ключ ини файла или текстовый файл, а при старте скрипта восстановить массив, то используя приведённые функции можно перевести массив в строку и обратно.<br />Оригинал <a href="https://autohotkey.com/boards/viewtopic.php?f=6&amp;t=3573">здесь</a>, я посчитал удобным адаптировать его для использования с Base64.</p><p><span class="bbu">ObjToBase64</span> - передаём массив, получаем строку.<br /><span class="bbu">ObjFromBase64</span> - передаём строку, получаем массив.</p><p>Также <a href="http://forum.script-coding.com/viewtopic.php?pid=121219#p121219">есть пример</a> сравнения массивов.</p><p>----------------------------------------------</p><p><a href="http://forum.script-coding.com/viewtopic.php?pid=113687#p113687">Тема для обсуждения.</a></p><p>----------------------------------------------</p><p><strong>Функции:</strong> (правка: 10:37 16.11.2017)</p><div class="codebox"><pre><code>
ObjToBase64(obj) {
	If !IsObject(obj)
		Return
	VarSetCapacity(Bin, Size := RawObjectSize(obj, 0) + 8, 0)
	RawObject(obj, NumPut(Size - 8, 0 + (addr := &amp;Bin), &quot;Int64&quot;), 0)
	DllCall(&quot;Crypt32.dll\CryptBinaryToString&quot;
		, Ptr, addr, UInt, Size, UInt, 0x00000001|0x40000000, UInt, 0, UIntP, TChars, &quot;CDECL Int&quot;)
	VarSetCapacity(Base64, Req := TChars * (A_IsUnicode ? 2 : 1 ))
	DllCall(&quot;Crypt32.dll\CryptBinaryToString&quot;
		, Ptr, addr, UInt, Size, UInt, 0x00000001|0x40000000, Str, Base64, UIntP, Req, &quot;CDECL Int&quot;)
	Return Base64
}

ObjFromBase64(Base64) {
	DllCall(&quot;Crypt32.dll\CryptStringToBinary&quot;, Ptr, &amp;Base64
		, UInt, StrLen(Base64), UInt, 1, UInt, 0, UIntP, Bytes, Int, 0, Int, 0, &quot;CDECL Int&quot;)
	VarSetCapacity(OutData, Req := Bytes * (A_IsUnicode ? 2 : 1))
	DllCall(&quot;Crypt32.dll\CryptStringToBinary&quot;, Ptr, &amp;Base64
		, UInt, StrLen(Base64), UInt, 1, Str, OutData, UIntP, Req, Int, 0, Int, 0, &quot;CDECL Int&quot;)
	Return ObjLoad(&amp;OutData)
}

RawObject(obj, addr, buf := 0, objects := 0) {
	; Type.Enum:    Char.1 UChar.2 Short.3 UShort.4 Int.5 UInt.6 Int64.7 UInt64.8 Double.9 String.10 Object.11
	; Negative for keys and positive for values
	If !objects
		objects:={(&quot;&quot;):0,(obj):0}
	Else
		objects[obj]:=(++objects[&quot;&quot;])
	for k, v in obj
	{ ; 9 = Int64 for size and Char for type
		If IsObject(k) {
			If objects.HasKey(k)
				NumPut(-12,addr+0,&quot;Char&quot;),NumPut(objects[k],addr+1,&quot;Int64&quot;),addr+=9
			Else
				NumPut(-11,addr+0,&quot;Char&quot;),NumPut(sz:=RawObjectSize(k,buf),addr+1,&quot;Int64&quot;),RawObject(k,addr+9,buf,objects),addr+=sz+9
		} Else
			NumPut(-10,addr+0,&quot;Char&quot;),NumPut(sz:=StrPut(k,addr+9)*2,addr+1,&quot;Int64&quot;),addr+=sz+9
		If IsObject(v) {
			If objects.HasKey(v)
				NumPut(12,addr+0,&quot;Char&quot;),NumPut(objects[v],addr+1,&quot;Int64&quot;),addr+=9
			Else
				NumPut(11,addr+0,&quot;Char&quot;),NumPut(sz:=RawObjectSize(v,buf),addr+1,&quot;Int64&quot;),RawObject(v,addr+9,buf,objects),addr+=sz+9
		} Else
			NumPut(10,addr+0,&quot;Char&quot;),NumPut(sz:=buf?obj.GetCapacity(k):StrPut(v)*2,addr+1,&quot;Int64&quot;),DllCall(&quot;RtlMoveMemory&quot;,&quot;PTR&quot;,addr+9,&quot;PTR&quot;,buf?obj.GetAddress(k):&amp;v,&quot;PTR&quot;,sz),addr+=sz+9
	}
}

RawObjectSize(obj,buf:=0,objects:=0){
	If !objects
		objects:={(obj):1}
	Else If !objects.HasKey(obj)
		objects[obj]:=1
	for k, v in obj
	{
		If IsObject(k)
			sz+=objects.HasKey(k)?9:RawObjectSize(k,buf,objects)+9
		Else
			sz+=StrPut(k)*2+9
		If IsObject(v)
			sz+=objects.HasKey(v)?9:RawObjectSize(v,buf,objects)+9
		Else
			sz+=(buf?obj.GetCapacity(k):StrPut(v)*2)+9
	}
	Return sz
}

ObjLoad(addr, objects := 0) {
	obj:=[],end:=addr+8+(sz:=NumGet(addr+0,&quot;Int64&quot;)),addr+=8
	If !objects
		objects:={0:obj}
	Else
		objects.Push(obj)
	While addr &lt; end { ; 9 = Int64 for size and Char for type
		If NumGet(addr+0,&quot;Char&quot;)=-12
			k:=objects[NumGet(addr+1,&quot;Int64&quot;)],addr+=9
		Else If NumGet(addr+0,&quot;Char&quot;)=-11
			k:=ObjLoad(addr+1,objects),addr+=9+NumGet(addr+1,&quot;Int64&quot;)
		Else If NumGet(addr+0,&quot;Char&quot;)=-10
			sz:=NumGet(addr+1,&quot;Int64&quot;),k:=StrGet(addr+9),addr+=sz+9
		Else
			k:=NumGet(addr+1,SubStr(&quot;Char  UChar Short UShortInt   UInt  Int64 UInt64Double&quot;,(sz:=-NumGet(addr+0,&quot;Char&quot;))*6-5,6)),addr+=SubStr(&quot;112244888&quot;,sz,1)+1
		If NumGet(addr+0,&quot;Char&quot;)= 12
			obj[k]:=objects[NumGet(addr+1,&quot;Int64&quot;)],addr+=9
		Else If NumGet(addr+0,&quot;Char&quot;)= 11
			obj[k]:=ObjLoad(addr+1,objects),addr+=9+NumGet(addr+1,&quot;Int64&quot;)
		Else If NumGet(addr+0,&quot;Char&quot;)= 10 {
			If (k + 0 != &quot;&quot;) &amp;&amp; !(k ~=&quot;S)\s&quot;) &amp;&amp; (abs(k) &lt;= 2147483647)
				obj[k]:=StrGet(addr+9),obj.SetCapacity(k,sz:=NumGet(addr+1,&quot;Int64&quot;)),DllCall(&quot;RtlMoveMemory&quot;,&quot;PTR&quot;,obj.GetAddress(k),&quot;PTR&quot;,addr+9,&quot;PTR&quot;,sz),addr+=sz+9
			Else
				obj[&quot;&quot; k]:=StrGet(addr+9),obj.SetCapacity(&quot;&quot; k,sz:=NumGet(addr+1,&quot;Int64&quot;)),DllCall(&quot;RtlMoveMemory&quot;,&quot;PTR&quot;,obj.GetAddress(&quot;&quot; k),&quot;PTR&quot;,addr+9,&quot;PTR&quot;,sz),addr+=sz+9
		} Else
			obj[k]:=NumGet(addr+1,SubStr(&quot;Char  UChar Short UShortInt   UInt  Int64 UInt64Double&quot;,(sz:=NumGet(addr+0,&quot;Char&quot;))*6-5,6)),addr+=SubStr(&quot;112244888&quot;,sz,1)+1
	}
	Return obj
}
</code></pre></div><div class="fancy_spoiler_switcher"><div class="fancy_spoiler_switcher_header"><strong>+</strong>&nbsp;Пример:</div><div class="fancy_spoiler"><div class="codebox"><pre><code>
#SingleInstance Force
#NoEnv

Arr := {&quot;1key&quot;:{2key:[,,&quot;value&quot;]}}
Base64 := ObjToBase64(Arr)
MsgBox % Base64

Obj := ObjFromBase64(Base64)
MsgBox % Obj.1key.2key[3]

Prefix := {&quot;LAlt&quot;:&quot;&lt;!&quot;,&quot;LCtrl&quot;:&quot;&lt;^&quot;,&quot;LShift&quot;:&quot;&lt;+&quot;,&quot;LWin&quot;:&quot;&lt;#&quot;}
Base64 := ObjToBase64(Prefix)
MsgBox % Base64

Obj := ObjFromBase64(Base64)
for k, v in Obj
	MsgBox % k &quot; : &quot; v

B := [&quot;Ivan&quot;, 345, &quot;London&quot;]
Base64 := ObjToBase64(B)
MsgBox % Base64

Obj := ObjFromBase64(Base64)
for k, v in Obj
	MsgBox % k &quot; : &quot; v
</code></pre></div></div></div><div class="fancy_spoiler_switcher"><div class="fancy_spoiler_switcher_header"><strong>+</strong>&nbsp;Пример, сохраняем экземпляр класса, загружаем. Конечно в каждой реализации своего класса могут быть свои нюансы:</div><div class="fancy_spoiler"><div class="codebox"><pre><code>
#SingleInstance Force
#NoEnv

MyClass := new Class

Loop 9
{
	MyClass[&quot;v&quot; A_Index] := A_Sec &quot; . &quot; A_Msec
	Sleep 10
}
MyClass.a := {b:{c:&quot;вложенный массив&quot;}}

Base64 := ObjToBase64(MyClass)
MsgBox % Base64

NewObj := new Class
NewObj.Load(ObjFromBase64(Base64))

for k, v in NewObj, list := &quot;&quot;
	list .= k &quot; : &quot; (IsObject(v) ? &quot;IsObject&quot; : v) &quot;`n&quot; 
MsgBox % list

NewObj.Test()
Return

class Class {
	x := 10, y := 20
	Load(Obj) { 
		for k, v in Obj
			This[k] := v
	}
	Test() {
		MsgBox % this.a.b.c
	}
} 
</code></pre></div></div></div><div class="fancy_spoiler_switcher"><div class="fancy_spoiler_switcher_header"><strong>+</strong>&nbsp;Пример выше, отдельно, загрузка экземпляра из сохранённой строки:</div><div class="fancy_spoiler"><div class="codebox"><pre><code>
#SingleInstance Force
#NoEnv

Base64 = /AEAAAAAAAD2BAAAAAAAAABhAAAAC04AAAAAAAAA9gQAAAAAAAAAYgAAAAs4AAAAAAAAAPYEAAAAAAAAAGMAAAAKIgAAAAAAAAAyBDsEPgQ2BDUEPQQ9BEsEOQQgADwEMARBBEEEOAQyBAAA9gYAAAAAAAAAdgAxAAAAChIAAAAAAAAAMAA3ACAALgAgADMAOAAwAAAA9gYAAAAAAAAAdgAyAAAAChIAAAAAAAAAMAA3ACAALgAgADMAOQA1AAAA9gYAAAAAAAAAdgAzAAAAChIAAAAAAAAAMAA3ACAALgAgADQAMAA1AAAA9gYAAAAAAAAAdgA0AAAAChIAAAAAAAAAMAA3ACAALgAgADQAMgA1AAAA9gYAAAAAAAAAdgA1AAAAChIAAAAAAAAAMAA3ACAALgAgADQANAA1AAAA9gYAAAAAAAAAdgA2AAAAChIAAAAAAAAAMAA3ACAALgAgADQANQA0AAAA9gYAAAAAAAAAdgA3AAAAChIAAAAAAAAAMAA3ACAALgAgADQANwAyAAAA9gYAAAAAAAAAdgA4AAAAChIAAAAAAAAAMAA3ACAALgAgADQAOAA0AAAA9gYAAAAAAAAAdgA5AAAAChIAAAAAAAAAMAA3ACAALgAgADUAMAA0AAAA9gQAAAAAAAAAeAAAAAIK9gQAAAAAAAAAeQAAAAIU

NewObj := new Class
NewObj.Load(ObjFromBase64(Base64))
NewObj.Test()

for k, v in NewObj, list := &quot;&quot;
	list .= k &quot; : &quot; (IsObject(v) ? &quot;IsObject&quot; : v) &quot;`n&quot; 
MsgBox % list
Return

class Class { 
	Load(Obj) { 
		for k, v in Obj
			This[k] := v
	}
	Test() {
		MsgBox % this.a.b.c
	}
} 
</code></pre></div></div></div>]]></description>
			<author><![CDATA[null@example.com (serzh82saratov)]]></author>
			<pubDate>Wed, 08 Mar 2017 14:20:50 +0000</pubDate>
			<guid>https://forum.script-coding.com/viewtopic.php?pid=113730#p113730</guid>
		</item>
	</channel>
</rss>
