YAML(全称:YAML Ain't Markup Language)是一种人类可读的数据序列化格式。它常用来写配置文件、数据交换或者作为存储格式。YAML的设计目标是简洁、易读,且容易与其他编程语言和数据格式(比如JSON、XML)互操作。
YAML 的主要特点包括:
- 简洁和易读:相比JSON,YAML更加直观和简洁。比如,YAML使用缩进来表示层级关系,而JSON使用大括号和方括号。
- 支持多种数据类型:包括标量(字符串、整数、浮点数等)、列表、字典(键值对)、日期等。
- 支持复杂结构:可以用来表示复杂的数据结构,如多层嵌套的对象和数组。
- 注释支持:YAML文件可以包含注释,注释以
#
开头,帮助解释配置项的用途。
出处:https://github.com/HotKeyIt/Yaml/blob/master/Yaml.ahk
Yaml.ahk
Yaml(YamlText,IsFile=1,YamlObj=0){ ; Version 1.0.0.17 http://www.autohotkey.com/forum/viewtopic.php?t=70559
static
static base:={Dump:"Yaml_Dump",Save:"Yaml_Save",Add:"Yaml_Add",Merge:"Yaml_Merge",__Delete:"__Delete",_Insert:"_Insert",_Remove:"_Remove",_GetCapacity:"_GetCapacity",_SetCapacity:"_SetCapacity",_GetAddress:"_GetAddress",_MaxIndex:"_MaxIndex",_MinIndex:"_MinIndex",_NewEnum:"_NewEnum",_HasKey:"_HasKey",_Clone:"_Clone",Insert:"Insert",Remove:"Remove",GetCapacity:"GetCapacity",SetCapacity:"SetCapacity",GetAddress:"GetAddress",MaxIndex:"MaxIndex",MinIndex:"MinIndex",NewEnum:"NewEnum",HasKey:"HasKey",Clone:"Clone",base:{__Call:"Yaml_Call"}}
static BackupVars:="LVL,SEQ,KEY,SCA,TYP,VAL,CMT,LFL,CNT",IncompleteSeqMap
local maxLVL:=0,LastContObj:=0,LastContKEY:=0,LinesAdded:=0,_LVLChanged:=0,_LVL,_SEQ,_KEY,_SCA,_TYP,_VAL,_CMT,_LFL,_CNT,_NXT,__LVL,__SEQ,__KEY,__SCA,__TYP,__VAL,__CMT,__LFL,__CNT,__NXT
AutoTrim % ((AutoTrim:=A_AutoTrim)="On")?"Off":"Off"
LVL0:=pYaml:=YamlObj?YamlObj:Object("base",base),__LVL:=0,__LVL0:=0
If IsFile
FileRead,YamlText,%YamlText%
Loop,Parse,YamlText,`n,`r
{
If (!_CNT && (A_LoopField=""||RegExMatch(A_LoopField,"^\s+$"))){ ;&&__KEY=""&&__SEQ="")){
If ((OBJ:=LVL%__LVL%[""].MaxIndex())&&IsObject(LVL%__LVL%["",OBJ])&&__SEQ){
If (__KEY!="")
Yaml_Continue(LastContObj:=LVL%__LVL%["",Obj],LastContKEY:=__key,"",__SCA)
else Yaml_Continue(LastContObj:=LVL%__LVL%[""],LastContKEY:=Obj,"",__SCA,__SEQ)
} else If (__SEQ && OBJ){
Yaml_Continue(LastContObj:=LVL%__LVL%[""],LastContKEY:=OBJ,"",__SCA,__SEQ)
} else If (OBJ){
Yaml_Continue(LastContObj:=LVL%__LVL%[""],LastContKEY:=OBJ,"",__SCA,1)
} else if (__KEY!="")
Yaml_Continue(LastContObj:=LVL%__LVL%,LastContKEY:=__KEY,"",__SCA)
else LinesAdded--
LinesAdded++
Continue
} else If (!_CNT && LastContObj
&& ( RegExMatch(A_LoopField,"^(---)?\s*?(-\s)?("".+""\s*:\s|'.+'\s*:\s|[^:""'\{\[]+\s*:\s)")
|| RegExMatch(A_LoopField,"^(---)|\s*(-\s)") )){
If !__SCA
LastContObj[LastContKEY]:=SubStr(LastContObj[LastContKEY],1,-1*LinesAdded)
LastContObj:=0,LastContKEY:=0,LinesAdded:=0
}
If InStr(A_LoopField,"#"){
If (RegexMatch(A_LoopField,"^\s*#.*") || InStr(A_LoopField,"%YAML")=1) ;Comments only, do not parse
continue
else if Yaml_IsQuoted(LTrim(A_LoopField,"- ")) || RegExMatch(A_LoopField,"(---)?\s*?(-\s)?("".+""\s*:\s|'.+'\s*:\s|[^:""'\{\[]+\s*:\s)\s*([\|\>][+-]?)?\s*(!!\w+\s)?\s*("".+|'.+)$")&&!RegExMatch(A_LoopField,"[^\\]""\s+#")
LoopField:=A_LoopField
else if RegExMatch(A_LoopField,"\s+#.*$","",RegExMatch(A_LoopField,"(---)?\s*?(-\s)?("".+""\s*:\s|'.+'\s*:\s|[^:""'\{\[]+\s*:\s)?\s*([\|\>][+-]?)?\s*(!!\w+\s)?\s*("".+""|'.+')?\K")-1)
LoopField:=SubStr(A_LoopField,1,RegExMatch(A_LoopField,"\s+#.*$","",RegExMatch(A_LoopField,"(---)?\s*?(-\s)?("".+""\s*:\s|'.+'\s*:\s|[^:""'\{\[]+\s*:\s)?\s*([\|\>][+-]?)?\s*(!!\w+\s)?\s*("".+""|'.+')?\K")-1)-1)
else LoopField:=A_LoopField
} else LoopField:=A_LoopField
If _CNT {
If Yaml_IsSeqMap(RegExReplace(IncompleteSeqMap LoopField,"^(\s+)?(-\s)?("".+""\s*:\s|'.+'\s*:\s|[^:""'\{\[]+\s*:\s)?"))
LoopField:=IncompleteSeqMap LoopField,_CNT:=0,IncompleteSeqMap:=""
else {
IncompleteSeqMap.=LoopField
continue
}
}
If (LoopField="---"){
Loop % (maxLVL)
LVL%A_Index%:=""
Loop,Parse,BackupVars,`,
__%A_LoopField%:="",__%A_LoopField%0:=""
Loop,Parse,BackupVars,`,
Loop % maxLVL
__%A_LoopField%%A_Index%:=""
maxLVL:=0
__LVL:=0,__LVL0:=0
If !IsObject(pYaml[""])
pYaml[""]:=LVL0:=Object("base",base)
pYaml[""].Insert(LVL0:=Object("base",base))
Continue
} else if (LoopField="..."){
LVL0:=pYaml
Loop % maxLVL
LVL%A_Index%:=""
Loop,Parse,BackupVars,`,
__%A_LoopField%:="",__%A_LoopField%0:=""
Loop,Parse,BackupVars,`,
Loop % maxLVL
__%A_LoopField%%A_Index%:=""
maxLVL:=0
__LVL:=0,__LVL0:=0
Continue
}
If (SubStr(LoopField,0)=":")
LoopField.=A_Space ; add space to force RegEx to match even if the value and space after collon is missing e.g. Object:`n objects item
RegExMatch(LoopField,"S)^(?<LVL>\s+)?(?<SEQ>-\s)?(?<KEY>"".+""\s*:\s|'.+'\s*:\s|[^:""'\{\[]+\s*:\s)?\s*(?<SCA>[\|\>][+-]?)?\s*(?<TYP>!!\w+\s)?\s*(?<VAL>"".+""|'.+'|.+)?\s*$",_)
If _KEY ;cut off (:)
StringTrimRight,_KEY,_KEY,2
_KEY:=Yaml_UnQuoteIfNeed(_KEY)
If IsVal:=Yaml_IsQuoted(_VAL)
_VAL:=Yaml_UnQuoteIfNeed(_VAL)
;determine current level
_LVL:=Yaml_S2I(_LVL)
If _LVL-__LVL>1||(_LVL>__LVL&&_LVLChanged) ;&&!(__SEQ&&__KEY!=""&&_KEY!="")) ; (__SEQ?2:1)
{
Loop % (_LVLChanged?_LVL-_LVLChanged:_LVL-__LVL-1)
LoopField:=SubStr(LoopField,SubStr(LoopField,1,1)=A_Tab?1:2)
_LVL:=_LVLChanged?_LVLChanged:__LVL+1,_LVLChanged:=_LVLChanged?_LVLChanged:_LVL ;__LVL%_LVL%:=__LVL%_NXT% ; (__SEQ?2:1)
} else if _LVLChanged
_LVL:=_LVLChanged
else _LVLChanged:=0
If (maxLVL<_LVL)
maxLVL:=_LVL+(_SEQ?1:0)
; Cut off the leading tabs/spaces conform _LVL
SubStr:=0,Tabs:=0
Loop,Parse,LoopField
If (_LVL*2=SubStr || !SubStr:=SubStr+(A_LoopField=A_Tab?2:1)), Tabs:=Tabs+(A_LoopField=A_Tab?1:0)
break
_LFL:=SubStr(LoopField,SubStr-Tabs+1+(_SEQ?2:0))
_LFL:=Yaml_UnQuoteIfNeed(_LFL)
_NXT:=_LVL+1 ;next indentation level
__NXT:=_NXT+1
_PRV:=_LVL=0?0:_LVL-1
Loop,Parse,BackupVars,`,
__%A_LoopField%:=__%A_LoopField%%_PRV%
If RegExMatch(_LFL,"^-\s*$"){
_SEQ:="-",_KEY:="",_VAL:=""
}
If (!IsVal && !_CNT && (_CNT:=Yaml_Incomplete(Trim(_LFL))||Yaml_Incomplete(Trim(_VAL)))){
IncompleteSeqMap:=LoopField
continue
}
If (_LVL<__LVL){ ;Reset Objects and Backup vars
Loop % (maxLVL)
If (A_Index>_LVL){
Loop,Parse,BackupVars,`,
__%A_LoopField%%maxLVL%:=""
LVL%A_Index%:="",maxLVL:=maxLVL-1
}
If (_LVL=0 && !__LVL:=__LVL0:=0)
Loop,Parse,BackupVars,`,
__%A_LoopField%:="",__%A_LoopField%0:=""
}
If (_SEQ&&_LVL>__LVL&&(__VAL!=""||__SCA))
_SEQ:="",_KEY:="",_VAL:="",_LFL:="- " _LFL
If (__CNT)||(_LVL>__LVL&&(__KEY!=""&&_KEY="")&&(__VAL!=""||__SCA))||(__SEQ&&__SCA)
_KEY:="",_VAL:=""
If (__CNT||(_LVL>__LVL&&(__KEY!=""||(__SEQ&&(__LFL||__SCA)&&!Yaml_IsSeqMap(__LFL)))&&!(_SEQ||_KEY!=""))){
If ((OBJ:=LVL%__LVL%[""].MaxIndex())&&IsObject(LVL%__LVL%["",OBJ])&&__SEQ){
If __KEY!=
Yaml_Continue(LVL%__LVL%["",Obj],__key,_LFL,__SCA),__CNT:=Yaml_SeqMap(LVL%__LVL%["",OBJ],__KEY,LVL%__LVL%["",OBJ,__KEY])?"":__CNT
else Yaml_Continue(LVL%__LVL%[""],Obj,_LFL,__SCA,__SEQ),__CNT:=Yaml_SeqMap(LVL%__LVL%[""],OBJ,LVL%__LVL%["",OBJ],__SEQ)?"":__CNT
} else If (__SEQ && OBJ){
Yaml_Continue(LVL%__LVL%[""],Obj,_LFL,__SCA,__SEQ)
__CNT:=Yaml_SeqMap(LVL%__LVL%[""],OBJ,LVL%__LVL%["",OBJ],__SEQ)?"":__CNT
} else If (OBJ && __KEY=""){
Yaml_Continue(LVL%__LVL%[""],OBJ,_LFL,__SCA,1)
__CNT:=Yaml_SeqMap(LVL%__LVL%[""],OBJ,LVL%__LVL%["",OBJ],1)?"":__CNT
} else {
Yaml_Continue(LVL%__LVL%,__KEY,_LFL,__SCA)
__CNT:=Yaml_SeqMap(LVL%__LVL%,__KEY,LVL%__LVL%[__KEY])?"":__CNT
}
Continue
}
;Create sequence or map
If (__SEQ&&(_LVL>__LVL)&&_KEY!=""&&__KEY!=""){
OBJ:=LVL%__LVL%[""].MaxIndex()
If _SEQ {
If !Yaml_SeqMap(LVL%_LVL%["",OBJ,__KEY,""],_KEY,_VAL){
If !IsObject(LVL%__LVL%["",OBJ,__KEY,""])
LVL%__LVL%["",OBJ,__KEY,""]:={base:base}
LVL%__LVL%["",OBJ,__KEY,""].Insert({(_KEY):_VAL!=""?_VAL:(LVL%_NXT%:={base:base}),base:base})
}
} else If !Yaml_SeqMap(LVL%_LVL%["",OBJ],_KEY,_VAL){
LVL%__LVL%["",OBJ,_KEY]:=_VAL!=""?_VAL:(LVL%_NXT%:={base:base})
}
If _VAL!=
continue
} else If (_SEQ){
If !IsObject(LVL%_LVL%[""])
LVL%_LVL%[""]:=Object("base",base)
While (SubStr(_LFL,1,2)="- "){
_LFL:=SubStr(_LFL,3),_KEY:=(_KEY!="")?_LFL:=SubStr(_KEY,3):_KEY,LVL%_LVL%[""].Insert(LVL%_NXT%:=Object("",Object("base",base),"base",base)),_LVL:=_LVL+1,_NXT:=_NXT+1,__NXT:=_NXT+1,_PRV:=_LVL-1,maxLVL:=(maxLVL<_LVL)?_LVL:maxLVL
Loop,Parse,BackupVars,`,
__%A_LoopField%:=_%A_LoopField%
,__%A_LoopField%%_PRV%:=_%A_LoopField%
}
If (_KEY="" && _VAL="" && !IsVal){
If !Yaml_SeqMap(LVL%_LVL%[""],"",_LFL)
LVL%_LVL%[""].Insert(LVL%_NXT%:=Object("base",base))
} else If (_KEY!="") {
LVL%_LVL%[""].Insert(LVL%__NXT%:=Object(_KEY,LVL%_NXT%:=Object("base",base),"base",base))
If !Yaml_SeqMap(LVL%__NXT%,_KEY,_VAL){
LVL%_LVL%[""].Remove()
LVL%_LVL%[""].Insert(LVL%__NXT%:=Object(_KEY,(_VAL!=""||IsVal)?_VAL:LVL%_NXT%:=Object("base",base),"base",base))
}
} else {
If !Yaml_SeqMap(LVL%_LVL%[""],"",_LFL)
LVL%_LVL%[""].Insert(_LFL)
}
If !LVL%_LVL%[""].MaxIndex()
LVL%_LVL%.Remove("")
} else if (_KEY!=""){
If (__SEQ && _LVL>__LVL) {
If (OBJ:=LVL%_PRV%[""].MaxIndex())&&IsObject(LVL%_PRV%["",OBJ]){
If !Yaml_SeqMap(LVL%_PRV%["",OBJ],_KEY,_VAL)
LVL%_PRV%["",OBJ,_KEY]:=(_VAL!=""||IsVal)?_VAL:(LVL%_NXT%:=Object("base",base))
} else {
LVL%_PRV%[""].Insert(Object(_KEY,(_VAL!=""||IsVal)?_VAL:(LVL%_NXT%:=Object("base",base)),"base",base))
Yaml_SeqMap(LVL%_PRV%["",OBJ?OBJ+1:1],_KEY,_VAL)
}
} else
If !Yaml_SeqMap(LVL%_LVL%,_KEY,_VAL)
LVL%_LVL%[_KEY]:=_VAL!=""?_VAL:(LVL%_NXT%:=Object("base",base))
} else if (_LVL>__LVL && (__KEY!="")) {
If (__VAL!="" || __SCA){
Yaml_Continue(LVL%__LVL%,__KEY,_LFL,__SCA)
Yaml_SeqMap(LVL%__LVL%,__KEY,LVL%__LVL%[__KEY])
Continue
} else {
If !Yaml_SeqMap(LVL%__LVL%[__KEY],_KEY,_VAL) ;!!! no Scalar???
LVL%__LVL%[__KEY,_KEY]:=_VAL
Continue
}
} else {
If (_LVL>__LVL&&(OBJ:=LVL%__LVL%[""].MaxIndex())&&IsObject(LVL%__LVL%["",OBJ])&&__SEQ){
If __CNT
Yaml_Continue(LVL%__LVL%[""],LVL%__LVL%[""].MaxIndex(),_LFL,__SCA,1)
If (__CNT:=Yaml_SeqMap(LVL%__LVL%[""],"",_LFL)?"":1)
LVL%__LVL%[""].Insert(_LFL)
} else {
If !IsObject(LVL%_LVL%[""])
LVL%_LVL%[""]:=Object("base",base)
If __CNT
Yaml_Continue(LVL%__LVL%[""],LVL%__LVL%[""].MaxIndex(),_LFL,__SCA,1)
If (__CNT:=Yaml_SeqMap(LVL%_LVL%[""],"",_LFL)?"":1)
LVL%_LVL%[""].Insert(_LFL)
}
Continue
}
Loop,Parse,BackupVars,`,
__%A_LoopField%:=_%A_LoopField%
,__%A_LoopField%%_LVL%:=_%A_LoopField%
}
If (LastContObj && !__SCA)
LastContObj[LastContKEY]:=SubStr(LastContObj[LastContKEY],1,-1*LinesAdded)
AutoTrim %AutoTrim%
Loop,Parse,BackupVars,`,
If !(__%A_LoopField%:="")
Loop % maxLVL
__%A_LoopField%%A_Index%:=""
Return pYaml,pYaml.base:=base
}
Yaml_Save(obj,file,level=""){
FileMove,% file,% file ".bakupyml",1
FileAppend,% obj.Dump(),% file
If !ErrorLevel
FileDelete,% file ".bakupyml"
else {
FileMove,% file ".bakupyml",% file
MsgBox,0, Error creating file, old file was restored.
}
}
Yaml_Call(NotSupported,f,p*){
If (p.MaxIndex()>1){
Loop % p.MaxIndex()
If A_Index>1
f:=f[""][p[A_Index-1]]
}
Return (!p.MaxIndex()?f[""].MaxIndex():f[""][p[p.MaxIndex()]])
}
Yaml_Merge(obj,merge){
for k,v in merge
{
If IsObject(v){
If obj.HasKey(k){
If IsObject(obj[k])
Yaml_Merge(obj[k],v)
else obj[k]:=v
} else obj[k]:=v
} else obj[k]:=v
}
}
Yaml_Add(O,Yaml="",IsFile=0){
static base:={Dump:"Yaml_Dump",Save:"Yaml_Save",Add:"Yaml_Add",Merge:"Yaml_Merge",__Delete:"__Delete",_Insert:"_Insert",_Remove:"_Remove",_GetCapacity:"_GetCapacity",_SetCapacity:"_SetCapacity",_GetAddress:"_GetAddress",_MaxIndex:"_MaxIndex",_MinIndex:"_MinIndex",_NewEnum:"_NewEnum",_HasKey:"_HasKey",_Clone:"_Clone",Insert:"Insert",Remove:"Remove",GetCapacity:"GetCapacity",SetCapacity:"SetCapacity",GetAddress:"GetAddress",MaxIndex:"MaxIndex",MinIndex:"MinIndex",NewEnum:"NewEnum",HasKey:"HasKey",Clone:"Clone",base:{__Call:"Yaml_Call"}}
If Yaml_IsSeqMap(Trim(Yaml)){
If !IsObject(O[""])
O[""]:=Object("base",base)
Yaml_SeqMap(O[""],"",Yaml)
} else Yaml(Yaml,IsFile,O)
}
Yaml_Dump(O,J="",R=0,Q=0){
static M1:="{",M2:="}",S1:="[",S2:="]",N:="`n",C:=", ",S:="- ",E:="",K:=": "
local dump:="",M,MX,F,I,key,value
If (J=0&&!R)
dump.= S1
for key in O
M:=A_Index
If IsObject(O[""]){
M--
for key in O[""]
MX:=A_Index
If IsObject(O[""][""])
MX--
If O[""].MaxIndex()
for key, value in O[""]
{
If key=
continue
I++
F:=IsObject(value)?(IsObject(value[""])?"S":"M"):E
If (J!=""&&J<=R){
dump.=(F?(%F%1 Yaml_Dump(value,J,R+1,F) %F%2):Yaml_EscIfNeed(value)) (I=MX&&!M?E:C) ;(Q="S"&&I=1?S1:E)(Q="S"&&I=MX?S2:E)
} else if F,dump:=dump N Yaml_I2S(R) S
dump.= (J!=""&&J<=(R+1)?%F%1:E) Yaml_Dump(value,J,R+1,F) (J!=""&&J<=(R+1)?%F%2:E)
else {
; If RegexMatch(value,"[\x{007F}-\x{FFFF}""\{\[']|:\s|\s#")
dump .= Yaml_EscIfNeed(value)
; else {
; value:= (value=""?"''":RegExReplace(RegExReplace(Value,"m)^(.*[\r\n].*)$","|" (SubStr(value,-1)="`n`n"?"+":SubStr(value,0)=N?"":"-") "`n$1"),"ms)(*ANYCRLF)\R",N Yaml_I2S(R+1)))
; StringReplace,value,value,% N Yaml_I2S(R+1) N Yaml_I2S(R+1),% N Yaml_I2S(R+1),A
; dump.=value
; }
}
}
}
I=0
for key, value in O
{
If key=
continue
I++
F:=IsObject(value)?(IsObject(value[""])?"S":"M"):E
If (J=0&&!R)
dump.= M1
If (J!=""&&J<=R){
dump.=(Q="S"&&I=1?M1:E) Yaml_EscIfNeed(key) K
dump.=F?(%F%1 Yaml_Dump(value,J,R+1,F) %F%2):Yaml_EscIfNeed(value)
dump.=(Q="S"&&I=M?M2:E) (J!=0||R?(I=M?E:C):E)
} else if F,dump:=dump N Yaml_I2S(R) Yaml_EscIfNeed(key) K
dump.= (J!=""&&J<=(R+1)?%F%1:E) Yaml_Dump(value,J,R+1,F) (J!=""&&J<=(R+1)?%F%2:E)
else {
; If RegexMatch(value,"[\x{007F}-\x{FFFF}""\{\['\t]|:\s|\s#")
dump .= Yaml_EscIfNeed(value)
; else {
; value:= (value=""?"''":RegExReplace(RegExReplace(Value,"m)^(.*[\r\n].*)$","|" (SubStr(value,-1)="`n`n"?"+":SubStr(value,0)="`n"?"":"-") "`n$1"),"ms)(*ANYCRLF)\R","`n" Yaml_I2S(R+1)))
; StringReplace,value,value,% "`n" Yaml_I2S(R+1) "`n" Yaml_I2S(R+1),% "`n" Yaml_I2S(R+1),A
; dump.= value
; }
}
If (J=0&&!R){
dump.=M2 (I<M?C:E)
}
}
If (J=0&&!R)
dump.=S2
If (R=0)
dump:=RegExReplace(dump,"^\R+")
Return dump
}
Yaml_UniChar( string ) {
static a:="`a",b:="`b",t:="`t",n:="`n",v:="`v",f:="`f",r:="`r",e:=Chr(0x1B)
Loop,Parse,string,\
{
If (A_Index=1){
var.=A_LoopField
continue
} else If lastempty {
var.="\" A_LoopField
lastempty:=0
Continue
} else if (A_LoopField=""){
lastempty:=1
Continue
}
If InStr("ux",SubStr(A_LoopField,1,1))
str:=SubStr(A_LoopField,1,RegExMatch(A_LoopField,"^[ux]?([\dA-F]{4})?([\dA-F]{2})?\K")-1)
else
str:=SubStr(A_LoopField,1,1)
If (str=="N")
str:="\x85"
else if (str=="P")
str:="\x2029"
else if (str=0)
str:="\x0"
else if (str=="L")
str:="\x2028"
else if (str=="_")
str:="\xA0"
If RegexMatch(str,"i)^[ux][\da-f]+$")
var.=Chr(Abs("0x" SubStr(str,2)))
else If str in a,b,t,n,v,f,r,e
var.=%str%
else var.=str
If InStr("ux",SubStr(A_LoopField,1,1))
var.=SubStr(A_LoopField,RegExMatch(A_LoopField,"^[ux]?([\dA-F]{4})?([\dA-F]{2})?\K"))
else var.=SubStr(A_LoopField,2)
}
return var
}
Yaml_CharUni( string ) {
static ascii:={"\":"\","`a": "a","`b": "b","`t": "t","`n": "n","`v": "v","`f": "f","`r": "r",Chr(0x1B): "e","""": """",Chr(0x85): "N",Chr(0x2029): "P",Chr(0x2028): "L","": "0",Chr(0xA0): "_"}
If !RegexMatch(string,"[\x{007F}-\x{FFFF}]"){
Loop,Parse,string
{
If ascii[A_LoopField]
var.="\" ascii[A_LoopField]
else
var.=A_LoopField
}
return var
}
format:=A_FormatInteger
SetFormat,Integer,H
Loop,Parse,string
{
If ascii[A_LoopField]
var.="\" ascii[A_LoopField]
else if Asc(A_LoopField)<128
var.=A_LoopField
else {
str:=SubStr(Asc(A_LoopField),3)
var.="\u" (StrLen(str)<2?"000":StrLen(str)<3?"00":StrLen(str)<4?"0":"") str
}
}
SetFormat,Integer,%Format%
return var
}
Yaml_EscIfNeed(s){
If (s="")
return "''"
else If RegExMatch(s,"m)[\{\[""'\r\n]|:\s|,\s|\s#")||RegExMatch(s,"^[\s#\\\-:>]")||RegExMatch(s,"m)\s$")||RegExMatch(s,"m)[\x{7F}-\x{7FFFFFFF}]")
return ("""" . Yaml_CharUni(s) . """")
else return s
}
Yaml_IsQuoted(ByRef s){
return InStr(".''."""".","." SubStr(Trim(s),1,1) SubStr(Trim(s),0) ".")?1:0
}
Yaml_UnQuoteIfNeed(s){
s:=Trim(s)
If !(SubStr(s,1,1)=""""&&SubStr(s,0)="""")
return (SubStr(s,1,1)="'"&&SubStr(s,0)="'")?SubStr(s,2,StrLen(s)-2):s
else return Yaml_UniChar(SubStr(s,2,StrLen(s)-2))
}
Yaml_S2I(str){
local idx:=0
Loop,Parse,str
If (A_LoopField=A_Tab)
idx++
else if !Mod(A_index,2)
idx++
Return idx
}
Yaml_I2S(idx){
Loop % idx
str .= " "
Return str
}
Yaml_Continue(Obj,key,value,scalar="",isval=0){
If !IsObject(isObj:=obj[key])
v:=isObj
If scalar {
StringTrimLeft,scaopt,scalar,1
scalar:=Asc(scalar)=124?"`n":" "
} else scalar:=" ",scaopt:="-"
temp := (value=""?"`n":(SubStr(v,0)="`n"&&scalar="`n"?"":(v=""?"":scalar))) value (scaopt!="-"?(v&&value=""?"`n":""):"")
obj[key]:=Yaml_UnQuoteIfNeed(v temp)
}
Yaml_Quote(ByRef L,F,Q,B,ByRef E){
Return (F="\"&&!E&&(E:=1))||(E&&!(E:=0)&&(L:=L ("\" F)))
}
Yaml_SeqMap(o,k,v,isVal=0){
v:=Trim(v,A_Tab A_Space "`n"),m:=SubStr(v,1,1) SubStr(v,0)
If Yaml_IsSeqMap(v)
return m="[]"?Yaml_Seq(o,k,SubStr(v,2,StrLen(v)-2),isVal):m="{}"?Yaml_Map(o,k,SubStr(v,2,StrLen(v)-2),isVal):0
}
Yaml_Seq(obj,key,value,isVal=0){
static base:={Dump:"Yaml_Dump",Save:"Yaml_Save",Add:"Yaml_Add",Merge:"Yaml_Merge",__Delete:"__Delete",_Insert:"_Insert",_Remove:"_Remove",_GetCapacity:"_GetCapacity",_SetCapacity:"_SetCapacity",_GetAddress:"_GetAddress",_MaxIndex:"_MaxIndex",_MinIndex:"_MinIndex",_NewEnum:"_NewEnum",_HasKey:"_HasKey",_Clone:"_Clone",Insert:"Insert",Remove:"Remove",GetCapacity:"GetCapacity",SetCapacity:"SetCapacity",GetAddress:"GetAddress",MaxIndex:"MaxIndex",MinIndex:"MinIndex",NewEnum:"NewEnum",HasKey:"HasKey",Clone:"Clone",base:{__Call:"Yaml_Call"}}
ContinueNext:=0
If (obj=""){
If (SubStr(value,0)!="]")
Return 0
else
value:=SubStr(value,2,StrLen(value)-2)
} else {
If (key=""){
obj.Insert(Object("",cObj:=Object("base",base),"base",base))
} else if (isval && IsObject(obj[key,""])){
cObj:=obj[key,""]
} else obj[key]:=Object("",cObj:=Object("base",base),"base",base)
}
Count:=StrLen(value)
Loop,Parse,value
{
If ((Quote=""""&&Yaml_Quote(LF,A_LoopField,Quote,Bracket,Escape)) || (ContinueNext && !ContinueNext:=0))
Continue
If (Quote){
If (A_LoopField=Quote){
Quote=
If Bracket
LF.= A_LoopField
else LF:=SubStr(LF,2)
Continue
}
LF .= A_LoopField
continue
} else if (!Quote&&InStr("""'",A_LoopField)){
Quote:=A_LoopField
If !Bracket
VQ:=Quote
LF.=A_LoopField
Continue
} else if (!Quote&&Bracket){
If (Asc(A_LoopField)=Asc(Bracket)+2)
BCount--
else if (A_LoopField=Bracket)
BCount++
If (BCount=0)
Bracket=
LF .= A_LoopField
Continue
} else if (!Quote&&!Bracket&&InStr("[{",A_LoopField)){
Bracket:=A_LoopField
BCount:=1
LF.=A_LoopField
Continue
}
If (A_Index=Count)
LF .= A_LoopField
else if (!Quote&&!Bracket&&A_LoopField=","&&(!InStr("0123456789",SubStr(value,A_Index-1,1)) | !InStr("0123456789",SubStr(value,A_Index+1,1)))){
ContinueNext:=SubStr(value,A_Index+1,1)=A_Space||SubStr(value,A_Index+1,1)=A_Tab
LF:=LF
} else {
LF .= A_LoopField
continue
}
If (obj=""){
If !VQ
If (Asc(LF)=91 && !Yaml_Seq("","",LF))
||(Asc(LF)=123 && !Yaml_Map("","",LF))
Return 0
} else {
If (VQ || !Yaml_SeqMap(cObj,"",LF))
cObj.Insert(VQ?Yaml_UniChar(LF):Trim(LF))
}
LF:="",VQ:=""
}
If (LF){
If (obj=""){
If !VQ
If (Asc(LF)=91 && !Yaml_Seq("","",LF))||(Asc(LF)=123 && !Yaml_Map("","",LF))
Return 0
} else If (VQ || !Yaml_SeqMap(cObj,"",LF))
cObj.Insert(VQ?Yaml_UniChar(LF):Trim(LF))
}
Return (obj=""?(Quote Bracket=""):1)
}
Yaml_Map(obj,key,value,isVal=0){
static base:={Dump:"Yaml_Dump",Save:"Yaml_Save",Add:"Yaml_Add",Merge:"Yaml_Merge",__Delete:"__Delete",_Insert:"_Insert",_Remove:"_Remove",_GetCapacity:"_GetCapacity",_SetCapacity:"_SetCapacity",_GetAddress:"_GetAddress",_MaxIndex:"_MaxIndex",_MinIndex:"_MinIndex",_NewEnum:"_NewEnum",_HasKey:"_HasKey",_Clone:"_Clone",Insert:"Insert",Remove:"Remove",GetCapacity:"GetCapacity",SetCapacity:"SetCapacity",GetAddress:"GetAddress",MaxIndex:"MaxIndex",MinIndex:"MinIndex",NewEnum:"NewEnum",HasKey:"HasKey",Clone:"Clone",base:{__Call:"Yaml_Call"}}
ContinueNext:=0
If (obj=""){
If (SubStr(value,0)!="}")
Return 0
else
value:=SubStr(value,2,StrLen(value)-2)
} else {
If (key="")
obj.Insert(cObj:=Object("base",base))
else obj[key]:=(cObj:=Object("base",base))
}
Count:=StrLen(value)
Loop,Parse,value
{
If ((Quote=""""&&Yaml_Quote(LF,A_LoopField,Quote,Bracket,Escape)) || (ContinueNext && !ContinueNext:=0))
Continue
If (Quote){
If (A_LoopField=Quote){
Quote=
LF.=A_LoopField
} else LF .= A_LoopField
continue
} else if (!Quote&&(k=""||v="")&&InStr("""'",A_LoopField)){
Quote:=A_LoopField
If (k && !Bracket)
VQ:=Quote
else if !Bracket
KQ:=Quote
LF.=Quote
Continue
} else If (k!=""&&LF=""&&InStr("`n`r `t",A_LoopField)){
Continue
}
If (!Quote&&Bracket){
If (Asc(A_LoopField)=Asc(Bracket)+2)
BCount--
else if (A_LoopField=Bracket)
BCount++
If (BCount=0)
Bracket=
LF .= A_LoopField
Continue
} else if (!Quote&&!Bracket&&InStr("[{",A_LoopField)){
Bracket:=A_LoopField
BCount=1
LF.=A_LoopField
Continue
}
If (A_Index=Count&&k!=""){
v:=LF A_LoopField
v:=Trim(v)
If (InStr("""'",SubStr(v,0))&&SubStr(v,1,1)=SubStr(v,0))
v:=SubStr(v,2,StrLen(v)-2)
} else If (!Quote&&!Bracket&&k!=""&&A_LoopField=","&&SubStr(value,A_Index+1,1)=A_Space){
ContinueNext:=1
LF:=Trim(LF)
If VQ
LF:=SubStr(LF,2,StrLen(LF)-2)
v:=LF,LF:=""
} else if (!Quote&&!Bracket&&k=""&&A_LoopField=":"){
LF:=Trim(LF)
If (InStr("""'",SubStr(LF,0))&&SubStr(LF,1,1)=SubStr(LF,0))
LF:=SubStr(LF,2,StrLen(LF)-2)
k:=LF,LF:=""
continue
} else {
LF .= A_LoopField
continue
}
If (obj=""){
If VQ=
If (Asc(v)=91 && !Yaml_Seq("","",v))
||(Asc(v)=123 && !Yaml_Map("","",v))
Return 0
} else {
If (VQ || !Yaml_SeqMap(cObj,k,v))
cObj[KQ?Yaml_UniChar(k):k]:=(VQ?Yaml_UniChar(v):Trim(v))
}
k:="",v:="",VQ:="",KQ:=""
}
If (k){
If (obj=""){
If (Asc(LF)=91 && !Yaml_Seq("","",LF))||(Asc(LF)=123 && !Yaml_Map("","",LF))
Return 0
} else {
LF:=Trim(LF)
If (VQ)
LF:=SubStr(LF,2,StrLen(LF)-2),cObj[k]:=Yaml_UniChar(LF)
else If (!Yaml_SeqMap(cObj,k,LF))
cObj[k]:=Trim(LF)
}
}
Return (obj=""?(Quote Bracket=""):1)
}
Yaml_Incomplete(value){
return (Asc(Trim(value,"`n" A_Tab A_Space))=91 && !Yaml_Seq("","",Trim(value,"`n" A_Tab A_Space)))
|| (Asc(Trim(value,"`n" A_Tab A_Space))=123 && !Yaml_Map("","",Trim(value,"`n" A_Tab A_Space)))
}
Yaml_IsSeqMap(value){
return (Asc(Trim(value,"`n" A_Tab A_Space))=91 && Yaml_Seq("","",Trim(value,"`n" A_Tab A_Space)))
|| (Asc(Trim(value,"`n" A_Tab A_Space))=123 && Yaml_Map("","",Trim(value,"`n" A_Tab A_Space)))
}
Yaml(YamlText,IsFile=1,YamlObj=0){ ; Version 1.0.0.17 http://www.autohotkey.com/forum/viewtopic.php?t=70559
static
static base:={Dump:"Yaml_Dump",Save:"Yaml_Save",Add:"Yaml_Add",Merge:"Yaml_Merge",__Delete:"__Delete",_Insert:"_Insert",_Remove:"_Remove",_GetCapacity:"_GetCapacity",_SetCapacity:"_SetCapacity",_GetAddress:"_GetAddress",_MaxIndex:"_MaxIndex",_MinIndex:"_MinIndex",_NewEnum:"_NewEnum",_HasKey:"_HasKey",_Clone:"_Clone",Insert:"Insert",Remove:"Remove",GetCapacity:"GetCapacity",SetCapacity:"SetCapacity",GetAddress:"GetAddress",MaxIndex:"MaxIndex",MinIndex:"MinIndex",NewEnum:"NewEnum",HasKey:"HasKey",Clone:"Clone",base:{__Call:"Yaml_Call"}}
static BackupVars:="LVL,SEQ,KEY,SCA,TYP,VAL,CMT,LFL,CNT",IncompleteSeqMap
local maxLVL:=0,LastContObj:=0,LastContKEY:=0,LinesAdded:=0,_LVLChanged:=0,_LVL,_SEQ,_KEY,_SCA,_TYP,_VAL,_CMT,_LFL,_CNT,_NXT,__LVL,__SEQ,__KEY,__SCA,__TYP,__VAL,__CMT,__LFL,__CNT,__NXT
AutoTrim % ((AutoTrim:=A_AutoTrim)="On")?"Off":"Off"
LVL0:=pYaml:=YamlObj?YamlObj:Object("base",base),__LVL:=0,__LVL0:=0
If IsFile
FileRead,YamlText,%YamlText%
Loop,Parse,YamlText,`n,`r
{
If (!_CNT && (A_LoopField=""||RegExMatch(A_LoopField,"^\s+$"))){ ;&&__KEY=""&&__SEQ="")){
If ((OBJ:=LVL%__LVL%[""].MaxIndex())&&IsObject(LVL%__LVL%["",OBJ])&&__SEQ){
If (__KEY!="")
Yaml_Continue(LastContObj:=LVL%__LVL%["",Obj],LastContKEY:=__key,"",__SCA)
else Yaml_Continue(LastContObj:=LVL%__LVL%[""],LastContKEY:=Obj,"",__SCA,__SEQ)
} else If (__SEQ && OBJ){
Yaml_Continue(LastContObj:=LVL%__LVL%[""],LastContKEY:=OBJ,"",__SCA,__SEQ)
} else If (OBJ){
Yaml_Continue(LastContObj:=LVL%__LVL%[""],LastContKEY:=OBJ,"",__SCA,1)
} else if (__KEY!="")
Yaml_Continue(LastContObj:=LVL%__LVL%,LastContKEY:=__KEY,"",__SCA)
else LinesAdded--
LinesAdded++
Continue
} else If (!_CNT && LastContObj
&& ( RegExMatch(A_LoopField,"^(---)?\s*?(-\s)?("".+""\s*:\s|'.+'\s*:\s|[^:""'\{\[]+\s*:\s)")
|| RegExMatch(A_LoopField,"^(---)|\s*(-\s)") )){
If !__SCA
LastContObj[LastContKEY]:=SubStr(LastContObj[LastContKEY],1,-1*LinesAdded)
LastContObj:=0,LastContKEY:=0,LinesAdded:=0
}
If InStr(A_LoopField,"#"){
If (RegexMatch(A_LoopField,"^\s*#.*") || InStr(A_LoopField,"%YAML")=1) ;Comments only, do not parse
continue
else if Yaml_IsQuoted(LTrim(A_LoopField,"- ")) || RegExMatch(A_LoopField,"(---)?\s*?(-\s)?("".+""\s*:\s|'.+'\s*:\s|[^:""'\{\[]+\s*:\s)\s*([\|\>][+-]?)?\s*(!!\w+\s)?\s*("".+|'.+)$")&&!RegExMatch(A_LoopField,"[^\\]""\s+#")
LoopField:=A_LoopField
else if RegExMatch(A_LoopField,"\s+#.*$","",RegExMatch(A_LoopField,"(---)?\s*?(-\s)?("".+""\s*:\s|'.+'\s*:\s|[^:""'\{\[]+\s*:\s)?\s*([\|\>][+-]?)?\s*(!!\w+\s)?\s*("".+""|'.+')?\K")-1)
LoopField:=SubStr(A_LoopField,1,RegExMatch(A_LoopField,"\s+#.*$","",RegExMatch(A_LoopField,"(---)?\s*?(-\s)?("".+""\s*:\s|'.+'\s*:\s|[^:""'\{\[]+\s*:\s)?\s*([\|\>][+-]?)?\s*(!!\w+\s)?\s*("".+""|'.+')?\K")-1)-1)
else LoopField:=A_LoopField
} else LoopField:=A_LoopField
If _CNT {
If Yaml_IsSeqMap(RegExReplace(IncompleteSeqMap LoopField,"^(\s+)?(-\s)?("".+""\s*:\s|'.+'\s*:\s|[^:""'\{\[]+\s*:\s)?"))
LoopField:=IncompleteSeqMap LoopField,_CNT:=0,IncompleteSeqMap:=""
else {
IncompleteSeqMap.=LoopField
continue
}
}
If (LoopField="---"){
Loop % (maxLVL)
LVL%A_Index%:=""
Loop,Parse,BackupVars,`,
__%A_LoopField%:="",__%A_LoopField%0:=""
Loop,Parse,BackupVars,`,
Loop % maxLVL
__%A_LoopField%%A_Index%:=""
maxLVL:=0
__LVL:=0,__LVL0:=0
If !IsObject(pYaml[""])
pYaml[""]:=LVL0:=Object("base",base)
pYaml[""].Insert(LVL0:=Object("base",base))
Continue
} else if (LoopField="..."){
LVL0:=pYaml
Loop % maxLVL
LVL%A_Index%:=""
Loop,Parse,BackupVars,`,
__%A_LoopField%:="",__%A_LoopField%0:=""
Loop,Parse,BackupVars,`,
Loop % maxLVL
__%A_LoopField%%A_Index%:=""
maxLVL:=0
__LVL:=0,__LVL0:=0
Continue
}
If (SubStr(LoopField,0)=":")
LoopField.=A_Space ; add space to force RegEx to match even if the value and space after collon is missing e.g. Object:`n objects item
RegExMatch(LoopField,"S)^(?<LVL>\s+)?(?<SEQ>-\s)?(?<KEY>"".+""\s*:\s|'.+'\s*:\s|[^:""'\{\[]+\s*:\s)?\s*(?<SCA>[\|\>][+-]?)?\s*(?<TYP>!!\w+\s)?\s*(?<VAL>"".+""|'.+'|.+)?\s*$",_)
If _KEY ;cut off (:)
StringTrimRight,_KEY,_KEY,2
_KEY:=Yaml_UnQuoteIfNeed(_KEY)
If IsVal:=Yaml_IsQuoted(_VAL)
_VAL:=Yaml_UnQuoteIfNeed(_VAL)
;determine current level
_LVL:=Yaml_S2I(_LVL)
If _LVL-__LVL>1||(_LVL>__LVL&&_LVLChanged) ;&&!(__SEQ&&__KEY!=""&&_KEY!="")) ; (__SEQ?2:1)
{
Loop % (_LVLChanged?_LVL-_LVLChanged:_LVL-__LVL-1)
LoopField:=SubStr(LoopField,SubStr(LoopField,1,1)=A_Tab?1:2)
_LVL:=_LVLChanged?_LVLChanged:__LVL+1,_LVLChanged:=_LVLChanged?_LVLChanged:_LVL ;__LVL%_LVL%:=__LVL%_NXT% ; (__SEQ?2:1)
} else if _LVLChanged
_LVL:=_LVLChanged
else _LVLChanged:=0
If (maxLVL<_LVL)
maxLVL:=_LVL+(_SEQ?1:0)
; Cut off the leading tabs/spaces conform _LVL
SubStr:=0,Tabs:=0
Loop,Parse,LoopField
If (_LVL*2=SubStr || !SubStr:=SubStr+(A_LoopField=A_Tab?2:1)), Tabs:=Tabs+(A_LoopField=A_Tab?1:0)
break
_LFL:=SubStr(LoopField,SubStr-Tabs+1+(_SEQ?2:0))
_LFL:=Yaml_UnQuoteIfNeed(_LFL)
_NXT:=_LVL+1 ;next indentation level
__NXT:=_NXT+1
_PRV:=_LVL=0?0:_LVL-1
Loop,Parse,BackupVars,`,
__%A_LoopField%:=__%A_LoopField%%_PRV%
If RegExMatch(_LFL,"^-\s*$"){
_SEQ:="-",_KEY:="",_VAL:=""
}
If (!IsVal && !_CNT && (_CNT:=Yaml_Incomplete(Trim(_LFL))||Yaml_Incomplete(Trim(_VAL)))){
IncompleteSeqMap:=LoopField
continue
}
If (_LVL<__LVL){ ;Reset Objects and Backup vars
Loop % (maxLVL)
If (A_Index>_LVL){
Loop,Parse,BackupVars,`,
__%A_LoopField%%maxLVL%:=""
LVL%A_Index%:="",maxLVL:=maxLVL-1
}
If (_LVL=0 && !__LVL:=__LVL0:=0)
Loop,Parse,BackupVars,`,
__%A_LoopField%:="",__%A_LoopField%0:=""
}
If (_SEQ&&_LVL>__LVL&&(__VAL!=""||__SCA))
_SEQ:="",_KEY:="",_VAL:="",_LFL:="- " _LFL
If (__CNT)||(_LVL>__LVL&&(__KEY!=""&&_KEY="")&&(__VAL!=""||__SCA))||(__SEQ&&__SCA)
_KEY:="",_VAL:=""
If (__CNT||(_LVL>__LVL&&(__KEY!=""||(__SEQ&&(__LFL||__SCA)&&!Yaml_IsSeqMap(__LFL)))&&!(_SEQ||_KEY!=""))){
If ((OBJ:=LVL%__LVL%[""].MaxIndex())&&IsObject(LVL%__LVL%["",OBJ])&&__SEQ){
If __KEY!=
Yaml_Continue(LVL%__LVL%["",Obj],__key,_LFL,__SCA),__CNT:=Yaml_SeqMap(LVL%__LVL%["",OBJ],__KEY,LVL%__LVL%["",OBJ,__KEY])?"":__CNT
else Yaml_Continue(LVL%__LVL%[""],Obj,_LFL,__SCA,__SEQ),__CNT:=Yaml_SeqMap(LVL%__LVL%[""],OBJ,LVL%__LVL%["",OBJ],__SEQ)?"":__CNT
} else If (__SEQ && OBJ){
Yaml_Continue(LVL%__LVL%[""],Obj,_LFL,__SCA,__SEQ)
__CNT:=Yaml_SeqMap(LVL%__LVL%[""],OBJ,LVL%__LVL%["",OBJ],__SEQ)?"":__CNT
} else If (OBJ && __KEY=""){
Yaml_Continue(LVL%__LVL%[""],OBJ,_LFL,__SCA,1)
__CNT:=Yaml_SeqMap(LVL%__LVL%[""],OBJ,LVL%__LVL%["",OBJ],1)?"":__CNT
} else {
Yaml_Continue(LVL%__LVL%,__KEY,_LFL,__SCA)
__CNT:=Yaml_SeqMap(LVL%__LVL%,__KEY,LVL%__LVL%[__KEY])?"":__CNT
}
Continue
}
;Create sequence or map
If (__SEQ&&(_LVL>__LVL)&&_KEY!=""&&__KEY!=""){
OBJ:=LVL%__LVL%[""].MaxIndex()
If _SEQ {
If !Yaml_SeqMap(LVL%_LVL%["",OBJ,__KEY,""],_KEY,_VAL){
If !IsObject(LVL%__LVL%["",OBJ,__KEY,""])
LVL%__LVL%["",OBJ,__KEY,""]:={base:base}
LVL%__LVL%["",OBJ,__KEY,""].Insert({(_KEY):_VAL!=""?_VAL:(LVL%_NXT%:={base:base}),base:base})
}
} else If !Yaml_SeqMap(LVL%_LVL%["",OBJ],_KEY,_VAL){
LVL%__LVL%["",OBJ,_KEY]:=_VAL!=""?_VAL:(LVL%_NXT%:={base:base})
}
If _VAL!=
continue
} else If (_SEQ){
If !IsObject(LVL%_LVL%[""])
LVL%_LVL%[""]:=Object("base",base)
While (SubStr(_LFL,1,2)="- "){
_LFL:=SubStr(_LFL,3),_KEY:=(_KEY!="")?_LFL:=SubStr(_KEY,3):_KEY,LVL%_LVL%[""].Insert(LVL%_NXT%:=Object("",Object("base",base),"base",base)),_LVL:=_LVL+1,_NXT:=_NXT+1,__NXT:=_NXT+1,_PRV:=_LVL-1,maxLVL:=(maxLVL<_LVL)?_LVL:maxLVL
Loop,Parse,BackupVars,`,
__%A_LoopField%:=_%A_LoopField%
,__%A_LoopField%%_PRV%:=_%A_LoopField%
}
If (_KEY="" && _VAL="" && !IsVal){
If !Yaml_SeqMap(LVL%_LVL%[""],"",_LFL)
LVL%_LVL%[""].Insert(LVL%_NXT%:=Object("base",base))
} else If (_KEY!="") {
LVL%_LVL%[""].Insert(LVL%__NXT%:=Object(_KEY,LVL%_NXT%:=Object("base",base),"base",base))
If !Yaml_SeqMap(LVL%__NXT%,_KEY,_VAL){
LVL%_LVL%[""].Remove()
LVL%_LVL%[""].Insert(LVL%__NXT%:=Object(_KEY,(_VAL!=""||IsVal)?_VAL:LVL%_NXT%:=Object("base",base),"base",base))
}
} else {
If !Yaml_SeqMap(LVL%_LVL%[""],"",_LFL)
LVL%_LVL%[""].Insert(_LFL)
}
If !LVL%_LVL%[""].MaxIndex()
LVL%_LVL%.Remove("")
} else if (_KEY!=""){
If (__SEQ && _LVL>__LVL) {
If (OBJ:=LVL%_PRV%[""].MaxIndex())&&IsObject(LVL%_PRV%["",OBJ]){
If !Yaml_SeqMap(LVL%_PRV%["",OBJ],_KEY,_VAL)
LVL%_PRV%["",OBJ,_KEY]:=(_VAL!=""||IsVal)?_VAL:(LVL%_NXT%:=Object("base",base))
} else {
LVL%_PRV%[""].Insert(Object(_KEY,(_VAL!=""||IsVal)?_VAL:(LVL%_NXT%:=Object("base",base)),"base",base))
Yaml_SeqMap(LVL%_PRV%["",OBJ?OBJ+1:1],_KEY,_VAL)
}
} else
If !Yaml_SeqMap(LVL%_LVL%,_KEY,_VAL)
LVL%_LVL%[_KEY]:=_VAL!=""?_VAL:(LVL%_NXT%:=Object("base",base))
} else if (_LVL>__LVL && (__KEY!="")) {
If (__VAL!="" || __SCA){
Yaml_Continue(LVL%__LVL%,__KEY,_LFL,__SCA)
Yaml_SeqMap(LVL%__LVL%,__KEY,LVL%__LVL%[__KEY])
Continue
} else {
If !Yaml_SeqMap(LVL%__LVL%[__KEY],_KEY,_VAL) ;!!! no Scalar???
LVL%__LVL%[__KEY,_KEY]:=_VAL
Continue
}
} else {
If (_LVL>__LVL&&(OBJ:=LVL%__LVL%[""].MaxIndex())&&IsObject(LVL%__LVL%["",OBJ])&&__SEQ){
If __CNT
Yaml_Continue(LVL%__LVL%[""],LVL%__LVL%[""].MaxIndex(),_LFL,__SCA,1)
If (__CNT:=Yaml_SeqMap(LVL%__LVL%[""],"",_LFL)?"":1)
LVL%__LVL%[""].Insert(_LFL)
} else {
If !IsObject(LVL%_LVL%[""])
LVL%_LVL%[""]:=Object("base",base)
If __CNT
Yaml_Continue(LVL%__LVL%[""],LVL%__LVL%[""].MaxIndex(),_LFL,__SCA,1)
If (__CNT:=Yaml_SeqMap(LVL%_LVL%[""],"",_LFL)?"":1)
LVL%_LVL%[""].Insert(_LFL)
}
Continue
}
Loop,Parse,BackupVars,`,
__%A_LoopField%:=_%A_LoopField%
,__%A_LoopField%%_LVL%:=_%A_LoopField%
}
If (LastContObj && !__SCA)
LastContObj[LastContKEY]:=SubStr(LastContObj[LastContKEY],1,-1*LinesAdded)
AutoTrim %AutoTrim%
Loop,Parse,BackupVars,`,
If !(__%A_LoopField%:="")
Loop % maxLVL
__%A_LoopField%%A_Index%:=""
Return pYaml,pYaml.base:=base
}
Yaml_Save(obj,file,level=""){
FileMove,% file,% file ".bakupyml",1
FileAppend,% obj.Dump(),% file
If !ErrorLevel
FileDelete,% file ".bakupyml"
else {
FileMove,% file ".bakupyml",% file
MsgBox,0, Error creating file, old file was restored.
}
}
Yaml_Call(NotSupported,f,p*){
If (p.MaxIndex()>1){
Loop % p.MaxIndex()
If A_Index>1
f:=f[""][p[A_Index-1]]
}
Return (!p.MaxIndex()?f[""].MaxIndex():f[""][p[p.MaxIndex()]])
}
Yaml_Merge(obj,merge){
for k,v in merge
{
If IsObject(v){
If obj.HasKey(k){
If IsObject(obj[k])
Yaml_Merge(obj[k],v)
else obj[k]:=v
} else obj[k]:=v
} else obj[k]:=v
}
}
Yaml_Add(O,Yaml="",IsFile=0){
static base:={Dump:"Yaml_Dump",Save:"Yaml_Save",Add:"Yaml_Add",Merge:"Yaml_Merge",__Delete:"__Delete",_Insert:"_Insert",_Remove:"_Remove",_GetCapacity:"_GetCapacity",_SetCapacity:"_SetCapacity",_GetAddress:"_GetAddress",_MaxIndex:"_MaxIndex",_MinIndex:"_MinIndex",_NewEnum:"_NewEnum",_HasKey:"_HasKey",_Clone:"_Clone",Insert:"Insert",Remove:"Remove",GetCapacity:"GetCapacity",SetCapacity:"SetCapacity",GetAddress:"GetAddress",MaxIndex:"MaxIndex",MinIndex:"MinIndex",NewEnum:"NewEnum",HasKey:"HasKey",Clone:"Clone",base:{__Call:"Yaml_Call"}}
If Yaml_IsSeqMap(Trim(Yaml)){
If !IsObject(O[""])
O[""]:=Object("base",base)
Yaml_SeqMap(O[""],"",Yaml)
} else Yaml(Yaml,IsFile,O)
}
Yaml_Dump(O,J="",R=0,Q=0){
static M1:="{",M2:="}",S1:="[",S2:="]",N:="`n",C:=", ",S:="- ",E:="",K:=": "
local dump:="",M,MX,F,I,key,value
If (J=0&&!R)
dump.= S1
for key in O
M:=A_Index
If IsObject(O[""]){
M--
for key in O[""]
MX:=A_Index
If IsObject(O[""][""])
MX--
If O[""].MaxIndex()
for key, value in O[""]
{
If key=
continue
I++
F:=IsObject(value)?(IsObject(value[""])?"S":"M"):E
If (J!=""&&J<=R){
dump.=(F?(%F%1 Yaml_Dump(value,J,R+1,F) %F%2):Yaml_EscIfNeed(value)) (I=MX&&!M?E:C) ;(Q="S"&&I=1?S1:E)(Q="S"&&I=MX?S2:E)
} else if F,dump:=dump N Yaml_I2S(R) S
dump.= (J!=""&&J<=(R+1)?%F%1:E) Yaml_Dump(value,J,R+1,F) (J!=""&&J<=(R+1)?%F%2:E)
else {
; If RegexMatch(value,"[\x{007F}-\x{FFFF}""\{\[']|:\s|\s#")
dump .= Yaml_EscIfNeed(value)
; else {
; value:= (value=""?"''":RegExReplace(RegExReplace(Value,"m)^(.*[\r\n].*)$","|" (SubStr(value,-1)="`n`n"?"+":SubStr(value,0)=N?"":"-") "`n$1"),"ms)(*ANYCRLF)\R",N Yaml_I2S(R+1)))
; StringReplace,value,value,% N Yaml_I2S(R+1) N Yaml_I2S(R+1),% N Yaml_I2S(R+1),A
; dump.=value
; }
}
}
}
I=0
for key, value in O
{
If key=
continue
I++
F:=IsObject(value)?(IsObject(value[""])?"S":"M"):E
If (J=0&&!R)
dump.= M1
If (J!=""&&J<=R){
dump.=(Q="S"&&I=1?M1:E) Yaml_EscIfNeed(key) K
dump.=F?(%F%1 Yaml_Dump(value,J,R+1,F) %F%2):Yaml_EscIfNeed(value)
dump.=(Q="S"&&I=M?M2:E) (J!=0||R?(I=M?E:C):E)
} else if F,dump:=dump N Yaml_I2S(R) Yaml_EscIfNeed(key) K
dump.= (J!=""&&J<=(R+1)?%F%1:E) Yaml_Dump(value,J,R+1,F) (J!=""&&J<=(R+1)?%F%2:E)
else {
; If RegexMatch(value,"[\x{007F}-\x{FFFF}""\{\['\t]|:\s|\s#")
dump .= Yaml_EscIfNeed(value)
; else {
; value:= (value=""?"''":RegExReplace(RegExReplace(Value,"m)^(.*[\r\n].*)$","|" (SubStr(value,-1)="`n`n"?"+":SubStr(value,0)="`n"?"":"-") "`n$1"),"ms)(*ANYCRLF)\R","`n" Yaml_I2S(R+1)))
; StringReplace,value,value,% "`n" Yaml_I2S(R+1) "`n" Yaml_I2S(R+1),% "`n" Yaml_I2S(R+1),A
; dump.= value
; }
}
If (J=0&&!R){
dump.=M2 (I<M?C:E)
}
}
If (J=0&&!R)
dump.=S2
If (R=0)
dump:=RegExReplace(dump,"^\R+")
Return dump
}
Yaml_UniChar( string ) {
static a:="`a",b:="`b",t:="`t",n:="`n",v:="`v",f:="`f",r:="`r",e:=Chr(0x1B)
Loop,Parse,string,\
{
If (A_Index=1){
var.=A_LoopField
continue
} else If lastempty {
var.="\" A_LoopField
lastempty:=0
Continue
} else if (A_LoopField=""){
lastempty:=1
Continue
}
If InStr("ux",SubStr(A_LoopField,1,1))
str:=SubStr(A_LoopField,1,RegExMatch(A_LoopField,"^[ux]?([\dA-F]{4})?([\dA-F]{2})?\K")-1)
else
str:=SubStr(A_LoopField,1,1)
If (str=="N")
str:="\x85"
else if (str=="P")
str:="\x2029"
else if (str=0)
str:="\x0"
else if (str=="L")
str:="\x2028"
else if (str=="_")
str:="\xA0"
If RegexMatch(str,"i)^[ux][\da-f]+$")
var.=Chr(Abs("0x" SubStr(str,2)))
else If str in a,b,t,n,v,f,r,e
var.=%str%
else var.=str
If InStr("ux",SubStr(A_LoopField,1,1))
var.=SubStr(A_LoopField,RegExMatch(A_LoopField,"^[ux]?([\dA-F]{4})?([\dA-F]{2})?\K"))
else var.=SubStr(A_LoopField,2)
}
return var
}
Yaml_CharUni( string ) {
static ascii:={"\":"\","`a": "a","`b": "b","`t": "t","`n": "n","`v": "v","`f": "f","`r": "r",Chr(0x1B): "e","""": """",Chr(0x85): "N",Chr(0x2029): "P",Chr(0x2028): "L","": "0",Chr(0xA0): "_"}
If !RegexMatch(string,"[\x{007F}-\x{FFFF}]"){
Loop,Parse,string
{
If ascii[A_LoopField]
var.="\" ascii[A_LoopField]
else
var.=A_LoopField
}
return var
}
format:=A_FormatInteger
SetFormat,Integer,H
Loop,Parse,string
{
If ascii[A_LoopField]
var.="\" ascii[A_LoopField]
else if Asc(A_LoopField)<128
var.=A_LoopField
else {
str:=SubStr(Asc(A_LoopField),3)
var.="\u" (StrLen(str)<2?"000":StrLen(str)<3?"00":StrLen(str)<4?"0":"") str
}
}
SetFormat,Integer,%Format%
return var
}
Yaml_EscIfNeed(s){
If (s="")
return "''"
else If RegExMatch(s,"m)[\{\[""'\r\n]|:\s|,\s|\s#")||RegExMatch(s,"^[\s#\\\-:>]")||RegExMatch(s,"m)\s$")||RegExMatch(s,"m)[\x{7F}-\x{7FFFFFFF}]")
return ("""" . Yaml_CharUni(s) . """")
else return s
}
Yaml_IsQuoted(ByRef s){
return InStr(".''."""".","." SubStr(Trim(s),1,1) SubStr(Trim(s),0) ".")?1:0
}
Yaml_UnQuoteIfNeed(s){
s:=Trim(s)
If !(SubStr(s,1,1)=""""&&SubStr(s,0)="""")
return (SubStr(s,1,1)="'"&&SubStr(s,0)="'")?SubStr(s,2,StrLen(s)-2):s
else return Yaml_UniChar(SubStr(s,2,StrLen(s)-2))
}
Yaml_S2I(str){
local idx:=0
Loop,Parse,str
If (A_LoopField=A_Tab)
idx++
else if !Mod(A_index,2)
idx++
Return idx
}
Yaml_I2S(idx){
Loop % idx
str .= " "
Return str
}
Yaml_Continue(Obj,key,value,scalar="",isval=0){
If !IsObject(isObj:=obj[key])
v:=isObj
If scalar {
StringTrimLeft,scaopt,scalar,1
scalar:=Asc(scalar)=124?"`n":" "
} else scalar:=" ",scaopt:="-"
temp := (value=""?"`n":(SubStr(v,0)="`n"&&scalar="`n"?"":(v=""?"":scalar))) value (scaopt!="-"?(v&&value=""?"`n":""):"")
obj[key]:=Yaml_UnQuoteIfNeed(v temp)
}
Yaml_Quote(ByRef L,F,Q,B,ByRef E){
Return (F="\"&&!E&&(E:=1))||(E&&!(E:=0)&&(L:=L ("\" F)))
}
Yaml_SeqMap(o,k,v,isVal=0){
v:=Trim(v,A_Tab A_Space "`n"),m:=SubStr(v,1,1) SubStr(v,0)
If Yaml_IsSeqMap(v)
return m="[]"?Yaml_Seq(o,k,SubStr(v,2,StrLen(v)-2),isVal):m="{}"?Yaml_Map(o,k,SubStr(v,2,StrLen(v)-2),isVal):0
}
Yaml_Seq(obj,key,value,isVal=0){
static base:={Dump:"Yaml_Dump",Save:"Yaml_Save",Add:"Yaml_Add",Merge:"Yaml_Merge",__Delete:"__Delete",_Insert:"_Insert",_Remove:"_Remove",_GetCapacity:"_GetCapacity",_SetCapacity:"_SetCapacity",_GetAddress:"_GetAddress",_MaxIndex:"_MaxIndex",_MinIndex:"_MinIndex",_NewEnum:"_NewEnum",_HasKey:"_HasKey",_Clone:"_Clone",Insert:"Insert",Remove:"Remove",GetCapacity:"GetCapacity",SetCapacity:"SetCapacity",GetAddress:"GetAddress",MaxIndex:"MaxIndex",MinIndex:"MinIndex",NewEnum:"NewEnum",HasKey:"HasKey",Clone:"Clone",base:{__Call:"Yaml_Call"}}
ContinueNext:=0
If (obj=""){
If (SubStr(value,0)!="]")
Return 0
else
value:=SubStr(value,2,StrLen(value)-2)
} else {
If (key=""){
obj.Insert(Object("",cObj:=Object("base",base),"base",base))
} else if (isval && IsObject(obj[key,""])){
cObj:=obj[key,""]
} else obj[key]:=Object("",cObj:=Object("base",base),"base",base)
}
Count:=StrLen(value)
Loop,Parse,value
{
If ((Quote=""""&&Yaml_Quote(LF,A_LoopField,Quote,Bracket,Escape)) || (ContinueNext && !ContinueNext:=0))
Continue
If (Quote){
If (A_LoopField=Quote){
Quote=
If Bracket
LF.= A_LoopField
else LF:=SubStr(LF,2)
Continue
}
LF .= A_LoopField
continue
} else if (!Quote&&InStr("""'",A_LoopField)){
Quote:=A_LoopField
If !Bracket
VQ:=Quote
LF.=A_LoopField
Continue
} else if (!Quote&&Bracket){
If (Asc(A_LoopField)=Asc(Bracket)+2)
BCount--
else if (A_LoopField=Bracket)
BCount++
If (BCount=0)
Bracket=
LF .= A_LoopField
Continue
} else if (!Quote&&!Bracket&&InStr("[{",A_LoopField)){
Bracket:=A_LoopField
BCount:=1
LF.=A_LoopField
Continue
}
If (A_Index=Count)
LF .= A_LoopField
else if (!Quote&&!Bracket&&A_LoopField=","&&(!InStr("0123456789",SubStr(value,A_Index-1,1)) | !InStr("0123456789",SubStr(value,A_Index+1,1)))){
ContinueNext:=SubStr(value,A_Index+1,1)=A_Space||SubStr(value,A_Index+1,1)=A_Tab
LF:=LF
} else {
LF .= A_LoopField
continue
}
If (obj=""){
If !VQ
If (Asc(LF)=91 && !Yaml_Seq("","",LF))
||(Asc(LF)=123 && !Yaml_Map("","",LF))
Return 0
} else {
If (VQ || !Yaml_SeqMap(cObj,"",LF))
cObj.Insert(VQ?Yaml_UniChar(LF):Trim(LF))
}
LF:="",VQ:=""
}
If (LF){
If (obj=""){
If !VQ
If (Asc(LF)=91 && !Yaml_Seq("","",LF))||(Asc(LF)=123 && !Yaml_Map("","",LF))
Return 0
} else If (VQ || !Yaml_SeqMap(cObj,"",LF))
cObj.Insert(VQ?Yaml_UniChar(LF):Trim(LF))
}
Return (obj=""?(Quote Bracket=""):1)
}
Yaml_Map(obj,key,value,isVal=0){
static base:={Dump:"Yaml_Dump",Save:"Yaml_Save",Add:"Yaml_Add",Merge:"Yaml_Merge",__Delete:"__Delete",_Insert:"_Insert",_Remove:"_Remove",_GetCapacity:"_GetCapacity",_SetCapacity:"_SetCapacity",_GetAddress:"_GetAddress",_MaxIndex:"_MaxIndex",_MinIndex:"_MinIndex",_NewEnum:"_NewEnum",_HasKey:"_HasKey",_Clone:"_Clone",Insert:"Insert",Remove:"Remove",GetCapacity:"GetCapacity",SetCapacity:"SetCapacity",GetAddress:"GetAddress",MaxIndex:"MaxIndex",MinIndex:"MinIndex",NewEnum:"NewEnum",HasKey:"HasKey",Clone:"Clone",base:{__Call:"Yaml_Call"}}
ContinueNext:=0
If (obj=""){
If (SubStr(value,0)!="}")
Return 0
else
value:=SubStr(value,2,StrLen(value)-2)
} else {
If (key="")
obj.Insert(cObj:=Object("base",base))
else obj[key]:=(cObj:=Object("base",base))
}
Count:=StrLen(value)
Loop,Parse,value
{
If ((Quote=""""&&Yaml_Quote(LF,A_LoopField,Quote,Bracket,Escape)) || (ContinueNext && !ContinueNext:=0))
Continue
If (Quote){
If (A_LoopField=Quote){
Quote=
LF.=A_LoopField
} else LF .= A_LoopField
continue
} else if (!Quote&&(k=""||v="")&&InStr("""'",A_LoopField)){
Quote:=A_LoopField
If (k && !Bracket)
VQ:=Quote
else if !Bracket
KQ:=Quote
LF.=Quote
Continue
} else If (k!=""&&LF=""&&InStr("`n`r `t",A_LoopField)){
Continue
}
If (!Quote&&Bracket){
If (Asc(A_LoopField)=Asc(Bracket)+2)
BCount--
else if (A_LoopField=Bracket)
BCount++
If (BCount=0)
Bracket=
LF .= A_LoopField
Continue
} else if (!Quote&&!Bracket&&InStr("[{",A_LoopField)){
Bracket:=A_LoopField
BCount=1
LF.=A_LoopField
Continue
}
If (A_Index=Count&&k!=""){
v:=LF A_LoopField
v:=Trim(v)
If (InStr("""'",SubStr(v,0))&&SubStr(v,1,1)=SubStr(v,0))
v:=SubStr(v,2,StrLen(v)-2)
} else If (!Quote&&!Bracket&&k!=""&&A_LoopField=","&&SubStr(value,A_Index+1,1)=A_Space){
ContinueNext:=1
LF:=Trim(LF)
If VQ
LF:=SubStr(LF,2,StrLen(LF)-2)
v:=LF,LF:=""
} else if (!Quote&&!Bracket&&k=""&&A_LoopField=":"){
LF:=Trim(LF)
If (InStr("""'",SubStr(LF,0))&&SubStr(LF,1,1)=SubStr(LF,0))
LF:=SubStr(LF,2,StrLen(LF)-2)
k:=LF,LF:=""
continue
} else {
LF .= A_LoopField
continue
}
If (obj=""){
If VQ=
If (Asc(v)=91 && !Yaml_Seq("","",v))
||(Asc(v)=123 && !Yaml_Map("","",v))
Return 0
} else {
If (VQ || !Yaml_SeqMap(cObj,k,v))
cObj[KQ?Yaml_UniChar(k):k]:=(VQ?Yaml_UniChar(v):Trim(v))
}
k:="",v:="",VQ:="",KQ:=""
}
If (k){
If (obj=""){
If (Asc(LF)=91 && !Yaml_Seq("","",LF))||(Asc(LF)=123 && !Yaml_Map("","",LF))
Return 0
} else {
LF:=Trim(LF)
If (VQ)
LF:=SubStr(LF,2,StrLen(LF)-2),cObj[k]:=Yaml_UniChar(LF)
else If (!Yaml_SeqMap(cObj,k,LF))
cObj[k]:=Trim(LF)
}
}
Return (obj=""?(Quote Bracket=""):1)
}
Yaml_Incomplete(value){
return (Asc(Trim(value,"`n" A_Tab A_Space))=91 && !Yaml_Seq("","",Trim(value,"`n" A_Tab A_Space)))
|| (Asc(Trim(value,"`n" A_Tab A_Space))=123 && !Yaml_Map("","",Trim(value,"`n" A_Tab A_Space)))
}
Yaml_IsSeqMap(value){
return (Asc(Trim(value,"`n" A_Tab A_Space))=91 && Yaml_Seq("","",Trim(value,"`n" A_Tab A_Space)))
|| (Asc(Trim(value,"`n" A_Tab A_Space))=123 && Yaml_Map("","",Trim(value,"`n" A_Tab A_Space)))
}
Yaml(YamlText,IsFile=1,YamlObj=0){ ; Version 1.0.0.17 http://www.autohotkey.com/forum/viewtopic.php?t=70559
static
static base:={Dump:"Yaml_Dump",Save:"Yaml_Save",Add:"Yaml_Add",Merge:"Yaml_Merge",__Delete:"__Delete",_Insert:"_Insert",_Remove:"_Remove",_GetCapacity:"_GetCapacity",_SetCapacity:"_SetCapacity",_GetAddress:"_GetAddress",_MaxIndex:"_MaxIndex",_MinIndex:"_MinIndex",_NewEnum:"_NewEnum",_HasKey:"_HasKey",_Clone:"_Clone",Insert:"Insert",Remove:"Remove",GetCapacity:"GetCapacity",SetCapacity:"SetCapacity",GetAddress:"GetAddress",MaxIndex:"MaxIndex",MinIndex:"MinIndex",NewEnum:"NewEnum",HasKey:"HasKey",Clone:"Clone",base:{__Call:"Yaml_Call"}}
static BackupVars:="LVL,SEQ,KEY,SCA,TYP,VAL,CMT,LFL,CNT",IncompleteSeqMap
local maxLVL:=0,LastContObj:=0,LastContKEY:=0,LinesAdded:=0,_LVLChanged:=0,_LVL,_SEQ,_KEY,_SCA,_TYP,_VAL,_CMT,_LFL,_CNT,_NXT,__LVL,__SEQ,__KEY,__SCA,__TYP,__VAL,__CMT,__LFL,__CNT,__NXT
AutoTrim % ((AutoTrim:=A_AutoTrim)="On")?"Off":"Off"
LVL0:=pYaml:=YamlObj?YamlObj:Object("base",base),__LVL:=0,__LVL0:=0
If IsFile
FileRead,YamlText,%YamlText%
Loop,Parse,YamlText,`n,`r
{
If (!_CNT && (A_LoopField=""||RegExMatch(A_LoopField,"^\s+$"))){ ;&&__KEY=""&&__SEQ="")){
If ((OBJ:=LVL%__LVL%[""].MaxIndex())&&IsObject(LVL%__LVL%["",OBJ])&&__SEQ){
If (__KEY!="")
Yaml_Continue(LastContObj:=LVL%__LVL%["",Obj],LastContKEY:=__key,"",__SCA)
else Yaml_Continue(LastContObj:=LVL%__LVL%[""],LastContKEY:=Obj,"",__SCA,__SEQ)
} else If (__SEQ && OBJ){
Yaml_Continue(LastContObj:=LVL%__LVL%[""],LastContKEY:=OBJ,"",__SCA,__SEQ)
} else If (OBJ){
Yaml_Continue(LastContObj:=LVL%__LVL%[""],LastContKEY:=OBJ,"",__SCA,1)
} else if (__KEY!="")
Yaml_Continue(LastContObj:=LVL%__LVL%,LastContKEY:=__KEY,"",__SCA)
else LinesAdded--
LinesAdded++
Continue
} else If (!_CNT && LastContObj
&& ( RegExMatch(A_LoopField,"^(---)?\s*?(-\s)?("".+""\s*:\s|'.+'\s*:\s|[^:""'\{\[]+\s*:\s)")
|| RegExMatch(A_LoopField,"^(---)|\s*(-\s)") )){
If !__SCA
LastContObj[LastContKEY]:=SubStr(LastContObj[LastContKEY],1,-1*LinesAdded)
LastContObj:=0,LastContKEY:=0,LinesAdded:=0
}
If InStr(A_LoopField,"#"){
If (RegexMatch(A_LoopField,"^\s*#.*") || InStr(A_LoopField,"%YAML")=1) ;Comments only, do not parse
continue
else if Yaml_IsQuoted(LTrim(A_LoopField,"- ")) || RegExMatch(A_LoopField,"(---)?\s*?(-\s)?("".+""\s*:\s|'.+'\s*:\s|[^:""'\{\[]+\s*:\s)\s*([\|\>][+-]?)?\s*(!!\w+\s)?\s*("".+|'.+)$")&&!RegExMatch(A_LoopField,"[^\\]""\s+#")
LoopField:=A_LoopField
else if RegExMatch(A_LoopField,"\s+#.*$","",RegExMatch(A_LoopField,"(---)?\s*?(-\s)?("".+""\s*:\s|'.+'\s*:\s|[^:""'\{\[]+\s*:\s)?\s*([\|\>][+-]?)?\s*(!!\w+\s)?\s*("".+""|'.+')?\K")-1)
LoopField:=SubStr(A_LoopField,1,RegExMatch(A_LoopField,"\s+#.*$","",RegExMatch(A_LoopField,"(---)?\s*?(-\s)?("".+""\s*:\s|'.+'\s*:\s|[^:""'\{\[]+\s*:\s)?\s*([\|\>][+-]?)?\s*(!!\w+\s)?\s*("".+""|'.+')?\K")-1)-1)
else LoopField:=A_LoopField
} else LoopField:=A_LoopField
If _CNT {
If Yaml_IsSeqMap(RegExReplace(IncompleteSeqMap LoopField,"^(\s+)?(-\s)?("".+""\s*:\s|'.+'\s*:\s|[^:""'\{\[]+\s*:\s)?"))
LoopField:=IncompleteSeqMap LoopField,_CNT:=0,IncompleteSeqMap:=""
else {
IncompleteSeqMap.=LoopField
continue
}
}
If (LoopField="---"){
Loop % (maxLVL)
LVL%A_Index%:=""
Loop,Parse,BackupVars,`,
__%A_LoopField%:="",__%A_LoopField%0:=""
Loop,Parse,BackupVars,`,
Loop % maxLVL
__%A_LoopField%%A_Index%:=""
maxLVL:=0
__LVL:=0,__LVL0:=0
If !IsObject(pYaml[""])
pYaml[""]:=LVL0:=Object("base",base)
pYaml[""].Insert(LVL0:=Object("base",base))
Continue
} else if (LoopField="..."){
LVL0:=pYaml
Loop % maxLVL
LVL%A_Index%:=""
Loop,Parse,BackupVars,`,
__%A_LoopField%:="",__%A_LoopField%0:=""
Loop,Parse,BackupVars,`,
Loop % maxLVL
__%A_LoopField%%A_Index%:=""
maxLVL:=0
__LVL:=0,__LVL0:=0
Continue
}
If (SubStr(LoopField,0)=":")
LoopField.=A_Space ; add space to force RegEx to match even if the value and space after collon is missing e.g. Object:`n objects item
RegExMatch(LoopField,"S)^(?<LVL>\s+)?(?<SEQ>-\s)?(?<KEY>"".+""\s*:\s|'.+'\s*:\s|[^:""'\{\[]+\s*:\s)?\s*(?<SCA>[\|\>][+-]?)?\s*(?<TYP>!!\w+\s)?\s*(?<VAL>"".+""|'.+'|.+)?\s*$",_)
If _KEY ;cut off (:)
StringTrimRight,_KEY,_KEY,2
_KEY:=Yaml_UnQuoteIfNeed(_KEY)
If IsVal:=Yaml_IsQuoted(_VAL)
_VAL:=Yaml_UnQuoteIfNeed(_VAL)
;determine current level
_LVL:=Yaml_S2I(_LVL)
If _LVL-__LVL>1||(_LVL>__LVL&&_LVLChanged) ;&&!(__SEQ&&__KEY!=""&&_KEY!="")) ; (__SEQ?2:1)
{
Loop % (_LVLChanged?_LVL-_LVLChanged:_LVL-__LVL-1)
LoopField:=SubStr(LoopField,SubStr(LoopField,1,1)=A_Tab?1:2)
_LVL:=_LVLChanged?_LVLChanged:__LVL+1,_LVLChanged:=_LVLChanged?_LVLChanged:_LVL ;__LVL%_LVL%:=__LVL%_NXT% ; (__SEQ?2:1)
} else if _LVLChanged
_LVL:=_LVLChanged
else _LVLChanged:=0
If (maxLVL<_LVL)
maxLVL:=_LVL+(_SEQ?1:0)
; Cut off the leading tabs/spaces conform _LVL
SubStr:=0,Tabs:=0
Loop,Parse,LoopField
If (_LVL*2=SubStr || !SubStr:=SubStr+(A_LoopField=A_Tab?2:1)), Tabs:=Tabs+(A_LoopField=A_Tab?1:0)
break
_LFL:=SubStr(LoopField,SubStr-Tabs+1+(_SEQ?2:0))
_LFL:=Yaml_UnQuoteIfNeed(_LFL)
_NXT:=_LVL+1 ;next indentation level
__NXT:=_NXT+1
_PRV:=_LVL=0?0:_LVL-1
Loop,Parse,BackupVars,`,
__%A_LoopField%:=__%A_LoopField%%_PRV%
If RegExMatch(_LFL,"^-\s*$"){
_SEQ:="-",_KEY:="",_VAL:=""
}
If (!IsVal && !_CNT && (_CNT:=Yaml_Incomplete(Trim(_LFL))||Yaml_Incomplete(Trim(_VAL)))){
IncompleteSeqMap:=LoopField
continue
}
If (_LVL<__LVL){ ;Reset Objects and Backup vars
Loop % (maxLVL)
If (A_Index>_LVL){
Loop,Parse,BackupVars,`,
__%A_LoopField%%maxLVL%:=""
LVL%A_Index%:="",maxLVL:=maxLVL-1
}
If (_LVL=0 && !__LVL:=__LVL0:=0)
Loop,Parse,BackupVars,`,
__%A_LoopField%:="",__%A_LoopField%0:=""
}
If (_SEQ&&_LVL>__LVL&&(__VAL!=""||__SCA))
_SEQ:="",_KEY:="",_VAL:="",_LFL:="- " _LFL
If (__CNT)||(_LVL>__LVL&&(__KEY!=""&&_KEY="")&&(__VAL!=""||__SCA))||(__SEQ&&__SCA)
_KEY:="",_VAL:=""
If (__CNT||(_LVL>__LVL&&(__KEY!=""||(__SEQ&&(__LFL||__SCA)&&!Yaml_IsSeqMap(__LFL)))&&!(_SEQ||_KEY!=""))){
If ((OBJ:=LVL%__LVL%[""].MaxIndex())&&IsObject(LVL%__LVL%["",OBJ])&&__SEQ){
If __KEY!=
Yaml_Continue(LVL%__LVL%["",Obj],__key,_LFL,__SCA),__CNT:=Yaml_SeqMap(LVL%__LVL%["",OBJ],__KEY,LVL%__LVL%["",OBJ,__KEY])?"":__CNT
else Yaml_Continue(LVL%__LVL%[""],Obj,_LFL,__SCA,__SEQ),__CNT:=Yaml_SeqMap(LVL%__LVL%[""],OBJ,LVL%__LVL%["",OBJ],__SEQ)?"":__CNT
} else If (__SEQ && OBJ){
Yaml_Continue(LVL%__LVL%[""],Obj,_LFL,__SCA,__SEQ)
__CNT:=Yaml_SeqMap(LVL%__LVL%[""],OBJ,LVL%__LVL%["",OBJ],__SEQ)?"":__CNT
} else If (OBJ && __KEY=""){
Yaml_Continue(LVL%__LVL%[""],OBJ,_LFL,__SCA,1)
__CNT:=Yaml_SeqMap(LVL%__LVL%[""],OBJ,LVL%__LVL%["",OBJ],1)?"":__CNT
} else {
Yaml_Continue(LVL%__LVL%,__KEY,_LFL,__SCA)
__CNT:=Yaml_SeqMap(LVL%__LVL%,__KEY,LVL%__LVL%[__KEY])?"":__CNT
}
Continue
}
;Create sequence or map
If (__SEQ&&(_LVL>__LVL)&&_KEY!=""&&__KEY!=""){
OBJ:=LVL%__LVL%[""].MaxIndex()
If _SEQ {
If !Yaml_SeqMap(LVL%_LVL%["",OBJ,__KEY,""],_KEY,_VAL){
If !IsObject(LVL%__LVL%["",OBJ,__KEY,""])
LVL%__LVL%["",OBJ,__KEY,""]:={base:base}
LVL%__LVL%["",OBJ,__KEY,""].Insert({(_KEY):_VAL!=""?_VAL:(LVL%_NXT%:={base:base}),base:base})
}
} else If !Yaml_SeqMap(LVL%_LVL%["",OBJ],_KEY,_VAL){
LVL%__LVL%["",OBJ,_KEY]:=_VAL!=""?_VAL:(LVL%_NXT%:={base:base})
}
If _VAL!=
continue
} else If (_SEQ){
If !IsObject(LVL%_LVL%[""])
LVL%_LVL%[""]:=Object("base",base)
While (SubStr(_LFL,1,2)="- "){
_LFL:=SubStr(_LFL,3),_KEY:=(_KEY!="")?_LFL:=SubStr(_KEY,3):_KEY,LVL%_LVL%[""].Insert(LVL%_NXT%:=Object("",Object("base",base),"base",base)),_LVL:=_LVL+1,_NXT:=_NXT+1,__NXT:=_NXT+1,_PRV:=_LVL-1,maxLVL:=(maxLVL<_LVL)?_LVL:maxLVL
Loop,Parse,BackupVars,`,
__%A_LoopField%:=_%A_LoopField%
,__%A_LoopField%%_PRV%:=_%A_LoopField%
}
If (_KEY="" && _VAL="" && !IsVal){
If !Yaml_SeqMap(LVL%_LVL%[""],"",_LFL)
LVL%_LVL%[""].Insert(LVL%_NXT%:=Object("base",base))
} else If (_KEY!="") {
LVL%_LVL%[""].Insert(LVL%__NXT%:=Object(_KEY,LVL%_NXT%:=Object("base",base),"base",base))
If !Yaml_SeqMap(LVL%__NXT%,_KEY,_VAL){
LVL%_LVL%[""].Remove()
LVL%_LVL%[""].Insert(LVL%__NXT%:=Object(_KEY,(_VAL!=""||IsVal)?_VAL:LVL%_NXT%:=Object("base",base),"base",base))
}
} else {
If !Yaml_SeqMap(LVL%_LVL%[""],"",_LFL)
LVL%_LVL%[""].Insert(_LFL)
}
If !LVL%_LVL%[""].MaxIndex()
LVL%_LVL%.Remove("")
} else if (_KEY!=""){
If (__SEQ && _LVL>__LVL) {
If (OBJ:=LVL%_PRV%[""].MaxIndex())&&IsObject(LVL%_PRV%["",OBJ]){
If !Yaml_SeqMap(LVL%_PRV%["",OBJ],_KEY,_VAL)
LVL%_PRV%["",OBJ,_KEY]:=(_VAL!=""||IsVal)?_VAL:(LVL%_NXT%:=Object("base",base))
} else {
LVL%_PRV%[""].Insert(Object(_KEY,(_VAL!=""||IsVal)?_VAL:(LVL%_NXT%:=Object("base",base)),"base",base))
Yaml_SeqMap(LVL%_PRV%["",OBJ?OBJ+1:1],_KEY,_VAL)
}
} else
If !Yaml_SeqMap(LVL%_LVL%,_KEY,_VAL)
LVL%_LVL%[_KEY]:=_VAL!=""?_VAL:(LVL%_NXT%:=Object("base",base))
} else if (_LVL>__LVL && (__KEY!="")) {
If (__VAL!="" || __SCA){
Yaml_Continue(LVL%__LVL%,__KEY,_LFL,__SCA)
Yaml_SeqMap(LVL%__LVL%,__KEY,LVL%__LVL%[__KEY])
Continue
} else {
If !Yaml_SeqMap(LVL%__LVL%[__KEY],_KEY,_VAL) ;!!! no Scalar???
LVL%__LVL%[__KEY,_KEY]:=_VAL
Continue
}
} else {
If (_LVL>__LVL&&(OBJ:=LVL%__LVL%[""].MaxIndex())&&IsObject(LVL%__LVL%["",OBJ])&&__SEQ){
If __CNT
Yaml_Continue(LVL%__LVL%[""],LVL%__LVL%[""].MaxIndex(),_LFL,__SCA,1)
If (__CNT:=Yaml_SeqMap(LVL%__LVL%[""],"",_LFL)?"":1)
LVL%__LVL%[""].Insert(_LFL)
} else {
If !IsObject(LVL%_LVL%[""])
LVL%_LVL%[""]:=Object("base",base)
If __CNT
Yaml_Continue(LVL%__LVL%[""],LVL%__LVL%[""].MaxIndex(),_LFL,__SCA,1)
If (__CNT:=Yaml_SeqMap(LVL%_LVL%[""],"",_LFL)?"":1)
LVL%_LVL%[""].Insert(_LFL)
}
Continue
}
Loop,Parse,BackupVars,`,
__%A_LoopField%:=_%A_LoopField%
,__%A_LoopField%%_LVL%:=_%A_LoopField%
}
If (LastContObj && !__SCA)
LastContObj[LastContKEY]:=SubStr(LastContObj[LastContKEY],1,-1*LinesAdded)
AutoTrim %AutoTrim%
Loop,Parse,BackupVars,`,
If !(__%A_LoopField%:="")
Loop % maxLVL
__%A_LoopField%%A_Index%:=""
Return pYaml,pYaml.base:=base
}
Yaml_Save(obj,file,level=""){
FileMove,% file,% file ".bakupyml",1
FileAppend,% obj.Dump(),% file
If !ErrorLevel
FileDelete,% file ".bakupyml"
else {
FileMove,% file ".bakupyml",% file
MsgBox,0, Error creating file, old file was restored.
}
}
Yaml_Call(NotSupported,f,p*){
If (p.MaxIndex()>1){
Loop % p.MaxIndex()
If A_Index>1
f:=f[""][p[A_Index-1]]
}
Return (!p.MaxIndex()?f[""].MaxIndex():f[""][p[p.MaxIndex()]])
}
Yaml_Merge(obj,merge){
for k,v in merge
{
If IsObject(v){
If obj.HasKey(k){
If IsObject(obj[k])
Yaml_Merge(obj[k],v)
else obj[k]:=v
} else obj[k]:=v
} else obj[k]:=v
}
}
Yaml_Add(O,Yaml="",IsFile=0){
static base:={Dump:"Yaml_Dump",Save:"Yaml_Save",Add:"Yaml_Add",Merge:"Yaml_Merge",__Delete:"__Delete",_Insert:"_Insert",_Remove:"_Remove",_GetCapacity:"_GetCapacity",_SetCapacity:"_SetCapacity",_GetAddress:"_GetAddress",_MaxIndex:"_MaxIndex",_MinIndex:"_MinIndex",_NewEnum:"_NewEnum",_HasKey:"_HasKey",_Clone:"_Clone",Insert:"Insert",Remove:"Remove",GetCapacity:"GetCapacity",SetCapacity:"SetCapacity",GetAddress:"GetAddress",MaxIndex:"MaxIndex",MinIndex:"MinIndex",NewEnum:"NewEnum",HasKey:"HasKey",Clone:"Clone",base:{__Call:"Yaml_Call"}}
If Yaml_IsSeqMap(Trim(Yaml)){
If !IsObject(O[""])
O[""]:=Object("base",base)
Yaml_SeqMap(O[""],"",Yaml)
} else Yaml(Yaml,IsFile,O)
}
Yaml_Dump(O,J="",R=0,Q=0){
static M1:="{",M2:="}",S1:="[",S2:="]",N:="`n",C:=", ",S:="- ",E:="",K:=": "
local dump:="",M,MX,F,I,key,value
If (J=0&&!R)
dump.= S1
for key in O
M:=A_Index
If IsObject(O[""]){
M--
for key in O[""]
MX:=A_Index
If IsObject(O[""][""])
MX--
If O[""].MaxIndex()
for key, value in O[""]
{
If key=
continue
I++
F:=IsObject(value)?(IsObject(value[""])?"S":"M"):E
If (J!=""&&J<=R){
dump.=(F?(%F%1 Yaml_Dump(value,J,R+1,F) %F%2):Yaml_EscIfNeed(value)) (I=MX&&!M?E:C) ;(Q="S"&&I=1?S1:E)(Q="S"&&I=MX?S2:E)
} else if F,dump:=dump N Yaml_I2S(R) S
dump.= (J!=""&&J<=(R+1)?%F%1:E) Yaml_Dump(value,J,R+1,F) (J!=""&&J<=(R+1)?%F%2:E)
else {
; If RegexMatch(value,"[\x{007F}-\x{FFFF}""\{\[']|:\s|\s#")
dump .= Yaml_EscIfNeed(value)
; else {
; value:= (value=""?"''":RegExReplace(RegExReplace(Value,"m)^(.*[\r\n].*)$","|" (SubStr(value,-1)="`n`n"?"+":SubStr(value,0)=N?"":"-") "`n$1"),"ms)(*ANYCRLF)\R",N Yaml_I2S(R+1)))
; StringReplace,value,value,% N Yaml_I2S(R+1) N Yaml_I2S(R+1),% N Yaml_I2S(R+1),A
; dump.=value
; }
}
}
}
I=0
for key, value in O
{
If key=
continue
I++
F:=IsObject(value)?(IsObject(value[""])?"S":"M"):E
If (J=0&&!R)
dump.= M1
If (J!=""&&J<=R){
dump.=(Q="S"&&I=1?M1:E) Yaml_EscIfNeed(key) K
dump.=F?(%F%1 Yaml_Dump(value,J,R+1,F) %F%2):Yaml_EscIfNeed(value)
dump.=(Q="S"&&I=M?M2:E) (J!=0||R?(I=M?E:C):E)
} else if F,dump:=dump N Yaml_I2S(R) Yaml_EscIfNeed(key) K
dump.= (J!=""&&J<=(R+1)?%F%1:E) Yaml_Dump(value,J,R+1,F) (J!=""&&J<=(R+1)?%F%2:E)
else {
; If RegexMatch(value,"[\x{007F}-\x{FFFF}""\{\['\t]|:\s|\s#")
dump .= Yaml_EscIfNeed(value)
; else {
; value:= (value=""?"''":RegExReplace(RegExReplace(Value,"m)^(.*[\r\n].*)$","|" (SubStr(value,-1)="`n`n"?"+":SubStr(value,0)="`n"?"":"-") "`n$1"),"ms)(*ANYCRLF)\R","`n" Yaml_I2S(R+1)))
; StringReplace,value,value,% "`n" Yaml_I2S(R+1) "`n" Yaml_I2S(R+1),% "`n" Yaml_I2S(R+1),A
; dump.= value
; }
}
If (J=0&&!R){
dump.=M2 (I<M?C:E)
}
}
If (J=0&&!R)
dump.=S2
If (R=0)
dump:=RegExReplace(dump,"^\R+")
Return dump
}
Yaml_UniChar( string ) {
static a:="`a",b:="`b",t:="`t",n:="`n",v:="`v",f:="`f",r:="`r",e:=Chr(0x1B)
Loop,Parse,string,\
{
If (A_Index=1){
var.=A_LoopField
continue
} else If lastempty {
var.="\" A_LoopField
lastempty:=0
Continue
} else if (A_LoopField=""){
lastempty:=1
Continue
}
If InStr("ux",SubStr(A_LoopField,1,1))
str:=SubStr(A_LoopField,1,RegExMatch(A_LoopField,"^[ux]?([\dA-F]{4})?([\dA-F]{2})?\K")-1)
else
str:=SubStr(A_LoopField,1,1)
If (str=="N")
str:="\x85"
else if (str=="P")
str:="\x2029"
else if (str=0)
str:="\x0"
else if (str=="L")
str:="\x2028"
else if (str=="_")
str:="\xA0"
If RegexMatch(str,"i)^[ux][\da-f]+$")
var.=Chr(Abs("0x" SubStr(str,2)))
else If str in a,b,t,n,v,f,r,e
var.=%str%
else var.=str
If InStr("ux",SubStr(A_LoopField,1,1))
var.=SubStr(A_LoopField,RegExMatch(A_LoopField,"^[ux]?([\dA-F]{4})?([\dA-F]{2})?\K"))
else var.=SubStr(A_LoopField,2)
}
return var
}
Yaml_CharUni( string ) {
static ascii:={"\":"\","`a": "a","`b": "b","`t": "t","`n": "n","`v": "v","`f": "f","`r": "r",Chr(0x1B): "e","""": """",Chr(0x85): "N",Chr(0x2029): "P",Chr(0x2028): "L","": "0",Chr(0xA0): "_"}
If !RegexMatch(string,"[\x{007F}-\x{FFFF}]"){
Loop,Parse,string
{
If ascii[A_LoopField]
var.="\" ascii[A_LoopField]
else
var.=A_LoopField
}
return var
}
format:=A_FormatInteger
SetFormat,Integer,H
Loop,Parse,string
{
If ascii[A_LoopField]
var.="\" ascii[A_LoopField]
else if Asc(A_LoopField)<128
var.=A_LoopField
else {
str:=SubStr(Asc(A_LoopField),3)
var.="\u" (StrLen(str)<2?"000":StrLen(str)<3?"00":StrLen(str)<4?"0":"") str
}
}
SetFormat,Integer,%Format%
return var
}
Yaml_EscIfNeed(s){
If (s="")
return "''"
else If RegExMatch(s,"m)[\{\[""'\r\n]|:\s|,\s|\s#")||RegExMatch(s,"^[\s#\\\-:>]")||RegExMatch(s,"m)\s$")||RegExMatch(s,"m)[\x{7F}-\x{7FFFFFFF}]")
return ("""" . Yaml_CharUni(s) . """")
else return s
}
Yaml_IsQuoted(ByRef s){
return InStr(".''."""".","." SubStr(Trim(s),1,1) SubStr(Trim(s),0) ".")?1:0
}
Yaml_UnQuoteIfNeed(s){
s:=Trim(s)
If !(SubStr(s,1,1)=""""&&SubStr(s,0)="""")
return (SubStr(s,1,1)="'"&&SubStr(s,0)="'")?SubStr(s,2,StrLen(s)-2):s
else return Yaml_UniChar(SubStr(s,2,StrLen(s)-2))
}
Yaml_S2I(str){
local idx:=0
Loop,Parse,str
If (A_LoopField=A_Tab)
idx++
else if !Mod(A_index,2)
idx++
Return idx
}
Yaml_I2S(idx){
Loop % idx
str .= " "
Return str
}
Yaml_Continue(Obj,key,value,scalar="",isval=0){
If !IsObject(isObj:=obj[key])
v:=isObj
If scalar {
StringTrimLeft,scaopt,scalar,1
scalar:=Asc(scalar)=124?"`n":" "
} else scalar:=" ",scaopt:="-"
temp := (value=""?"`n":(SubStr(v,0)="`n"&&scalar="`n"?"":(v=""?"":scalar))) value (scaopt!="-"?(v&&value=""?"`n":""):"")
obj[key]:=Yaml_UnQuoteIfNeed(v temp)
}
Yaml_Quote(ByRef L,F,Q,B,ByRef E){
Return (F="\"&&!E&&(E:=1))||(E&&!(E:=0)&&(L:=L ("\" F)))
}
Yaml_SeqMap(o,k,v,isVal=0){
v:=Trim(v,A_Tab A_Space "`n"),m:=SubStr(v,1,1) SubStr(v,0)
If Yaml_IsSeqMap(v)
return m="[]"?Yaml_Seq(o,k,SubStr(v,2,StrLen(v)-2),isVal):m="{}"?Yaml_Map(o,k,SubStr(v,2,StrLen(v)-2),isVal):0
}
Yaml_Seq(obj,key,value,isVal=0){
static base:={Dump:"Yaml_Dump",Save:"Yaml_Save",Add:"Yaml_Add",Merge:"Yaml_Merge",__Delete:"__Delete",_Insert:"_Insert",_Remove:"_Remove",_GetCapacity:"_GetCapacity",_SetCapacity:"_SetCapacity",_GetAddress:"_GetAddress",_MaxIndex:"_MaxIndex",_MinIndex:"_MinIndex",_NewEnum:"_NewEnum",_HasKey:"_HasKey",_Clone:"_Clone",Insert:"Insert",Remove:"Remove",GetCapacity:"GetCapacity",SetCapacity:"SetCapacity",GetAddress:"GetAddress",MaxIndex:"MaxIndex",MinIndex:"MinIndex",NewEnum:"NewEnum",HasKey:"HasKey",Clone:"Clone",base:{__Call:"Yaml_Call"}}
ContinueNext:=0
If (obj=""){
If (SubStr(value,0)!="]")
Return 0
else
value:=SubStr(value,2,StrLen(value)-2)
} else {
If (key=""){
obj.Insert(Object("",cObj:=Object("base",base),"base",base))
} else if (isval && IsObject(obj[key,""])){
cObj:=obj[key,""]
} else obj[key]:=Object("",cObj:=Object("base",base),"base",base)
}
Count:=StrLen(value)
Loop,Parse,value
{
If ((Quote=""""&&Yaml_Quote(LF,A_LoopField,Quote,Bracket,Escape)) || (ContinueNext && !ContinueNext:=0))
Continue
If (Quote){
If (A_LoopField=Quote){
Quote=
If Bracket
LF.= A_LoopField
else LF:=SubStr(LF,2)
Continue
}
LF .= A_LoopField
continue
} else if (!Quote&&InStr("""'",A_LoopField)){
Quote:=A_LoopField
If !Bracket
VQ:=Quote
LF.=A_LoopField
Continue
} else if (!Quote&&Bracket){
If (Asc(A_LoopField)=Asc(Bracket)+2)
BCount--
else if (A_LoopField=Bracket)
BCount++
If (BCount=0)
Bracket=
LF .= A_LoopField
Continue
} else if (!Quote&&!Bracket&&InStr("[{",A_LoopField)){
Bracket:=A_LoopField
BCount:=1
LF.=A_LoopField
Continue
}
If (A_Index=Count)
LF .= A_LoopField
else if (!Quote&&!Bracket&&A_LoopField=","&&(!InStr("0123456789",SubStr(value,A_Index-1,1)) | !InStr("0123456789",SubStr(value,A_Index+1,1)))){
ContinueNext:=SubStr(value,A_Index+1,1)=A_Space||SubStr(value,A_Index+1,1)=A_Tab
LF:=LF
} else {
LF .= A_LoopField
continue
}
If (obj=""){
If !VQ
If (Asc(LF)=91 && !Yaml_Seq("","",LF))
||(Asc(LF)=123 && !Yaml_Map("","",LF))
Return 0
} else {
If (VQ || !Yaml_SeqMap(cObj,"",LF))
cObj.Insert(VQ?Yaml_UniChar(LF):Trim(LF))
}
LF:="",VQ:=""
}
If (LF){
If (obj=""){
If !VQ
If (Asc(LF)=91 && !Yaml_Seq("","",LF))||(Asc(LF)=123 && !Yaml_Map("","",LF))
Return 0
} else If (VQ || !Yaml_SeqMap(cObj,"",LF))
cObj.Insert(VQ?Yaml_UniChar(LF):Trim(LF))
}
Return (obj=""?(Quote Bracket=""):1)
}
Yaml_Map(obj,key,value,isVal=0){
static base:={Dump:"Yaml_Dump",Save:"Yaml_Save",Add:"Yaml_Add",Merge:"Yaml_Merge",__Delete:"__Delete",_Insert:"_Insert",_Remove:"_Remove",_GetCapacity:"_GetCapacity",_SetCapacity:"_SetCapacity",_GetAddress:"_GetAddress",_MaxIndex:"_MaxIndex",_MinIndex:"_MinIndex",_NewEnum:"_NewEnum",_HasKey:"_HasKey",_Clone:"_Clone",Insert:"Insert",Remove:"Remove",GetCapacity:"GetCapacity",SetCapacity:"SetCapacity",GetAddress:"GetAddress",MaxIndex:"MaxIndex",MinIndex:"MinIndex",NewEnum:"NewEnum",HasKey:"HasKey",Clone:"Clone",base:{__Call:"Yaml_Call"}}
ContinueNext:=0
If (obj=""){
If (SubStr(value,0)!="}")
Return 0
else
value:=SubStr(value,2,StrLen(value)-2)
} else {
If (key="")
obj.Insert(cObj:=Object("base",base))
else obj[key]:=(cObj:=Object("base",base))
}
Count:=StrLen(value)
Loop,Parse,value
{
If ((Quote=""""&&Yaml_Quote(LF,A_LoopField,Quote,Bracket,Escape)) || (ContinueNext && !ContinueNext:=0))
Continue
If (Quote){
If (A_LoopField=Quote){
Quote=
LF.=A_LoopField
} else LF .= A_LoopField
continue
} else if (!Quote&&(k=""||v="")&&InStr("""'",A_LoopField)){
Quote:=A_LoopField
If (k && !Bracket)
VQ:=Quote
else if !Bracket
KQ:=Quote
LF.=Quote
Continue
} else If (k!=""&&LF=""&&InStr("`n`r `t",A_LoopField)){
Continue
}
If (!Quote&&Bracket){
If (Asc(A_LoopField)=Asc(Bracket)+2)
BCount--
else if (A_LoopField=Bracket)
BCount++
If (BCount=0)
Bracket=
LF .= A_LoopField
Continue
} else if (!Quote&&!Bracket&&InStr("[{",A_LoopField)){
Bracket:=A_LoopField
BCount=1
LF.=A_LoopField
Continue
}
If (A_Index=Count&&k!=""){
v:=LF A_LoopField
v:=Trim(v)
If (InStr("""'",SubStr(v,0))&&SubStr(v,1,1)=SubStr(v,0))
v:=SubStr(v,2,StrLen(v)-2)
} else If (!Quote&&!Bracket&&k!=""&&A_LoopField=","&&SubStr(value,A_Index+1,1)=A_Space){
ContinueNext:=1
LF:=Trim(LF)
If VQ
LF:=SubStr(LF,2,StrLen(LF)-2)
v:=LF,LF:=""
} else if (!Quote&&!Bracket&&k=""&&A_LoopField=":"){
LF:=Trim(LF)
If (InStr("""'",SubStr(LF,0))&&SubStr(LF,1,1)=SubStr(LF,0))
LF:=SubStr(LF,2,StrLen(LF)-2)
k:=LF,LF:=""
continue
} else {
LF .= A_LoopField
continue
}
If (obj=""){
If VQ=
If (Asc(v)=91 && !Yaml_Seq("","",v))
||(Asc(v)=123 && !Yaml_Map("","",v))
Return 0
} else {
If (VQ || !Yaml_SeqMap(cObj,k,v))
cObj[KQ?Yaml_UniChar(k):k]:=(VQ?Yaml_UniChar(v):Trim(v))
}
k:="",v:="",VQ:="",KQ:=""
}
If (k){
If (obj=""){
If (Asc(LF)=91 && !Yaml_Seq("","",LF))||(Asc(LF)=123 && !Yaml_Map("","",LF))
Return 0
} else {
LF:=Trim(LF)
If (VQ)
LF:=SubStr(LF,2,StrLen(LF)-2),cObj[k]:=Yaml_UniChar(LF)
else If (!Yaml_SeqMap(cObj,k,LF))
cObj[k]:=Trim(LF)
}
}
Return (obj=""?(Quote Bracket=""):1)
}
Yaml_Incomplete(value){
return (Asc(Trim(value,"`n" A_Tab A_Space))=91 && !Yaml_Seq("","",Trim(value,"`n" A_Tab A_Space)))
|| (Asc(Trim(value,"`n" A_Tab A_Space))=123 && !Yaml_Map("","",Trim(value,"`n" A_Tab A_Space)))
}
Yaml_IsSeqMap(value){
return (Asc(Trim(value,"`n" A_Tab A_Space))=91 && Yaml_Seq("","",Trim(value,"`n" A_Tab A_Space)))
|| (Asc(Trim(value,"`n" A_Tab A_Space))=123 && Yaml_Map("","",Trim(value,"`n" A_Tab A_Space)))
}
声明:站内资源为整理优化好的代码上传分享与学习研究,如果是开源代码基本都会标明出处,方便大家扩展学习路径。请不要恶意搬运,破坏站长辛苦整理维护的劳动成果。本站为爱好者分享站点,所有内容不作为商业行为。如若本站上传内容侵犯了原著者的合法权益,请联系我们进行删除下架。
评论(0)