class MyJSONError < StandardError; end
# - - - - - - - - - - -
def is_space_char(text, ptr = 0)
!!(text[ptr]=~/^\s/)
end
def is_digit_char(text, ptr = 0)
!!(text[ptr]=~/^[0-9]/)
end
# - - - - - - - - - - -
def json_parse_true(text, ptr = 0)
if text[ptr..(ptr+3)] == 'true'
return [true, ptr+4]
else
raise MyJSONError.new("invalid keyword at #{ptr}")
end
end
def json_parse_false(text, ptr = 0)
if text[ptr..(ptr+4)] == 'false'
return [false, ptr+5]
else
raise MyJSONError.new("invalid keyword at #{ptr}")
end
end
def json_parse_null(text, ptr = 0)
if text[ptr..(ptr+3)] == 'null'
return [nil, ptr+4]
else
raise MyJSONError.new("invalid keyword at #{ptr}")
end
end
def json_parse_string(text, ptr = 0)
abort "json_parse_string" if text[ptr] != '"'
ptr += 1
state = :string
str = ""
hex4 = ""
while text[ptr]
if state == :string
if text[ptr] == '"'
return [str, ptr+1]
elsif text[ptr] == "\\"
state = :escape
ptr += 1
else
str << text[ptr]
ptr += 1
end
elsif state == :escape
if text[ptr] == '"'
str << '"'; state = :string; ptr += 1
elsif text[ptr] == "\\"
str << "\\"; state = :string; ptr += 1
elsif text[ptr] == "/"
str << "/"; state = :string; ptr += 1
elsif text[ptr] == "b"
str << "\b"; state = :string; ptr += 1
elsif text[ptr] == "f"
str << "\f"; state = :string; ptr += 1
elsif text[ptr] == "n"
str << "\n"; state = :string; ptr += 1
elsif text[ptr] == "r"
str << "\r"; state = :string; ptr += 1
elsif text[ptr] == "t"
str << "\t"; state = :string; ptr += 1
elsif text[ptr] == "u"
hex4 = ""; state = :hexadec; ptr += 1
end
elsif state == :hexadec
hex4 << text[ptr]
if hex4.size == 4
str << [hex4.to_i(16)].pack("U")
state = :string
end
ptr += 1
end
end
raise MyJSONError.new("invalid 4 hexadecimal digits at #{ptr}") if state == :hexadec
raise MyJSONError.new("not found '\"' at #{ptr}")
# メモ:シングルクオートはエスケープしないが,
# エディタがエスケープするので'\'ではなく"\\"に...
end
def json_parse_number(text, ptr = 0)
sgn = 1
val = 0
if text[ptr] == '-'
sgn = -1
ptr += 1
end
while is_digit_char(text, ptr)
val = val*10 + text[ptr].to_i
ptr += 1
end
return [sgn*val, ptr]
end
def json_parse_array(text, ptr = 0)
abort "json_parse_array" if text[ptr] != '['
ptr += 1
arr = []
state = :initial
while text[ptr]
if is_space_char(text, ptr)
ptr += 1
elsif text[ptr] == ']'
raise MyJSONError.new("invalid ',' at #{ptr}") if state != :initial && state != :value
return [arr, ptr+1]
elsif text[ptr] == ','
raise MyJSONError.new("invalid ',' at #{ptr}") if state != :value
state = :comma
ptr += 1
else
v, ptr = json_parse(text, ptr)
arr << v
state = :value
end
end
raise MyJSONError.new("not found ']' at #{ptr}")
end
def json_parse_object(text, ptr = 0)
abort "json_parse_object" if text[ptr] != '{'
ptr += 1
hash = {}
key = nil
state = :initial
while text[ptr]
if is_space_char(text, ptr)
ptr += 1
elsif text[ptr] == '}'
raise MyJSONError.new("invalid ',' at #{ptr}") if state != :initial && state != :value
return [hash, ptr+1]
elsif text[ptr] == ','
raise MyJSONError.new("invalid ',' at #{ptr}") if state != :value
state = :comma
ptr += 1
elsif text[ptr] == ':'
raise MyJSONError.new("invalid ':' at #{ptr}") if state != :key
state = :colon
ptr += 1
elsif text[ptr] == '"' && (state == :comma || state == :initial)
key, ptr = json_parse(text, ptr)
state = :key
else
val, ptr = json_parse(text, ptr)
hash[key] = val
state = :value
end
end
raise MyJSONError.new("not found '}' at #{ptr}")
end
def json_parse(text, ptr = 0)
while text[ptr]
if is_space_char(text, ptr)
ptr += 1
elsif text[ptr] == 't'
return json_parse_true(text, ptr)
elsif text[ptr] == 'f'
return json_parse_false(text, ptr)
elsif text[ptr] == 'n'
return json_parse_null(text, ptr)
elsif text[ptr] == '"'
return json_parse_string(text, ptr)
elsif text[ptr] == '-'
return json_parse_number(text, ptr)
elsif is_digit_char(text, ptr)
return json_parse_number(text, ptr)
elsif text[ptr] == '['
return json_parse_array(text, ptr)
elsif text[ptr] == '{'
return json_parse_object(text, ptr)
else
raise MyJSONError.new("invalid at #{ptr}")
end
end
end
# - - - - - - - - - - -
def test_sub
abort "is_space_char" unless is_space_char(" ") == true
abort "is_space_char" unless is_space_char("t") == false
end
test_sub
def test_main
abort "failed: true" unless json_parse('true')[0] == true
abort "failed: false" unless json_parse('false')[0] == false
abort "failed: null" unless json_parse('null')[0] == nil
abort "failed: string" unless json_parse('"str"')[0] == 'str'
abort "failed: escape" unless json_parse('"foo\nbar"')[0] == "foo\nbar"
abort "failed: hexadecimal" unless json_parse('"\u7D05\u7389"')[0] == "紅玉"
abort "failed: number" unless json_parse('1234567890')[0] == 1234567890
abort "failed: negative number" unless json_parse('-1')[0] == -1
abort "failed: array 1" unless json_parse('[1,2,3]')[0] == [1,2,3]
abort "failed: array 2" unless json_parse('[1,"foo",null]')[0] == [1,'foo',nil]
abort "failed: matrix" unless json_parse('[[1,2],[3,4],[5,6]]')[0] == [[1,2],[3,4],[5,6]]
abort "failed: russian array" unless json_parse('[0,[1,[2,[3,[4]]]]]')[0] == [0,[1,[2,[3,[4]]]]]
abort "failed: object 1" unless json_parse('{"key":"val"}')[0] == {"key"=>"val"}
abort "failed: object 2" unless json_parse('{"a":null,"b":[1,2],"c":true,"d":{"x":"\t"}}')[0] == {"a"=>nil,"b"=>[1,2],"c"=>true,"d"=>{"x"=>"\t"}}
end
test_main
Y2xhc3MgTXlKU09ORXJyb3IgPCBTdGFuZGFyZEVycm9yOyBlbmQKICAgIAojIC0gLSAtIC0gLSAtIC0gLSAtIC0gLQoKZGVmIGlzX3NwYWNlX2NoYXIodGV4dCwgcHRyID0gMCkKICAgICEhKHRleHRbcHRyXT1+L15ccy8pCmVuZAoKZGVmIGlzX2RpZ2l0X2NoYXIodGV4dCwgcHRyID0gMCkKICAgICEhKHRleHRbcHRyXT1+L15bMC05XS8pCmVuZAoKIyAtIC0gLSAtIC0gLSAtIC0gLSAtIC0KCmRlZiBqc29uX3BhcnNlX3RydWUodGV4dCwgcHRyID0gMCkKICAgIGlmIHRleHRbcHRyLi4ocHRyKzMpXSA9PSAndHJ1ZScKICAgICAgICByZXR1cm4gW3RydWUsIHB0cis0XQogICAgZWxzZQogICAgICAgIHJhaXNlIE15SlNPTkVycm9yLm5ldygiaW52YWxpZCBrZXl3b3JkIGF0ICN7cHRyfSIpCiAgICBlbmQKZW5kCgpkZWYganNvbl9wYXJzZV9mYWxzZSh0ZXh0LCBwdHIgPSAwKQogICAgaWYgdGV4dFtwdHIuLihwdHIrNCldID09ICdmYWxzZScKICAgICAgICByZXR1cm4gW2ZhbHNlLCBwdHIrNV0KICAgIGVsc2UKICAgICAgICByYWlzZSBNeUpTT05FcnJvci5uZXcoImludmFsaWQga2V5d29yZCBhdCAje3B0cn0iKQogICAgZW5kCmVuZAoKZGVmIGpzb25fcGFyc2VfbnVsbCh0ZXh0LCBwdHIgPSAwKQogICAgaWYgdGV4dFtwdHIuLihwdHIrMyldID09ICdudWxsJwogICAgICAgIHJldHVybiBbbmlsLCBwdHIrNF0KICAgIGVsc2UKICAgICAgICByYWlzZSBNeUpTT05FcnJvci5uZXcoImludmFsaWQga2V5d29yZCBhdCAje3B0cn0iKQogICAgZW5kCmVuZAoKZGVmIGpzb25fcGFyc2Vfc3RyaW5nKHRleHQsIHB0ciA9IDApCiAgICBhYm9ydCAianNvbl9wYXJzZV9zdHJpbmciIGlmIHRleHRbcHRyXSAhPSAnIicKICAgIHB0ciArPSAxCiAgICBzdGF0ZSA9IDpzdHJpbmcKICAgIHN0ciA9ICIiCiAgICBoZXg0ID0gIiIKICAgIHdoaWxlIHRleHRbcHRyXQogICAgICAgIGlmIHN0YXRlID09IDpzdHJpbmcKICAgICAgICAgICAgaWYgdGV4dFtwdHJdID09ICciJwogICAgICAgICAgICAgICAgcmV0dXJuIFtzdHIsIHB0cisxXQogICAgICAgICAgICBlbHNpZiB0ZXh0W3B0cl0gPT0gIlxcIiAKICAgICAgICAgICAgICAgIHN0YXRlID0gOmVzY2FwZQogICAgICAgICAgICAgICAgcHRyICs9IDEKICAgICAgICAgICAgZWxzZQogICAgICAgICAgICAgICAgc3RyIDw8IHRleHRbcHRyXQogICAgICAgICAgICAgICAgcHRyICs9IDEKICAgICAgICAgICAgZW5kCiAgICAgICAgZWxzaWYgc3RhdGUgPT0gOmVzY2FwZQogICAgICAgICAgICBpZiB0ZXh0W3B0cl0gPT0gJyInCiAgICAgICAgICAgICAgICBzdHIgPDwgJyInOyBzdGF0ZSA9IDpzdHJpbmc7IHB0ciArPSAxCiAgICAgICAgICAgIGVsc2lmIHRleHRbcHRyXSA9PSAiXFwiCiAgICAgICAgICAgICAgICBzdHIgPDwgIlxcIjsgc3RhdGUgPSA6c3RyaW5nOyBwdHIgKz0gMQogICAgICAgICAgICBlbHNpZiB0ZXh0W3B0cl0gPT0gIi8iCiAgICAgICAgICAgICAgICBzdHIgPDwgIi8iOyBzdGF0ZSA9IDpzdHJpbmc7IHB0ciArPSAxCiAgICAgICAgICAgIGVsc2lmIHRleHRbcHRyXSA9PSAiYiIKICAgICAgICAgICAgICAgIHN0ciA8PCAiXGIiOyBzdGF0ZSA9IDpzdHJpbmc7IHB0ciArPSAxCiAgICAgICAgICAgIGVsc2lmIHRleHRbcHRyXSA9PSAiZiIKICAgICAgICAgICAgICAgIHN0ciA8PCAiXGYiOyBzdGF0ZSA9IDpzdHJpbmc7IHB0ciArPSAxCiAgICAgICAgICAgIGVsc2lmIHRleHRbcHRyXSA9PSAibiIKICAgICAgICAgICAgICAgIHN0ciA8PCAiXG4iOyBzdGF0ZSA9IDpzdHJpbmc7IHB0ciArPSAxCiAgICAgICAgICAgIGVsc2lmIHRleHRbcHRyXSA9PSAiciIKICAgICAgICAgICAgICAgIHN0ciA8PCAiXHIiOyBzdGF0ZSA9IDpzdHJpbmc7IHB0ciArPSAxCiAgICAgICAgICAgIGVsc2lmIHRleHRbcHRyXSA9PSAidCIKICAgICAgICAgICAgICAgIHN0ciA8PCAiXHQiOyBzdGF0ZSA9IDpzdHJpbmc7IHB0ciArPSAxCiAgICAgICAgICAgIGVsc2lmIHRleHRbcHRyXSA9PSAidSIKICAgICAgICAgICAgICAgIGhleDQgPSAiIjsgc3RhdGUgPSA6aGV4YWRlYzsgcHRyICs9IDEKICAgICAgICAgICAgZW5kCiAgICAgICAgZWxzaWYgc3RhdGUgPT0gOmhleGFkZWMKICAgICAgICAgICAgaGV4NCA8PCB0ZXh0W3B0cl0KICAgICAgICAgICAgaWYgaGV4NC5zaXplID09IDQKICAgICAgICAgICAgICAgIHN0ciA8PCBbaGV4NC50b19pKDE2KV0ucGFjaygiVSIpCiAgICAgICAgICAgICAgICBzdGF0ZSA9IDpzdHJpbmcKICAgICAgICAgICAgZW5kCiAgICAgICAgICAgIHB0ciArPSAxCiAgICAgICAgZW5kCiAgICBlbmQKICAgIHJhaXNlIE15SlNPTkVycm9yLm5ldygiaW52YWxpZCA0IGhleGFkZWNpbWFsIGRpZ2l0cyBhdCAje3B0cn0iKSBpZiBzdGF0ZSA9PSA6aGV4YWRlYwogICAgcmFpc2UgTXlKU09ORXJyb3IubmV3KCJub3QgZm91bmQgJ1wiJyBhdCAje3B0cn0iKQogICAgIyDjg6Hjg6LvvJrjgrfjg7PjgrDjg6vjgq/jgqrjg7zjg4jjga/jgqjjgrnjgrHjg7zjg5fjgZfjgarjgYTjgYzvvIwKICAgICMgICAgICAg44Ko44OH44Kj44K/44GM44Ko44K544Kx44O844OX44GZ44KL44Gu44GnJ1wn44Gn44Gv44Gq44GPIlxcIuOBqy4uLgplbmQKCmRlZiBqc29uX3BhcnNlX251bWJlcih0ZXh0LCBwdHIgPSAwKQogICAgc2duID0gMQogICAgdmFsID0gMAogICAgaWYgdGV4dFtwdHJdID09ICctJwogICAgICAgIHNnbiA9IC0xCiAgICAgICAgcHRyICs9IDEKICAgIGVuZAogICAgd2hpbGUgaXNfZGlnaXRfY2hhcih0ZXh0LCBwdHIpCiAgICAgICAgdmFsID0gdmFsKjEwICsgdGV4dFtwdHJdLnRvX2kKICAgICAgICBwdHIgKz0gMQogICAgZW5kCiAgICByZXR1cm4gW3Nnbip2YWwsIHB0cl0KZW5kCgpkZWYganNvbl9wYXJzZV9hcnJheSh0ZXh0LCBwdHIgPSAwKQogICAgYWJvcnQgImpzb25fcGFyc2VfYXJyYXkiIGlmIHRleHRbcHRyXSAhPSAnWycKICAgIHB0ciArPSAxCiAgICBhcnIgPSBbXQogICAgc3RhdGUgPSA6aW5pdGlhbAogICAgd2hpbGUgdGV4dFtwdHJdCiAgICAgICAgaWYgaXNfc3BhY2VfY2hhcih0ZXh0LCBwdHIpCiAgICAgICAgICAgIHB0ciArPSAxCiAgICAgICAgZWxzaWYgdGV4dFtwdHJdID09ICddJwogICAgICAgICAgICByYWlzZSBNeUpTT05FcnJvci5uZXcoImludmFsaWQgJywnIGF0ICN7cHRyfSIpIGlmIHN0YXRlICE9IDppbml0aWFsICYmIHN0YXRlICE9IDp2YWx1ZQogICAgICAgICAgICByZXR1cm4gW2FyciwgcHRyKzFdCiAgICAgICAgZWxzaWYgdGV4dFtwdHJdID09ICcsJwogICAgICAgICAgICByYWlzZSBNeUpTT05FcnJvci5uZXcoImludmFsaWQgJywnIGF0ICN7cHRyfSIpIGlmIHN0YXRlICE9IDp2YWx1ZQogICAgICAgICAgICBzdGF0ZSA9IDpjb21tYQogICAgICAgICAgICBwdHIgKz0gMQogICAgICAgIGVsc2UKICAgICAgICAgICAgdiwgcHRyID0ganNvbl9wYXJzZSh0ZXh0LCBwdHIpCiAgICAgICAgICAgIGFyciA8PCB2CiAgICAgICAgICAgIHN0YXRlID0gOnZhbHVlCiAgICAgICAgZW5kCiAgICBlbmQKICAgIHJhaXNlIE15SlNPTkVycm9yLm5ldygibm90IGZvdW5kICddJyBhdCAje3B0cn0iKQplbmQKCmRlZiBqc29uX3BhcnNlX29iamVjdCh0ZXh0LCBwdHIgPSAwKQogICAgYWJvcnQgImpzb25fcGFyc2Vfb2JqZWN0IiBpZiB0ZXh0W3B0cl0gIT0gJ3snCiAgICBwdHIgKz0gMQogICAgaGFzaCA9IHt9CiAgICBrZXkgPSBuaWwKICAgIHN0YXRlID0gOmluaXRpYWwKICAgIHdoaWxlIHRleHRbcHRyXQogICAgICAgIGlmIGlzX3NwYWNlX2NoYXIodGV4dCwgcHRyKQogICAgICAgICAgICBwdHIgKz0gMQogICAgICAgIGVsc2lmIHRleHRbcHRyXSA9PSAnfScKICAgICAgICAgICAgcmFpc2UgTXlKU09ORXJyb3IubmV3KCJpbnZhbGlkICcsJyBhdCAje3B0cn0iKSBpZiBzdGF0ZSAhPSA6aW5pdGlhbCAmJiBzdGF0ZSAhPSA6dmFsdWUKICAgICAgICAgICAgcmV0dXJuIFtoYXNoLCBwdHIrMV0KICAgICAgICBlbHNpZiB0ZXh0W3B0cl0gPT0gJywnCiAgICAgICAgICAgIHJhaXNlIE15SlNPTkVycm9yLm5ldygiaW52YWxpZCAnLCcgYXQgI3twdHJ9IikgaWYgc3RhdGUgIT0gOnZhbHVlCiAgICAgICAgICAgIHN0YXRlID0gOmNvbW1hCiAgICAgICAgICAgIHB0ciArPSAxCiAgICAgICAgZWxzaWYgdGV4dFtwdHJdID09ICc6JwogICAgICAgICAgICByYWlzZSBNeUpTT05FcnJvci5uZXcoImludmFsaWQgJzonIGF0ICN7cHRyfSIpIGlmIHN0YXRlICE9IDprZXkKICAgICAgICAgICAgc3RhdGUgPSA6Y29sb24KICAgICAgICAgICAgcHRyICs9IDEKICAgICAgICBlbHNpZiB0ZXh0W3B0cl0gPT0gJyInICYmIChzdGF0ZSA9PSA6Y29tbWEgfHwgc3RhdGUgPT0gOmluaXRpYWwpCiAgICAgICAgICAgIGtleSwgcHRyID0ganNvbl9wYXJzZSh0ZXh0LCBwdHIpCiAgICAgICAgICAgIHN0YXRlID0gOmtleQogICAgICAgIGVsc2UKICAgICAgICAgICAgdmFsLCBwdHIgPSBqc29uX3BhcnNlKHRleHQsIHB0cikKICAgICAgICAgICAgaGFzaFtrZXldID0gdmFsCiAgICAgICAgICAgIHN0YXRlID0gOnZhbHVlCiAgICAgICAgZW5kCiAgICBlbmQKICAgIHJhaXNlIE15SlNPTkVycm9yLm5ldygibm90IGZvdW5kICd9JyBhdCAje3B0cn0iKQplbmQKCmRlZiBqc29uX3BhcnNlKHRleHQsIHB0ciA9IDApCiAgICB3aGlsZSB0ZXh0W3B0cl0KICAgICAgICBpZiBpc19zcGFjZV9jaGFyKHRleHQsIHB0cikKICAgICAgICAgICAgcHRyICs9IDEKICAgICAgICBlbHNpZiB0ZXh0W3B0cl0gPT0gJ3QnCiAgICAgICAgICAgIHJldHVybiBqc29uX3BhcnNlX3RydWUodGV4dCwgcHRyKQogICAgICAgIGVsc2lmIHRleHRbcHRyXSA9PSAnZicKICAgICAgICAgICAgcmV0dXJuIGpzb25fcGFyc2VfZmFsc2UodGV4dCwgcHRyKQogICAgICAgIGVsc2lmIHRleHRbcHRyXSA9PSAnbicKICAgICAgICAgICAgcmV0dXJuIGpzb25fcGFyc2VfbnVsbCh0ZXh0LCBwdHIpCiAgICAgICAgZWxzaWYgdGV4dFtwdHJdID09ICciJwogICAgICAgICAgICByZXR1cm4ganNvbl9wYXJzZV9zdHJpbmcodGV4dCwgcHRyKQogICAgICAgIGVsc2lmIHRleHRbcHRyXSA9PSAnLScKICAgICAgICAgICAgcmV0dXJuIGpzb25fcGFyc2VfbnVtYmVyKHRleHQsIHB0cikKICAgICAgICBlbHNpZiBpc19kaWdpdF9jaGFyKHRleHQsIHB0cikKICAgICAgICAgICAgcmV0dXJuIGpzb25fcGFyc2VfbnVtYmVyKHRleHQsIHB0cikKICAgICAgICBlbHNpZiB0ZXh0W3B0cl0gPT0gJ1snCiAgICAgICAgICAgIHJldHVybiBqc29uX3BhcnNlX2FycmF5KHRleHQsIHB0cikKICAgICAgICBlbHNpZiB0ZXh0W3B0cl0gPT0gJ3snCiAgICAgICAgICAgIHJldHVybiBqc29uX3BhcnNlX29iamVjdCh0ZXh0LCBwdHIpCiAgICAgICAgZWxzZQogICAgICAgICAgICByYWlzZSBNeUpTT05FcnJvci5uZXcoImludmFsaWQgYXQgI3twdHJ9IikKICAgICAgICBlbmQKICAgIGVuZAplbmQKCgoKIyAtIC0gLSAtIC0gLSAtIC0gLSAtIC0KCmRlZiB0ZXN0X3N1YgogICAgYWJvcnQgImlzX3NwYWNlX2NoYXIiIHVubGVzcyBpc19zcGFjZV9jaGFyKCIgIikgPT0gdHJ1ZQogICAgYWJvcnQgImlzX3NwYWNlX2NoYXIiIHVubGVzcyBpc19zcGFjZV9jaGFyKCJ0IikgPT0gZmFsc2UKZW5kCnRlc3Rfc3ViCgpkZWYgdGVzdF9tYWluCiAgICBhYm9ydCAiZmFpbGVkOiB0cnVlIiB1bmxlc3MganNvbl9wYXJzZSgndHJ1ZScpWzBdID09IHRydWUKICAgIGFib3J0ICJmYWlsZWQ6IGZhbHNlIiB1bmxlc3MganNvbl9wYXJzZSgnZmFsc2UnKVswXSA9PSBmYWxzZQogICAgYWJvcnQgImZhaWxlZDogbnVsbCIgdW5sZXNzIGpzb25fcGFyc2UoJ251bGwnKVswXSA9PSBuaWwKICAgIGFib3J0ICJmYWlsZWQ6IHN0cmluZyIgdW5sZXNzIGpzb25fcGFyc2UoJyJzdHIiJylbMF0gPT0gJ3N0cicKICAgIGFib3J0ICJmYWlsZWQ6IGVzY2FwZSIgdW5sZXNzIGpzb25fcGFyc2UoJyJmb29cbmJhciInKVswXSA9PSAiZm9vXG5iYXIiCiAgICBhYm9ydCAiZmFpbGVkOiBoZXhhZGVjaW1hbCIgdW5sZXNzIGpzb25fcGFyc2UoJyJcdTdEMDVcdTczODkiJylbMF0gPT0gIue0heeOiSIKICAgIGFib3J0ICJmYWlsZWQ6IG51bWJlciIgdW5sZXNzIGpzb25fcGFyc2UoJzEyMzQ1Njc4OTAnKVswXSA9PSAxMjM0NTY3ODkwCiAgICBhYm9ydCAiZmFpbGVkOiBuZWdhdGl2ZSBudW1iZXIiIHVubGVzcyBqc29uX3BhcnNlKCctMScpWzBdID09IC0xCiAgICBhYm9ydCAiZmFpbGVkOiBhcnJheSAxIiB1bmxlc3MganNvbl9wYXJzZSgnWzEsMiwzXScpWzBdID09IFsxLDIsM10KICAgIGFib3J0ICJmYWlsZWQ6IGFycmF5IDIiIHVubGVzcyBqc29uX3BhcnNlKCdbMSwiZm9vIixudWxsXScpWzBdID09IFsxLCdmb28nLG5pbF0KICAgIGFib3J0ICJmYWlsZWQ6IG1hdHJpeCIgdW5sZXNzIGpzb25fcGFyc2UoJ1tbMSwyXSxbMyw0XSxbNSw2XV0nKVswXSA9PSBbWzEsMl0sWzMsNF0sWzUsNl1dCiAgICBhYm9ydCAiZmFpbGVkOiBydXNzaWFuIGFycmF5IiB1bmxlc3MganNvbl9wYXJzZSgnWzAsWzEsWzIsWzMsWzRdXV1dXScpWzBdID09IFswLFsxLFsyLFszLFs0XV1dXV0KICAgIGFib3J0ICJmYWlsZWQ6IG9iamVjdCAxIiB1bmxlc3MganNvbl9wYXJzZSgneyJrZXkiOiJ2YWwifScpWzBdID09IHsia2V5Ij0+InZhbCJ9CiAgICBhYm9ydCAiZmFpbGVkOiBvYmplY3QgMiIgdW5sZXNzIGpzb25fcGFyc2UoJ3siYSI6bnVsbCwiYiI6WzEsMl0sImMiOnRydWUsImQiOnsieCI6Ilx0In19JylbMF0gPT0geyJhIj0+bmlsLCJiIj0+WzEsMl0sImMiPT50cnVlLCJkIj0+eyJ4Ij0+Ilx0In19CmVuZAp0ZXN0X21haW4=