<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>P3068R4: Allowing exception throwing in constant-evaluation</title>
<link rel="stylesheet" href="data:text/css;base64,QG1lZGlhIChwcmVmZXJzLWNvbG9yLXNjaGVtZTogZGFyaykgewoJOnJvb3QgewoJCS0tdGV4dC1jb2xvcjogI0JCQjsKCQktLWZvdW5kLWhpZ2hsaWdodDogYmx1ZTsKCQktLWZvdW5kLXRleHQtY29sb3I6IHdoaXRlOwoJCS0tbWFpbi1iYWNrZ3JvdW5kOiAzMiwzMiwzMjsKCQktLWhlYWRlci1jb2xvcjogd2hpdGU7CgkJLS1ib3gtc2hhZG93LWNvbG9yOiByZ2JhKDAsMCwwLDAuNSk7CiAgICAtLXRoaW4tYm94LXNoYWRvdy1jb2xvcjogcmdiYSgwLDAsMCwwLjEpOwoJCS0tbmF2LWJhY2tncm91bmQtY29sb3I6ICMxMDEwMTA7CgkJLS1jb2RlLWZvcmVncm91bmQtY29sb3I6IHdoaXRlOwoJCS0tY29kZS1pbmZvLWNvbG9yOiByZ2JhKDI1NSwyNTUsMjU1LDAuMSk7CgkJLS1jb2RlLWJhY2tncm91bmQtY29sb3I6IHZhcigtLW5hdi1iYWNrZ3JvdW5kLWNvbG9yKTsKCQktLWxpbmstY29sb3I6ICM4ZWYzZmY7CgkJLS12aXNpdGVkLWxpbmstY29sb3I6ICNmMGZmODk7CgkJLS1ob3Zlci1saW5rLWNvbG9yOiAjYjNmN2ZmOwoJCS0taG92ZXItdmlzaXRlZC1saW5rLWNvbG9yOiAjYzhmZmIzOwoJCS0tbGluZS1jb2xvcjogMjU1LDI1NSwyNTU7CgkJLS1oZWFkZXItYmFja2dyb3VuZDogMCwwLDA7CgkJLS1xdW90ZS1sZWZ0LWNvbG9yOiByZ2JhKDI1NSwyNTUsMjU1LDAuNSk7CgkJLS1oaWdobGlnaHQ6IHJnYmEoMjU1LDI1MiwwLDAuMjUpOwoJfQoJOjpzZWxlY3Rpb24gewoJICBjb2xvcjogYmxhY2s7CgkgIGJhY2tncm91bmQ6IGxpZ2h0eWVsbG93OwoJfQoJCn0KCkBtZWRpYSAocHJlZmVycy1jb2xvci1zY2hlbWU6IGxpZ2h0KSB7Cgk6cm9vdCB7CgkJLS10ZXh0LWNvbG9yOiBibGFjazsKCQktLWZvdW5kLWhpZ2hsaWdodDogeWVsbG93OwoJCS0tZm91bmQtdGV4dC1jb2xvcjogYmxhY2s7CgkJLS1tYWluLWJhY2tncm91bmQ6IDI1NSwyNTUsMjU1OwoJCS0taGVhZGVyLWNvbG9yOiBibGFjazsKCQktLWJveC1zaGFkb3ctY29sb3I6IHJnYmEoMCwwLDAsMC4zKTsKICAgIC0tdGhpbi1ib3gtc2hhZG93LWNvbG9yOiByZ2JhKDAsMCwwLDAuMSk7CgkJLS1uYXYtYmFja2dyb3VuZC1jb2xvcjogI0Y1RjVGNTsKCQktLWNvZGUtZm9yZWdyb3VuZC1jb2xvcjogYmxhY2s7CgkJLS1jb2RlLWluZm8tY29sb3I6IHJnYmEoMCwwLDAsMC4xKTsKCQktLWNvZGUtYmFja2dyb3VuZC1jb2xvcjogdmFyKC0tbmF2LWJhY2tncm91bmQtY29sb3IpOwoJCS0tbGluay1jb2xvcjogIzAwMDA4MjsKCQktLXZpc2l0ZWQtbGluay1jb2xvcjogIzUwOGQwZjsKCQktLWhvdmVyLWxpbmstY29sb3I6ICM1NzU3YzI7CgkJLS1ob3Zlci12aXNpdGVkLWxpbmstY29sb3I6ICM5NGM1NjA7CgkJLS1saW5lLWNvbG9yOiAxMiw0Myw3NTsKCQktLWhlYWRlci1iYWNrZ3JvdW5kOiAwLDAsMDsKCQktLXF1b3RlLWxlZnQtY29sb3I6IHJnYmEoMCwwLDAsMC41KTsKCQktLWhpZ2hsaWdodDogcmdiYSgyNTUsMjU0LDIwNywwLjUpOwoJfQoJOjpzZWxlY3Rpb24gewoJICBjb2xvcjogYmxhY2s7CgkgIGJhY2tncm91bmQ6ICNhNGMzZjY7Cgl9Cn0KCnNwYW46dGFyZ2V0LCBwOnRhcmdldCwgbGk6dGFyZ2V0LCBkaXY6dGFyZ2V0IHsKICBiYWNrZ3JvdW5kOiB2YXIoLS1oaWdobGlnaHQpOwp9CgoubmFtZS1vZi1wYXBlciB7Cglmb250LXNpemU6IDI4cHg7CglwYWRkaW5nLXRvcDogMC41ZW07Cn0KCnNwYW4uZm91bmQgewoJdGV4dC1zaGFkb3c6IDAgMCAxMHB4IHZhcigtLWZvdW5kLWhpZ2hsaWdodCksICAwIDAgMTBweCB2YXIoLS1mb3VuZC1oaWdobGlnaHQpLCAgMCAwIDEwcHggdmFyKC0tZm91bmQtaGlnaGxpZ2h0KSwgIDAgMCAxMHB4IHZhcigtLWZvdW5kLWhpZ2hsaWdodCk7Cgljb2xvcjogdmFyKC0tZm91bmQtdGV4dC1jb2xvcikgIWltcG9ydGFudDsKfQoKYm9keSB7Cglmb250LWZhbWlseTogSGVsdmV0aWNhOwoJcGFkZGluZzogMDsKCW1hcmdpbjogMDsKCW92ZXJmbG93OiBoaWRkZW47Cgljb2xvcjogdmFyKC0tdGV4dC1jb2xvcik7CgliYWNrZ3JvdW5kLWNvbG9yOiByZ2JhKHZhcigtLW1haW4tYmFja2dyb3VuZCksIDEpOwp9Cgpib2R5ID4gZGl2IHsKCWRpc3BsYXk6IGZsZXg7CglwYWRkaW5nOiAwOwoJbWFyZ2luOiAwOwp9CgouaGlkZS1vbi1uYXJyb3cgewoJZGlzcGxheTogaW5oZXJpdDsKfQoKLmhpZGUtb24td2lkZSB7CglkaXNwbGF5OiBub25lOwp9CgpAbWVkaWEgb25seSBzY3JlZW4gYW5kIChtYXgtd2lkdGg6IDExMDBweCkgewoJYm9keSB7CgkJb3ZlcmZsb3c6IGluaGVyaXQgIWltcG9ydGFudDsKCX0KCS5oaWRlLW9uLW5hcnJvdyB7CgkJZGlzcGxheTogbm9uZTsKCX0KCS5oaWRlLW9uLXdpZGUgewoJCWRpc3BsYXk6IGluaGVyaXQ7Cgl9Cglib2R5ID4gZGl2IHsKCQlkaXNwbGF5OiBibG9jayAhaW1wb3J0YW50OwoJfQoJYXJ0aWNsZSB7CgkJb3ZlcmZsb3c6IGluaGVyaXQgIWltcG9ydGFudDsKCQliYWNrZ3JvdW5kLWltYWdlOiBsaW5lYXItZ3JhZGllbnQodG8gcmlnaHQsIHRyYW5zcGFyZW50LHJnYmEodmFyKC0tbWFpbi1iYWNrZ3JvdW5kKSwwLjYpLCByZ2JhKHZhcigtLW1haW4tYmFja2dyb3VuZCksMC44KSwgcmdiYSh2YXIoLS1tYWluLWJhY2tncm91bmQpLDAuNiksIHRyYW5zcGFyZW50KSAhaW1wb3J0YW50OwoJfQoJbmF2LCBhcnRpY2xlIHsKCQlmbGV4OiBpbml0aWFsICFpbXBvcnRhbnQ7Cgl9CgluYXYgewoJCW1pbi13aWR0aDogaW5pdGlhbCAhaW1wb3J0YW50OwoJCW1heC13aWR0aDogaW5pdGlhbCAhaW1wb3J0YW50OwoJCW1pbi1oZWlnaHQ6IGluaXRpYWwgIWltcG9ydGFudDsKCQltYXgtaGVpZ2h0OiBpbml0aWFsICFpbXBvcnRhbnQ7CgkJYm94LXNoYWRvdzogMCAxMHB4IDAgdmFyKC0tYm94LXNoYWRvdy1jb2xvcik7Cgl9CgluYXYgPiBkaXYgewoJCW92ZXJmbG93OiBpbmhlcml0ICFpbXBvcnRhbnQ7CgkJcG9zaXRpb246IHJlbGF0aXZlICFpbXBvcnRhbnQ7CgkJbWF4LXdpZHRoOiBpbml0aWFsICFpbXBvcnRhbnQ7CgkJbWF4LWhlaWdodDogaW5pdGlhbCAhaW1wb3J0YW50OwoJfQoJZGl2Omhhcyg+IGlucHV0W3R5cGU9c2VhcmNoXSkgewoJCWRpc3BsYXk6IG5vbmU7Cgl9CglkaXYucXVvdGUgewoJCW92ZXJmbG93LXg6IHNjcm9sbDsKCX0KfQoKbmF2IHsKCXBhZGRpbmc6IDAgMC41ZW07CgltYXJnaW46IDA7CglmbGV4OiAxIDEgMDsKCW1pbi13aWR0aDogMzUwcHg7CgltYXgtd2lkdGg6IDM1MHB4OwoJYm94LXNoYWRvdzogMCAwIDEwcHggdmFyKC0tYm94LXNoYWRvdy1jb2xvcik7CgliYWNrZ3JvdW5kLWNvbG9yOiB2YXIoLS1uYXYtYmFja2dyb3VuZC1jb2xvcik7Cn0KCm5hdiA+IGRpdiB7Cglwb3NpdGlvbjogZml4ZWQ7CgltYXgtd2lkdGg6IDM1MHB4OwoJbWF4LWhlaWdodDogMTAwJTsKCW92ZXJmbG93OiBzY3JvbGw7Cgl0b3A6IDA7CglsZWZ0OiAwOwoJcGFkZGluZzogMCAwLjVlbTsKCW1hcmdpbjogMDsKfQoKbmF2ID4gZGl2ID4gZGl2IHsKCXBhZGRpbmc6IDAuNWVtOwoJcGFkZGluZy10b3A6IDA7CglwYWRkaW5nLWJvdHRvbTogMWVtOwp9CgphcnRpY2xlIHsKCWZsZXg6IDMgMSAwOwogIHNjcm9sbC1iZWhhdmlvcjogc21vb3RoOwoJb3ZlcmZsb3c6IHNjcm9sbDsKCWhlaWdodDogMTAwdmg7Cgl0ZXh0LWFsaWduOiBqdXN0aWZ5OwoJYmFja2dyb3VuZC1pbWFnZTogbGluZWFyLWdyYWRpZW50KHRvIGJvdHRvbSwgdHJhbnNwYXJlbnQscmdiYSh2YXIoLS1tYWluLWJhY2tncm91bmQpLDAuNiksIHJnYmEodmFyKC0tbWFpbi1iYWNrZ3JvdW5kKSwwLjgpLCByZ2JhKHZhcigtLW1haW4tYmFja2dyb3VuZCksMC42KSwgdHJhbnNwYXJlbnQpOwoJcGFkZGluZzogMDsKCW1hcmdpbjogMDsKfQoKYXJ0aWNsZSA+IGRpdiB7CglwYWRkaW5nLXJpZ2h0OiAxLjVlbTsKCXBhZGRpbmctbGVmdDogMS41ZW07CglwYWRkaW5nLWJvdHRvbTogMWVtOwp9Cgpjb2RlIHsKCQp9CgpkaXYucXVvdGUgewoJY29sb3I6IHZhcigtLWNvZGUtZm9yZWdyb3VuZC1jb2xvcik7CgliYWNrZ3JvdW5kOiB2YXIoLS1jb2RlLWJhY2tncm91bmQtY29sb3IpOwoJcGFkZGluZzogMWVtOwoJYm9yZGVyLXJhZGl1czogMHB4IDE1cHggMTVweCAwcHg7Cglib3JkZXItbGVmdDogNXB4IHNvbGlkIHZhcigtLXF1b3RlLWxlZnQtY29sb3IpOwoJZm9udC1zdHlsZTogaXRhbGljOwoJbWFyZ2luOiAxZW07Cn0KCmNvZGU6bm90KHByZSA+IGNvZGUpIHsKCWNvbG9yOiBpbmhlcml0OwoJYmFja2dyb3VuZDogdmFyKC0tY29kZS1iYWNrZ3JvdW5kLWNvbG9yKTsKCWJvcmRlci1yYWRpdXM6IDVweDsKCXBhZGRpbmc6IDAgMC4yZW07CgltYXJnaW46IDAgMnB4OwoJb3V0bGluZTogMnB4IHNvbGlkIHZhcigtLWNvZGUtYmFja2dyb3VuZC1jb2xvcik7Cn0KCnByZSA+IGNvZGUgewoJb3V0bGluZTogbm9uZTsKCWxpbmUtaGVpZ2h0OiAxLjQ7Cgl0YWItc2l6ZTogMjsKfQoKcHJlOmhhcyhjb2RlKSB7Cgljb2xvcjogdmFyKC0tY29kZS1mb3JlZ3JvdW5kLWNvbG9yKTsKCWJhY2tncm91bmQ6IHZhcigtLWNvZGUtYmFja2dyb3VuZC1jb2xvcik7CglwYWRkaW5nOiAxZW07Cglib3JkZXItcmFkaXVzOiAxNXB4OwoJcG9zaXRpb246IHJlbGF0aXZlOwoJei1pbmRleDogMTsKCW92ZXJmbG93LXg6IHNjcm9sbDsKfQoKcHJlOmhhcyhjb2RlLmxhbmd1YWdlLWNhcmJvbik6OmJlZm9yZSB7Cgljb250ZW50OiAiQ2FyYm9uIjsKCXRleHQtdHJhbnNmb3JtOiB1cHBlcmNhc2U7Cglwb3NpdGlvbjogYWJzb2x1dGU7Cgl0b3A6IDFlbTsKCXJpZ2h0OiAxZW07Cgljb2xvcjogdmFyKC0tY29kZS1pbmZvLWNvbG9yKTsKCWZvbnQtd2VpZ2h0OiBib2xkOwp9CgpwLCB1bCA+IGxpIHsKCXRleHQtYWxpZ246IGp1c3RpZnk7CglvdmVyZmxvdy13cmFwOiBicmVhay13b3JkOwoJaHlwaGVuczogYXV0bzsKfQoKZGl2LmRlc2NyaXB0aW9uIHVsIHsKICBwYWRkaW5nLXRvcDogMC41ZW07CglwYWRkaW5nLWJvdHRvbTogMC41ZW07Cn0KCmEgewoJY29sb3I6IHZhcigtLWxpbmstY29sb3IpOwoJdGV4dC1kZWNvcmF0aW9uLXN0eWxlOiBkb3R0ZWQ7Cn0KCmE6aG92ZXIgewoJY29sb3I6IHZhcigtLWhvdmVyLWxpbmstY29sb3IpOwoJdGV4dC1kZWNvcmF0aW9uLXN0eWxlOiBzb2xpZDsKfQoKYTp2aXNpdGVkIHsKCWNvbG9yOiB2YXIoLS12aXNpdGVkLWxpbmstY29sb3IpOwp9CgphOnZpc2l0ZWQ6aG92ZXIgewoJY29sb3I6IHZhcigtLWhvdmVyLXZpc2l0ZWQtbGluay1jb2xvcik7Cgl0ZXh0LWRlY29yYXRpb24tc3R5bGU6IHNvbGlkOwp9CgpoMSwgaDIsIGgzLCBoNCwgaDUgewoJbWFyZ2luOiAwOwoJbWFyZ2luLWJvdHRvbTogMTBweDsKCXBhZGRpbmc6IDAuNWVtOwoJcGFkZGluZy10b3A6IDIwcHg7CglwYWRkaW5nLWJvdHRvbTogMnB4OwoJei1pbmRleDogMjsKCWNvbG9yOiB2YXIoLS1oZWFkZXItY29sb3IpOwp9CgphcnRpY2xlIGgxLCBhcnRpY2xlIGgyLCBhcnRpY2xlIGgzLCBhcnRpY2xlIGg0LCBhcnRpY2xlIGg1IHsKLyoJcG9zaXRpb246IHN0aWNreTsKCXBvc2l0aW9uOiAtd2Via2l0LXN0aWNreTsKCXRvcDogMDsqLwoJCn0KCmgxIHsKCWZvbnQtd2VpZ2h0OiA4MDA7Cglib3JkZXItYm90dG9tOiByZ2JhKHZhcigtLWxpbmUtY29sb3IpLCAxKSBkb3R0ZWQgMnB4Owp9CgpoMiB7Cglmb250LXdlaWdodDogODAwOwoJYm9yZGVyLWJvdHRvbTogcmdiYSh2YXIoLS1saW5lLWNvbG9yKSwgMC43NSkgZG90dGVkIDJweDsKfQoKaDMsIGg0LCBoNSB7Cglmb250LXdlaWdodDogNjAwOwoJYm9yZGVyLWJvdHRvbTogcmdiYSh2YXIoLS1saW5lLWNvbG9yKSwgMC4zMykgZG90dGVkIDJweDsKfQoKaDEgPiBhLCBoMiA+IGEsIGgzID4gYSwgaDQgPiBhLCBoNSA+IGEgewoJY29sb3I6IGluaGVyaXQgIWltcG9ydGFudDsKCXRleHQtZGVjb3JhdGlvbjogaW5oZXJpdDsKfQoKaDE6dGFyZ2V0OjphZnRlciwgaDI6dGFyZ2V0OjphZnRlciwgaDM6dGFyZ2V0OjphZnRlciwgaDQ6dGFyZ2V0OjphZnRlciwgaDU6dGFyZ2V0OjphZnRlciB7Cgl0ZXh0LWRlY29yYXRpb246IGluaGVyaXQ7Cgljb250ZW50OiAiIOKak++4jiI7CiAgZm9udC1zaXplOiAxNHB4Owp9CgpoMSA+IGE6aG92ZXIsIGgyID4gYTpob3ZlciwgaDMgPiBhOmhvdmVyLCBoNCA+IGE6aG92ZXIsIGg1ID4gYTpob3ZlciB7Cgljb2xvcjogdmFyKC0taG92ZXItbGluay1jb2xvcik7Cn0KCmRpdjpoYXMoPiBpbnB1dFt0eXBlPXNlYXJjaF0pIHsKCXBvc2l0aW9uOiBmaXhlZDsKCXRvcDogMDsKCXJpZ2h0OiAwOwoJei1pbmRleDogMTAwMDsKCXBhZGRpbmc6IDAuNWVtOwoJYmFja2dyb3VuZC1jb2xvcjogdmFyKC0tbmF2LWJhY2tncm91bmQtY29sb3IpOwoJYm94LXNoYWRvdzogMCAwIDEwcHggcmdiYSgwLDAsMCwwLjMpOwoJYm9yZGVyLWJvdHRvbS1sZWZ0LXJhZGl1czogMTBweDsKfQoKZGl2ID4gaW5wdXRbdHlwZT1zZWFyY2hdIHsKCWJhY2tncm91bmQtY29sb3I6IHZhcigtLW5hdi1iYWNrZ3JvdW5kLWNvbG9yKTsKCWJvcmRlcjogMnB4IHNvbGlkIHZhcigtLXRleHQtY29sb3IpOwoJY29sb3I6IHZhcigtLXRleHQtY29sb3IpOwoJd2lkdGg6IDMwMHB4Owp9CgpkaXYucGFwZXItaW5mbyB7CglwYWRkaW5nOiAwOwoJcGFkZGluZy10b3A6IDFlbTsKCQoJLmtleSB7CgkJZm9udC13ZWlnaHQ6IGJvbGQ7Cgl9CgkKCWRpdiB7Cgl9Cn0KCnVsIHsKCXBhZGRpbmc6IDA7CgltYXJnaW46IDA7CglwYWRkaW5nLWxlZnQ6IDJlbTsKfQoKbGkgPiB1bCB7CglwYWRkaW5nLWxlZnQ6IDAuNWVtOwp9Cgp1bCA+IGxpIHsKCXBhZGRpbmctbGVmdDogMC41ZW07Cn0KCmNvZGUgLmVycm9yLCBjb2RlIC5iZWZvcmUgewoJCWxpbmUtaGVpZ2h0OiAxLjk7Cn0KCmNvZGUgLmVycm9yID4gKiwgY29kZSAuYmVmb3JlID4gKiB7CgliYWNrZ3JvdW5kLWNvbG9yOiAjRkY4ODg4ICFpbXBvcnRhbnQ7Cgljb2xvcjogYmxhY2sgIWltcG9ydGFudDsKCUBtZWRpYSAocHJlZmVycy1jb2xvci1zY2hlbWU6IGRhcmspIHsKCQljb2xvcjogd2hpdGU7Cgl9Cglib3JkZXI6IDNweCBzb2xpZCAjRkY4ODg4OwoJZm9udC13ZWlnaHQ6IGJvbGQ7Cn0KCmNvZGUgLmFmdGVyID4gKiB7CgliYWNrZ3JvdW5kLWNvbG9yOiBsaWdodGdyZWVuICFpbXBvcnRhbnQ7Cgljb2xvcjogYmxhY2sgIWltcG9ydGFudDsKCUBtZWRpYSAocHJlZmVycy1jb2xvci1zY2hlbWU6IGRhcmspIHsKCQljb2xvcjogd2hpdGU7Cgl9Cglib3JkZXI6IDNweCBzb2xpZCBsaWdodGdyZWVuOwoJZm9udC13ZWlnaHQ6IGJvbGQ7Cn0KCmNvZGUgLnVuY2hhbmdlZCA+ICogewoJYmFja2dyb3VuZC1jb2xvcjogbGlnaHR5ZWxsb3cgIWltcG9ydGFudDsKCWNvbG9yOiBibGFjayAhaW1wb3J0YW50OwoJQG1lZGlhIChwcmVmZXJzLWNvbG9yLXNjaGVtZTogZGFyaykgewoJCWNvbG9yOiB3aGl0ZTsKCX0KCWJvcmRlcjogM3B4IHNvbGlkIGxpZ2h0eWVsbG93OwoJZm9udC13ZWlnaHQ6IGJvbGQ7Cn0KCmNvZGUgLmludmlzaWJsZSB7Cgl2aXNpYmlsaXR5OiBoaWRkZW47Cn0KCi5jaGFuZ2VzIHsKCWRpc3BsYXk6IGlubGluZS1ibG9jazsKfQoKLndvcmRpbmcgaDEsIC53b3JkaW5nIGgyIHsKCWZvbnQtc2l6ZTogaW5oZXJpdDsKCXRleHQtZGVjb3JhdGlvbjogbm9uZTsKCWJvcmRlcjogbm9uZTsKCXBhZGRpbmc6IDA7CgltYXJnaW46IDA7Cn0KCi53b3JkaW5nIHAgewoJcGFkZGluZzogMDsKCXBhZGRpbmctdG9wOiAwLjVlbTsKCW1hcmdpbjogMDsKfQoKLndvcmRpbmcgYSB7Cgl0ZXh0LWRlY29yYXRpb246IG5vbmU7Cgljb2xvcjogaW5oZXJpdDsKfQoKLndvcmRpbmcgYTpob3ZlciB7Cgl0ZXh0LWRlY29yYXRpb246IHVuZGVybGluZTsKCWNvbG9yOiB2YXIoLS1saW5rLWNvbG9yKTsKfQoKLndvcmRpbmcgY29kZSB7CgliYWNrZ3JvdW5kOiBpbmhlcml0ICFpbXBvcnRhbnQ7Cglib3JkZXI6IG5vbmU7CglvdXRsaW5lOiBub25lOwp9CgkKLndvcmRpbmcgewoJZm9udC1mYW1pbHk6ICJOb3RvIFNlcmlmIjsKCQoJcGFkZGluZzogMC41ZW0gMWVtOwoJcGFkZGluZy1ib3R0b206IDFlbTsKCWNvbG9yOiB2YXIoLS1jb2RlLWZvcmVncm91bmQtY29sb3IpOwoJYmFja2dyb3VuZDogdmFyKC0tY29kZS1iYWNrZ3JvdW5kLWNvbG9yKTsKCWxpbmUtaGVpZ2h0OiAxLjU1OwoJCglib3JkZXItcmFkaXVzOiAxNXB4OwoJcG9zaXRpb246IHJlbGF0aXZlOwoJei1pbmRleDogMTsKCW92ZXJmbG93LXg6IHNjcm9sbDsKfQoJCi53b3JkaW5nIC5hZGRlZCB7CgliYWNrZ3JvdW5kLWNvbG9yOiBsaWdodGdyZWVuOwogIHRleHQtZGVjb3JhdGlvbjogdW5kZXJsaW5lOwogIHRleHQtZGVjb3JhdGlvbi1jb2xvcjogZ3JlZW47CiAgdGV4dC1kZWNvcmF0aW9uLXRoaWNrbmVzczogMnB4ICFpbXBvcnRhbnQ7Cgl6LWluZGV4OiA4MDsKCXBhZGRpbmc6IDNweDsKCUBtZWRpYSAocHJlZmVycy1jb2xvci1zY2hlbWU6IGRhcmspIHsKCQljb2xvcjogYmxhY2s7Cgl9Cn0KCQoud29yZGluZyAucmVtb3ZlZCB7CgliYWNrZ3JvdW5kLWNvbG9yOiAjRkY4ODg4OwoJei1pbmRleDogNTA7CglwYWRkaW5nOiAzcHg7CiAgdGV4dC1kZWNvcmF0aW9uOiBsaW5lLXRocm91Z2g7CiAgdGV4dC1kZWNvcmF0aW9uLWNvbG9yOiByZWQ7CiAgdGV4dC1kZWNvcmF0aW9uLXRoaWNrbmVzczogMnB4ICFpbXBvcnRhbnQ7CglAbWVkaWEgKHByZWZlcnMtY29sb3Itc2NoZW1lOiBkYXJrKSB7CgkJY29sb3I6IGJsYWNrOwoJfQp9CgkKLndvcmRpbmcgLm5vdGUgewoJZm9udC1zaXplOiAwLjhlbTsKfQoJCi53b3JkaW5nCSsgLndvcmRpbmcgewoJbWFyZ2luLXRvcDogMC41ZW07Cn0KCQoud29yZGluZyBwcmU6aGFzKGNvZGUpIHsKCWJvcmRlcjogMXB4IHNvbGlkIHZhcigtLWNvZGUtaW5mby1jb2xvcik7Cglib3JkZXItcmFkaXVzOiAwOwoJcGFkZGluZzogMGVtOwoJei1pbmRleDogMTsKCW92ZXJmbG93LXg6IHNjcm9sbDsKfQoJCi53b3JkaW5nCWNvZGUgLmFkZGVkZWQgc3BhbiB7Cgljb2xvcjogYmxhY2sgIWltcG9ydGFudDsKfQoKdGFibGUucG9sbCB7CiAgYm9yZGVyLWNvbGxhcHNlOiBjb2xsYXBzZTsKICBtYXJnaW4tdG9wOiAyMHB4Owp9Cgp0YWJsZS5wb2xsIHRoLCB0YWJsZS5wb2xsIHRkIHsKICBib3JkZXI6IDA7CiAgcGFkZGluZzogMCAxMHB4OwogIHRleHQtYWxpZ246IGNlbnRlcjsKICBib3JkZXI6IDJweCBzb2xpZCByZ2JhKDEyOCwxMjgsMTI4LDAuMik7Cn0KCnRhYmxlLnBvbGwgdGQ6Zmlyc3QtY2hpbGQsIHRhYmxlLnBvbGwgdGg6Zmlyc3QtY2hpbGQgewogYm9yZGVyLWxlZnQ6IG5vbmU7Cn0KCnRhYmxlLnBvbGwgdGQ6bGFzdC1jaGlsZCwgdGFibGUucG9sbCB0aDpsYXN0LWNoaWxkIHsKIGJvcmRlci1yaWdodDogbm9uZTsKfQoKdGFibGUucG9sbCB0cjpmaXJzdC1jaGlsZCB0aCwgdGFibGUucG9sbCB0cjpmaXJzdC1jaGlsZCB0ZCB7CiAgYm9yZGVyLXRvcDogbm9uZTsKfQoKdGFibGUucG9sbCB0cjpsYXN0LWNoaWxkIHRoLCB0YWJsZS5wb2xsIHRyOmxhc3QtY2hpbGQgdGQgewogIGJvcmRlci1ib3R0b206IG5vbmU7Cn0KCi53b3JkaW5nIC5kZXNjcmlwdGlvbiB7CiAgcGFkZGluZy1ib3R0b206IDFlbTsKfQoKLndvcmRpbmcgLmNhcHMgewogIHRleHQtdHJhbnNmb3JtOiB1cHBlcmNhc2U7Cn0KCnRhYmxlLmJlZm9yZS1hZnRlciB0aCwgdGFibGUuYmVmb3JlLWFmdGVyIHRkICB7CiAgaGVpZ2h0OiAzMHB4Owp9Cgp0YWJsZS5iZWZvcmUtYWZ0ZXIgdGQuZ3JlZW4gewogIGNvbG9yOiBncmVlbjsKfQoKdGFibGUuYmVmb3JlLWFmdGVyIHRkLnJlZCB7CiAgY29sb3I6IHJlZDsKICBmb250LXNpemU6IDI0cHg7CiAgbGluZS1oZWlnaHQ6IDE2cHg7Cn0KCmRpdi53b3JkaW5nLW5vdGUgewogIGJhY2tncm91bmQ6IHJnYih2YXIoLS1tYWluLWJhY2tncm91bmQpKTsKICBib3gtc2hhZG93OiA1cHggMCAxMHB4IHZhcigtLXRoaW4tYm94LXNoYWRvdy1jb2xvcikgaW5zZXQ7CiAgYm9yZGVyLXJhZGl1czogMTVweDsKICBjb2xvcjogdmFyKC0tdGV4dC1jb2xvcik7CiAgcGFkZGluZzogMTBweDsKICBtYXJnaW46IDEwcHggMjBweDsKICBmb250LXNpemU6IDEycHg7Cn0KCi5wYXJudW0gewoJZm9udC1zaXplOiAxMnB4OwoJbWFyZ2luLXJpZ2h0OiAwLjI1ZW07CglkaXNwbGF5OiBpbmxpbmUtYmxvY2s7Cn0KCmxpOmhhcyg+IC5wYXJudW0pIHsKCWxpc3Qtc3R5bGUtcG9zaXRpb246IGluc2lkZTsKCXBvc2l0aW9uOiByZWxhdGl2ZTsKfQoKbGkgPiAucGFybnVtIHsKCXBvc2l0aW9uOiBhYnNvbHV0ZTsKCWxlZnQ6IC0zMHB4OwoJYm90dG9tOiAycHg7Cn0K">
<link rel="stylesheet" href="data:text/css;base64,QG1lZGlhIChwcmVmZXJzLWNvbG9yLXNjaGVtZTogbGlnaHQpIHsKCnByZSBjb2RlLmhsanMgewoKfQpjb2RlLmhsanMgewoKfQovKgoKWENvZGUgc3R5bGUgKGMpIEFuZ2VsIEdhcmNpYSA8YW5nZWxnYXJjaWEubWFpbEBnbWFpbC5jb20+CgoqLwouaGxqcyB7CiAgY29sb3I6IGluaGVyaXQKfQovKiBHcmF5IERPQ1RZUEUgc2VsZWN0b3JzIGxpa2UgV2ViS2l0ICovCi54bWwgLmhsanMtbWV0YSB7CiAgY29sb3I6ICNjMGMwYzAKfQouaGxqcy1jb21tZW50LAouaGxqcy1xdW90ZSB7CiAgY29sb3I6ICMwMDc0MDAKfQouaGxqcy10YWcsCi5obGpzLWF0dHJpYnV0ZSwKLmhsanMta2V5d29yZCwKLmhsanMtc2VsZWN0b3ItdGFnLAouaGxqcy1saXRlcmFsLAouaGxqcy1uYW1lIHsKICBjb2xvcjogI2FhMGQ5MQp9Ci5obGpzLXZhcmlhYmxlLAouaGxqcy10ZW1wbGF0ZS12YXJpYWJsZSB7CiAgY29sb3I6ICMzRjZFNzQKfQouaGxqcy1jb2RlLAouaGxqcy1zdHJpbmcsCi5obGpzLW1ldGEgLmhsanMtc3RyaW5nIHsKICBjb2xvcjogI2M0MWExNgp9Ci5obGpzLXJlZ2V4cCwKLmhsanMtbGluayB7CiAgY29sb3I6ICMwRTBFRkYKfQouaGxqcy10aXRsZSwKLmhsanMtc3ltYm9sLAouaGxqcy1idWxsZXQsCi5obGpzLW51bWJlciB7CiAgY29sb3I6ICMxYzAwY2YKfQouaGxqcy1zZWN0aW9uLAouaGxqcy1tZXRhIHsKICBjb2xvcjogIzY0MzgyMAp9Ci5obGpzLXRpdGxlLmNsYXNzXywKLmhsanMtY2xhc3MgLmhsanMtdGl0bGUsCi5obGpzLXR5cGUsCi5obGpzLWJ1aWx0X2luLAouaGxqcy1wYXJhbXMgewogIGNvbG9yOiAjNWMyNjk5Cn0KLmhsanMtYXR0ciB7CiAgY29sb3I6ICM4MzZDMjgKfQouaGxqcy1zdWJzdCB7CiAgY29sb3I6ICMwMDAKfQouaGxqcy1mb3JtdWxhIHsKICBmb250LXN0eWxlOiBpdGFsaWMKfQouaGxqcy1hZGRpdGlvbiB7Cgp9Ci5obGpzLWRlbGV0aW9uIHsKCn0KLmhsanMtc2VsZWN0b3ItaWQsCi5obGpzLXNlbGVjdG9yLWNsYXNzIHsKICBjb2xvcjogIzliNzAzZgp9Ci5obGpzLWRvY3RhZywKLmhsanMtc3Ryb25nIHsKICBmb250LXdlaWdodDogYm9sZAp9Ci5obGpzLWVtcGhhc2lzIHsKICBmb250LXN0eWxlOiBpdGFsaWMKfQoKfQoKQG1lZGlhIChwcmVmZXJzLWNvbG9yLXNjaGVtZTogZGFyaykgewoKcHJlIGNvZGUuaGxqcyB7Cgp9CmNvZGUuaGxqcyB7Cgp9Ci8qCgpYQ29kZSBzdHlsZSAoYykgQW5nZWwgR2FyY2lhIDxhbmdlbGdhcmNpYS5tYWlsQGdtYWlsLmNvbT4KCiovCi5obGpzIHsKICBjb2xvcjogaW5oZXJpdAp9Ci8qIEdyYXkgRE9DVFlQRSBzZWxlY3RvcnMgbGlrZSBXZWJLaXQgKi8KLnhtbCAuaGxqcy1tZXRhIHsKICBjb2xvcjogI2MwYzBjMAp9Ci5obGpzLWNvbW1lbnQsCi5obGpzLXF1b3RlIHsKICBjb2xvcjogIzAwNzQwMAp9Ci5obGpzLXRhZywKLmhsanMtYXR0cmlidXRlLAouaGxqcy1rZXl3b3JkLAouaGxqcy1zZWxlY3Rvci10YWcsCi5obGpzLWxpdGVyYWwsCi5obGpzLW5hbWUgewogIGNvbG9yOiAjYWEwZDkxCn0KLmhsanMtdmFyaWFibGUsCi5obGpzLXRlbXBsYXRlLXZhcmlhYmxlIHsKICBjb2xvcjogIzNGNkU3NAp9Ci5obGpzLWNvZGUsCi5obGpzLXN0cmluZywKLmhsanMtbWV0YSAuaGxqcy1zdHJpbmcgewogIGNvbG9yOiAjYzQxYTE2Cn0KLmhsanMtcmVnZXhwLAouaGxqcy1saW5rIHsKICBjb2xvcjogIzBFMEVGRgp9Ci5obGpzLXRpdGxlLAouaGxqcy1zeW1ib2wsCi5obGpzLWJ1bGxldCwKLmhsanMtbnVtYmVyIHsKICBjb2xvcjogIzkzODJmZgp9Ci5obGpzLXNlY3Rpb24sCi5obGpzLW1ldGEgewogIGNvbG9yOiAjNjQzODIwCn0KLmhsanMtdGl0bGUuY2xhc3NfLAouaGxqcy1jbGFzcyAuaGxqcy10aXRsZSwKLmhsanMtdHlwZSwKLmhsanMtYnVpbHRfaW4sCi5obGpzLXBhcmFtcyB7CiAgY29sb3I6ICNiODc5ZmYKfQouaGxqcy1hdHRyIHsKICBjb2xvcjogIzgzNkMyOAp9Ci5obGpzLXN1YnN0IHsKICBjb2xvcjogIzAwMAp9Ci5obGpzLWZvcm11bGEgewogIGZvbnQtc3R5bGU6IGl0YWxpYwp9Ci5obGpzLWFkZGl0aW9uIHsKCn0KLmhsanMtZGVsZXRpb24gewoKfQouaGxqcy1zZWxlY3Rvci1pZCwKLmhsanMtc2VsZWN0b3ItY2xhc3MgewogIGNvbG9yOiAjOWI3MDNmCn0KLmhsanMtZG9jdGFnLAouaGxqcy1zdHJvbmcgewogIGZvbnQtd2VpZ2h0OiBib2xkCn0KLmhsanMtZW1waGFzaXMgewogIGZvbnQtc3R5bGU6IGl0YWxpYwp9Cgp9CgoK">
<link href="https://fonts.googleapis.com/css?family=Noto+Serif" rel='stylesheet'>
<script src="data:text/javascript;base64,LyohCiAgSGlnaGxpZ2h0LmpzIHYxMS45LjAgKGdpdDogYjdlYzRiZmFmYykKICAoYykgMjAwNi0yMDI0IHVuZGVmaW5lZCBhbmQgb3RoZXIgY29udHJpYnV0b3JzCiAgTGljZW5zZTogQlNELTMtQ2xhdXNlCiAqLwp2YXIgaGxqcz1mdW5jdGlvbigpeyJ1c2Ugc3RyaWN0IjtmdW5jdGlvbiBlKHQpewpyZXR1cm4gdCBpbnN0YW5jZW9mIE1hcD90LmNsZWFyPXQuZGVsZXRlPXQuc2V0PSgpPT57CnRocm93IEVycm9yKCJtYXAgaXMgcmVhZC1vbmx5Iil9OnQgaW5zdGFuY2VvZiBTZXQmJih0LmFkZD10LmNsZWFyPXQuZGVsZXRlPSgpPT57CnRocm93IEVycm9yKCJzZXQgaXMgcmVhZC1vbmx5IikKfSksT2JqZWN0LmZyZWV6ZSh0KSxPYmplY3QuZ2V0T3duUHJvcGVydHlOYW1lcyh0KS5mb3JFYWNoKChuPT57CmNvbnN0IGk9dFtuXSxzPXR5cGVvZiBpOyJvYmplY3QiIT09cyYmImZ1bmN0aW9uIiE9PXN8fE9iamVjdC5pc0Zyb3plbihpKXx8ZShpKQp9KSksdH1jbGFzcyB0e2NvbnN0cnVjdG9yKGUpewp2b2lkIDA9PT1lLmRhdGEmJihlLmRhdGE9e30pLHRoaXMuZGF0YT1lLmRhdGEsdGhpcy5pc01hdGNoSWdub3JlZD0hMX0KaWdub3JlTWF0Y2goKXt0aGlzLmlzTWF0Y2hJZ25vcmVkPSEwfX1mdW5jdGlvbiBuKGUpewpyZXR1cm4gZS5yZXBsYWNlKC8mL2csIiZhbXA7IikucmVwbGFjZSgvPC9nLCImbHQ7IikucmVwbGFjZSgvPi9nLCImZ3Q7IikucmVwbGFjZSgvIi9nLCImcXVvdDsiKS5yZXBsYWNlKC8nL2csIiYjeDI3OyIpCn1mdW5jdGlvbiBpKGUsLi4udCl7Y29uc3Qgbj1PYmplY3QuY3JlYXRlKG51bGwpO2Zvcihjb25zdCB0IGluIGUpblt0XT1lW3RdCjtyZXR1cm4gdC5mb3JFYWNoKChlPT57Zm9yKGNvbnN0IHQgaW4gZSluW3RdPWVbdF19KSksbn1jb25zdCBzPWU9PiEhZS5zY29wZQo7Y2xhc3Mgb3tjb25zdHJ1Y3RvcihlLHQpewp0aGlzLmJ1ZmZlcj0iIix0aGlzLmNsYXNzUHJlZml4PXQuY2xhc3NQcmVmaXgsZS53YWxrKHRoaXMpfWFkZFRleHQoZSl7CnRoaXMuYnVmZmVyKz1uKGUpfW9wZW5Ob2RlKGUpe2lmKCFzKGUpKXJldHVybjtjb25zdCB0PSgoZSx7cHJlZml4OnR9KT0+ewppZihlLnN0YXJ0c1dpdGgoImxhbmd1YWdlOiIpKXJldHVybiBlLnJlcGxhY2UoImxhbmd1YWdlOiIsImxhbmd1YWdlLSIpCjtpZihlLmluY2x1ZGVzKCIuIikpe2NvbnN0IG49ZS5zcGxpdCgiLiIpCjtyZXR1cm5bYCR7dH0ke24uc2hpZnQoKX1gLC4uLm4ubWFwKCgoZSx0KT0+YCR7ZX0keyJfIi5yZXBlYXQodCsxKX1gKSldLmpvaW4oIiAiKQp9cmV0dXJuYCR7dH0ke2V9YH0pKGUuc2NvcGUse3ByZWZpeDp0aGlzLmNsYXNzUHJlZml4fSk7dGhpcy5zcGFuKHQpfQpjbG9zZU5vZGUoZSl7cyhlKSYmKHRoaXMuYnVmZmVyKz0iPC9zcGFuPiIpfXZhbHVlKCl7cmV0dXJuIHRoaXMuYnVmZmVyfXNwYW4oZSl7CnRoaXMuYnVmZmVyKz1gPHNwYW4gY2xhc3M9IiR7ZX0iPmB9fWNvbnN0IHI9KGU9e30pPT57Y29uc3QgdD17Y2hpbGRyZW46W119CjtyZXR1cm4gT2JqZWN0LmFzc2lnbih0LGUpLHR9O2NsYXNzIGF7Y29uc3RydWN0b3IoKXsKdGhpcy5yb290Tm9kZT1yKCksdGhpcy5zdGFjaz1bdGhpcy5yb290Tm9kZV19Z2V0IHRvcCgpewpyZXR1cm4gdGhpcy5zdGFja1t0aGlzLnN0YWNrLmxlbmd0aC0xXX1nZXQgcm9vdCgpe3JldHVybiB0aGlzLnJvb3ROb2RlfWFkZChlKXsKdGhpcy50b3AuY2hpbGRyZW4ucHVzaChlKX1vcGVuTm9kZShlKXtjb25zdCB0PXIoe3Njb3BlOmV9KQo7dGhpcy5hZGQodCksdGhpcy5zdGFjay5wdXNoKHQpfWNsb3NlTm9kZSgpewppZih0aGlzLnN0YWNrLmxlbmd0aD4xKXJldHVybiB0aGlzLnN0YWNrLnBvcCgpfWNsb3NlQWxsTm9kZXMoKXsKZm9yKDt0aGlzLmNsb3NlTm9kZSgpOyk7fXRvSlNPTigpe3JldHVybiBKU09OLnN0cmluZ2lmeSh0aGlzLnJvb3ROb2RlLG51bGwsNCl9CndhbGsoZSl7cmV0dXJuIHRoaXMuY29uc3RydWN0b3IuX3dhbGsoZSx0aGlzLnJvb3ROb2RlKX1zdGF0aWMgX3dhbGsoZSx0KXsKcmV0dXJuInN0cmluZyI9PXR5cGVvZiB0P2UuYWRkVGV4dCh0KTp0LmNoaWxkcmVuJiYoZS5vcGVuTm9kZSh0KSwKdC5jaGlsZHJlbi5mb3JFYWNoKCh0PT50aGlzLl93YWxrKGUsdCkpKSxlLmNsb3NlTm9kZSh0KSksZX1zdGF0aWMgX2NvbGxhcHNlKGUpewoic3RyaW5nIiE9dHlwZW9mIGUmJmUuY2hpbGRyZW4mJihlLmNoaWxkcmVuLmV2ZXJ5KChlPT4ic3RyaW5nIj09dHlwZW9mIGUpKT9lLmNoaWxkcmVuPVtlLmNoaWxkcmVuLmpvaW4oIiIpXTplLmNoaWxkcmVuLmZvckVhY2goKGU9PnsKYS5fY29sbGFwc2UoZSl9KSkpfX1jbGFzcyBjIGV4dGVuZHMgYXtjb25zdHJ1Y3RvcihlKXtzdXBlcigpLHRoaXMub3B0aW9ucz1lfQphZGRUZXh0KGUpeyIiIT09ZSYmdGhpcy5hZGQoZSl9c3RhcnRTY29wZShlKXt0aGlzLm9wZW5Ob2RlKGUpfWVuZFNjb3BlKCl7CnRoaXMuY2xvc2VOb2RlKCl9X19hZGRTdWJsYW5ndWFnZShlLHQpe2NvbnN0IG49ZS5yb290Cjt0JiYobi5zY29wZT0ibGFuZ3VhZ2U6Iit0KSx0aGlzLmFkZChuKX10b0hUTUwoKXsKcmV0dXJuIG5ldyBvKHRoaXMsdGhpcy5vcHRpb25zKS52YWx1ZSgpfWZpbmFsaXplKCl7CnJldHVybiB0aGlzLmNsb3NlQWxsTm9kZXMoKSwhMH19ZnVuY3Rpb24gbChlKXsKcmV0dXJuIGU/InN0cmluZyI9PXR5cGVvZiBlP2U6ZS5zb3VyY2U6bnVsbH1mdW5jdGlvbiBnKGUpe3JldHVybiBoKCIoPz0iLGUsIikiKX0KZnVuY3Rpb24gdShlKXtyZXR1cm4gaCgiKD86IixlLCIpKiIpfWZ1bmN0aW9uIGQoZSl7cmV0dXJuIGgoIig/OiIsZSwiKT8iKX0KZnVuY3Rpb24gaCguLi5lKXtyZXR1cm4gZS5tYXAoKGU9PmwoZSkpKS5qb2luKCIiKX1mdW5jdGlvbiBmKC4uLmUpe2NvbnN0IHQ9KGU9PnsKY29uc3QgdD1lW2UubGVuZ3RoLTFdCjtyZXR1cm4ib2JqZWN0Ij09dHlwZW9mIHQmJnQuY29uc3RydWN0b3I9PT1PYmplY3Q/KGUuc3BsaWNlKGUubGVuZ3RoLTEsMSksdCk6e30KfSkoZSk7cmV0dXJuIigiKyh0LmNhcHR1cmU/IiI6Ij86IikrZS5tYXAoKGU9PmwoZSkpKS5qb2luKCJ8IikrIikifQpmdW5jdGlvbiBwKGUpe3JldHVybiBSZWdFeHAoZS50b1N0cmluZygpKyJ8IikuZXhlYygiIikubGVuZ3RoLTF9CmNvbnN0IGI9L1xbKD86W15cXFxdXXxcXC4pKlxdfFwoXD8/fFxcKFsxLTldWzAtOV0qKXxcXC4vCjtmdW5jdGlvbiBtKGUse2pvaW5XaXRoOnR9KXtsZXQgbj0wO3JldHVybiBlLm1hcCgoZT0+e24rPTE7Y29uc3QgdD1uCjtsZXQgaT1sKGUpLHM9IiI7Zm9yKDtpLmxlbmd0aD4wOyl7Y29uc3QgZT1iLmV4ZWMoaSk7aWYoIWUpe3MrPWk7YnJlYWt9CnMrPWkuc3Vic3RyaW5nKDAsZS5pbmRleCksCmk9aS5zdWJzdHJpbmcoZS5pbmRleCtlWzBdLmxlbmd0aCksIlxcIj09PWVbMF1bMF0mJmVbMV0/cys9IlxcIisoTnVtYmVyKGVbMV0pK3QpOihzKz1lWzBdLAoiKCI9PT1lWzBdJiZuKyspfXJldHVybiBzfSkpLm1hcCgoZT0+YCgke2V9KWApKS5qb2luKHQpfQpjb25zdCBFPSJbYS16QS1aXVxcdyoiLHg9IlthLXpBLVpfXVxcdyoiLHc9IlxcYlxcZCsoXFwuXFxkKyk/Iix5PSIoLT8pKFxcYjBbeFhdW2EtZkEtRjAtOV0rfChcXGJcXGQrKFxcLlxcZCopP3xcXC5cXGQrKShbZUVdWy0rXT9cXGQrKT8pIixfPSJcXGIoMGJbMDFdKykiLE89ewpiZWdpbjoiXFxcXFtcXHNcXFNdIixyZWxldmFuY2U6MH0sdj17c2NvcGU6InN0cmluZyIsYmVnaW46IiciLGVuZDoiJyIsCmlsbGVnYWw6IlxcbiIsY29udGFpbnM6W09dfSxrPXtzY29wZToic3RyaW5nIixiZWdpbjonIicsZW5kOiciJyxpbGxlZ2FsOiJcXG4iLApjb250YWluczpbT119LE49KGUsdCxuPXt9KT0+e2NvbnN0IHM9aSh7c2NvcGU6ImNvbW1lbnQiLGJlZ2luOmUsZW5kOnQsCmNvbnRhaW5zOltdfSxuKTtzLmNvbnRhaW5zLnB1c2goe3Njb3BlOiJkb2N0YWciLApiZWdpbjoiWyBdKig/PShUT0RPfEZJWE1FfE5PVEV8QlVHfE9QVElNSVpFfEhBQ0t8WFhYKTopIiwKZW5kOi8oVE9ET3xGSVhNRXxOT1RFfEJVR3xPUFRJTUlaRXxIQUNLfFhYWCk6LyxleGNsdWRlQmVnaW46ITAscmVsZXZhbmNlOjB9KQo7Y29uc3Qgbz1mKCJJIiwiYSIsImlzIiwic28iLCJ1cyIsInRvIiwiYXQiLCJpZiIsImluIiwiaXQiLCJvbiIsL1tBLVphLXpdK1snXShkfHZlfHJlfGxsfHR8c3xuKS8sL1tBLVphLXpdK1stXVthLXpdKy8sL1tBLVphLXpdW2Etel17Mix9LykKO3JldHVybiBzLmNvbnRhaW5zLnB1c2goe2JlZ2luOmgoL1sgXSsvLCIoIixvLC9bLl0/WzpdPyhbLl1bIF18WyBdKS8sIil7M30iKX0pLHMKfSxTPU4oIi8vIiwiJCIpLE09TigiL1xcKiIsIlxcKi8iKSxSPU4oIiMiLCIkIik7dmFyIGo9T2JqZWN0LmZyZWV6ZSh7Cl9fcHJvdG9fXzpudWxsLEFQT1NfU1RSSU5HX01PREU6dixCQUNLU0xBU0hfRVNDQVBFOk8sQklOQVJZX05VTUJFUl9NT0RFOnsKc2NvcGU6Im51bWJlciIsYmVnaW46XyxyZWxldmFuY2U6MH0sQklOQVJZX05VTUJFUl9SRTpfLENPTU1FTlQ6TiwKQ19CTE9DS19DT01NRU5UX01PREU6TSxDX0xJTkVfQ09NTUVOVF9NT0RFOlMsQ19OVU1CRVJfTU9ERTp7c2NvcGU6Im51bWJlciIsCmJlZ2luOnkscmVsZXZhbmNlOjB9LENfTlVNQkVSX1JFOnksRU5EX1NBTUVfQVNfQkVHSU46ZT0+T2JqZWN0LmFzc2lnbihlLHsKIm9uOmJlZ2luIjooZSx0KT0+e3QuZGF0YS5fYmVnaW5NYXRjaD1lWzFdfSwib246ZW5kIjooZSx0KT0+ewp0LmRhdGEuX2JlZ2luTWF0Y2ghPT1lWzFdJiZ0Lmlnbm9yZU1hdGNoKCl9fSksSEFTSF9DT01NRU5UX01PREU6UixJREVOVF9SRTpFLApNQVRDSF9OT1RISU5HX1JFOi9cYlxCLyxNRVRIT0RfR1VBUkQ6e2JlZ2luOiJcXC5cXHMqIit4LHJlbGV2YW5jZTowfSwKTlVNQkVSX01PREU6e3Njb3BlOiJudW1iZXIiLGJlZ2luOncscmVsZXZhbmNlOjB9LE5VTUJFUl9SRTp3LApQSFJBU0FMX1dPUkRTX01PREU6ewpiZWdpbjovXGIoYXxhbnx0aGV8YXJlfEknbXxpc24ndHxkb24ndHxkb2Vzbid0fHdvbid0fGJ1dHxqdXN0fHNob3VsZHxwcmV0dHl8c2ltcGx5fGVub3VnaHxnb25uYXxnb2luZ3x3dGZ8c298c3VjaHx3aWxsfHlvdXx5b3VyfHRoZXl8bGlrZXxtb3JlKVxiLwp9LFFVT1RFX1NUUklOR19NT0RFOmssUkVHRVhQX01PREU6e3Njb3BlOiJyZWdleHAiLGJlZ2luOi9cLyg/PVteL1xuXSpcLykvLAplbmQ6L1wvW2dpbXV5XSovLGNvbnRhaW5zOltPLHtiZWdpbjovXFsvLGVuZDovXF0vLHJlbGV2YW5jZTowLGNvbnRhaW5zOltPXX1dfSwKUkVfU1RBUlRFUlNfUkU6IiF8IT18IT09fCV8JT18JnwmJnwmPXxcXCp8XFwqPXxcXCt8XFwrPXwsfC18LT18Lz18L3w6fDt8PDx8PDw9fDw9fDx8PT09fD09fD18Pj4+PXw+Pj18Pj18Pj4+fD4+fD58XFw/fFxcW3xcXHt8XFwofFxcXnxcXF49fFxcfHxcXHw9fFxcfFxcfHx+IiwKU0hFQkFORzooZT17fSk9Pntjb25zdCB0PS9eIyFbIF0qXC8vCjtyZXR1cm4gZS5iaW5hcnkmJihlLmJlZ2luPWgodCwvLipcYi8sZS5iaW5hcnksL1xiLiovKSksaSh7c2NvcGU6Im1ldGEiLGJlZ2luOnQsCmVuZDovJC8scmVsZXZhbmNlOjAsIm9uOmJlZ2luIjooZSx0KT0+ezAhPT1lLmluZGV4JiZ0Lmlnbm9yZU1hdGNoKCl9fSxlKX0sClRJVExFX01PREU6e3Njb3BlOiJ0aXRsZSIsYmVnaW46RSxyZWxldmFuY2U6MH0sVU5ERVJTQ09SRV9JREVOVF9SRTp4LApVTkRFUlNDT1JFX1RJVExFX01PREU6e3Njb3BlOiJ0aXRsZSIsYmVnaW46eCxyZWxldmFuY2U6MH19KTtmdW5jdGlvbiBBKGUsdCl7CiIuIj09PWUuaW5wdXRbZS5pbmRleC0xXSYmdC5pZ25vcmVNYXRjaCgpfWZ1bmN0aW9uIEkoZSx0KXsKdm9pZCAwIT09ZS5jbGFzc05hbWUmJihlLnNjb3BlPWUuY2xhc3NOYW1lLGRlbGV0ZSBlLmNsYXNzTmFtZSl9ZnVuY3Rpb24gVChlLHQpewp0JiZlLmJlZ2luS2V5d29yZHMmJihlLmJlZ2luPSJcXGIoIitlLmJlZ2luS2V5d29yZHMuc3BsaXQoIiAiKS5qb2luKCJ8IikrIikoPyFcXC4pKD89XFxifFxccykiLAplLl9fYmVmb3JlQmVnaW49QSxlLmtleXdvcmRzPWUua2V5d29yZHN8fGUuYmVnaW5LZXl3b3JkcyxkZWxldGUgZS5iZWdpbktleXdvcmRzLAp2b2lkIDA9PT1lLnJlbGV2YW5jZSYmKGUucmVsZXZhbmNlPTApKX1mdW5jdGlvbiBMKGUsdCl7CkFycmF5LmlzQXJyYXkoZS5pbGxlZ2FsKSYmKGUuaWxsZWdhbD1mKC4uLmUuaWxsZWdhbCkpfWZ1bmN0aW9uIEIoZSx0KXsKaWYoZS5tYXRjaCl7CmlmKGUuYmVnaW58fGUuZW5kKXRocm93IEVycm9yKCJiZWdpbiAmIGVuZCBhcmUgbm90IHN1cHBvcnRlZCB3aXRoIG1hdGNoIikKO2UuYmVnaW49ZS5tYXRjaCxkZWxldGUgZS5tYXRjaH19ZnVuY3Rpb24gUChlLHQpewp2b2lkIDA9PT1lLnJlbGV2YW5jZSYmKGUucmVsZXZhbmNlPTEpfWNvbnN0IEQ9KGUsdCk9PntpZighZS5iZWZvcmVNYXRjaClyZXR1cm4KO2lmKGUuc3RhcnRzKXRocm93IEVycm9yKCJiZWZvcmVNYXRjaCBjYW5ub3QgYmUgdXNlZCB3aXRoIHN0YXJ0cyIpCjtjb25zdCBuPU9iamVjdC5hc3NpZ24oe30sZSk7T2JqZWN0LmtleXMoZSkuZm9yRWFjaCgodD0+e2RlbGV0ZSBlW3RdCn0pKSxlLmtleXdvcmRzPW4ua2V5d29yZHMsZS5iZWdpbj1oKG4uYmVmb3JlTWF0Y2gsZyhuLmJlZ2luKSksZS5zdGFydHM9ewpyZWxldmFuY2U6MCxjb250YWluczpbT2JqZWN0LmFzc2lnbihuLHtlbmRzUGFyZW50OiEwfSldCn0sZS5yZWxldmFuY2U9MCxkZWxldGUgbi5iZWZvcmVNYXRjaAp9LEg9WyJvZiIsImFuZCIsImZvciIsImluIiwibm90Iiwib3IiLCJpZiIsInRoZW4iLCJwYXJlbnQiLCJsaXN0IiwidmFsdWUiXSxDPSJrZXl3b3JkIgo7ZnVuY3Rpb24gJChlLHQsbj1DKXtjb25zdCBpPU9iamVjdC5jcmVhdGUobnVsbCkKO3JldHVybiJzdHJpbmciPT10eXBlb2YgZT9zKG4sZS5zcGxpdCgiICIpKTpBcnJheS5pc0FycmF5KGUpP3MobixlKTpPYmplY3Qua2V5cyhlKS5mb3JFYWNoKChuPT57Ck9iamVjdC5hc3NpZ24oaSwkKGVbbl0sdCxuKSl9KSksaTtmdW5jdGlvbiBzKGUsbil7CnQmJihuPW4ubWFwKChlPT5lLnRvTG93ZXJDYXNlKCkpKSksbi5mb3JFYWNoKCh0PT57Y29uc3Qgbj10LnNwbGl0KCJ8IikKO2lbblswXV09W2UsVShuWzBdLG5bMV0pXX0pKX19ZnVuY3Rpb24gVShlLHQpewpyZXR1cm4gdD9OdW1iZXIodCk6KGU9PkguaW5jbHVkZXMoZS50b0xvd2VyQ2FzZSgpKSkoZSk/MDoxfWNvbnN0IHo9e30sVz1lPT57CmNvbnNvbGUuZXJyb3IoZSl9LFg9KGUsLi4udCk9Pntjb25zb2xlLmxvZygiV0FSTjogIitlLC4uLnQpfSxHPShlLHQpPT57CnpbYCR7ZX0vJHt0fWBdfHwoY29uc29sZS5sb2coYERlcHJlY2F0ZWQgYXMgb2YgJHtlfS4gJHt0fWApLHpbYCR7ZX0vJHt0fWBdPSEwKQp9LEs9RXJyb3IoKTtmdW5jdGlvbiBGKGUsdCx7a2V5Om59KXtsZXQgaT0wO2NvbnN0IHM9ZVtuXSxvPXt9LHI9e30KO2ZvcihsZXQgZT0xO2U8PXQubGVuZ3RoO2UrKylyW2UraV09c1tlXSxvW2UraV09ITAsaSs9cCh0W2UtMV0pCjtlW25dPXIsZVtuXS5fZW1pdD1vLGVbbl0uX211bHRpPSEwfWZ1bmN0aW9uIFooZSl7KGU9PnsKZS5zY29wZSYmIm9iamVjdCI9PXR5cGVvZiBlLnNjb3BlJiZudWxsIT09ZS5zY29wZSYmKGUuYmVnaW5TY29wZT1lLnNjb3BlLApkZWxldGUgZS5zY29wZSl9KShlKSwic3RyaW5nIj09dHlwZW9mIGUuYmVnaW5TY29wZSYmKGUuYmVnaW5TY29wZT17Cl93cmFwOmUuYmVnaW5TY29wZX0pLCJzdHJpbmciPT10eXBlb2YgZS5lbmRTY29wZSYmKGUuZW5kU2NvcGU9e193cmFwOmUuZW5kU2NvcGUKfSksKGU9PntpZihBcnJheS5pc0FycmF5KGUuYmVnaW4pKXsKaWYoZS5za2lwfHxlLmV4Y2x1ZGVCZWdpbnx8ZS5yZXR1cm5CZWdpbil0aHJvdyBXKCJza2lwLCBleGNsdWRlQmVnaW4sIHJldHVybkJlZ2luIG5vdCBjb21wYXRpYmxlIHdpdGggYmVnaW5TY29wZToge30iKSwKSwo7aWYoIm9iamVjdCIhPXR5cGVvZiBlLmJlZ2luU2NvcGV8fG51bGw9PT1lLmJlZ2luU2NvcGUpdGhyb3cgVygiYmVnaW5TY29wZSBtdXN0IGJlIG9iamVjdCIpLApLO0YoZSxlLmJlZ2luLHtrZXk6ImJlZ2luU2NvcGUifSksZS5iZWdpbj1tKGUuYmVnaW4se2pvaW5XaXRoOiIifSl9fSkoZSksKGU9PnsKaWYoQXJyYXkuaXNBcnJheShlLmVuZCkpewppZihlLnNraXB8fGUuZXhjbHVkZUVuZHx8ZS5yZXR1cm5FbmQpdGhyb3cgVygic2tpcCwgZXhjbHVkZUVuZCwgcmV0dXJuRW5kIG5vdCBjb21wYXRpYmxlIHdpdGggZW5kU2NvcGU6IHt9IiksCksKO2lmKCJvYmplY3QiIT10eXBlb2YgZS5lbmRTY29wZXx8bnVsbD09PWUuZW5kU2NvcGUpdGhyb3cgVygiZW5kU2NvcGUgbXVzdCBiZSBvYmplY3QiKSwKSztGKGUsZS5lbmQse2tleToiZW5kU2NvcGUifSksZS5lbmQ9bShlLmVuZCx7am9pbldpdGg6IiJ9KX19KShlKX1mdW5jdGlvbiBWKGUpewpmdW5jdGlvbiB0KHQsbil7CnJldHVybiBSZWdFeHAobCh0KSwibSIrKGUuY2FzZV9pbnNlbnNpdGl2ZT8iaSI6IiIpKyhlLnVuaWNvZGVSZWdleD8idSI6IiIpKyhuPyJnIjoiIikpCn1jbGFzcyBue2NvbnN0cnVjdG9yKCl7CnRoaXMubWF0Y2hJbmRleGVzPXt9LHRoaXMucmVnZXhlcz1bXSx0aGlzLm1hdGNoQXQ9MSx0aGlzLnBvc2l0aW9uPTB9CmFkZFJ1bGUoZSx0KXsKdC5wb3NpdGlvbj10aGlzLnBvc2l0aW9uKyssdGhpcy5tYXRjaEluZGV4ZXNbdGhpcy5tYXRjaEF0XT10LHRoaXMucmVnZXhlcy5wdXNoKFt0LGVdKSwKdGhpcy5tYXRjaEF0Kz1wKGUpKzF9Y29tcGlsZSgpezA9PT10aGlzLnJlZ2V4ZXMubGVuZ3RoJiYodGhpcy5leGVjPSgpPT5udWxsKQo7Y29uc3QgZT10aGlzLnJlZ2V4ZXMubWFwKChlPT5lWzFdKSk7dGhpcy5tYXRjaGVyUmU9dChtKGUse2pvaW5XaXRoOiJ8Igp9KSwhMCksdGhpcy5sYXN0SW5kZXg9MH1leGVjKGUpe3RoaXMubWF0Y2hlclJlLmxhc3RJbmRleD10aGlzLmxhc3RJbmRleAo7Y29uc3QgdD10aGlzLm1hdGNoZXJSZS5leGVjKGUpO2lmKCF0KXJldHVybiBudWxsCjtjb25zdCBuPXQuZmluZEluZGV4KCgoZSx0KT0+dD4wJiZ2b2lkIDAhPT1lKSksaT10aGlzLm1hdGNoSW5kZXhlc1tuXQo7cmV0dXJuIHQuc3BsaWNlKDAsbiksT2JqZWN0LmFzc2lnbih0LGkpfX1jbGFzcyBze2NvbnN0cnVjdG9yKCl7CnRoaXMucnVsZXM9W10sdGhpcy5tdWx0aVJlZ2V4ZXM9W10sCnRoaXMuY291bnQ9MCx0aGlzLmxhc3RJbmRleD0wLHRoaXMucmVnZXhJbmRleD0wfWdldE1hdGNoZXIoZSl7CmlmKHRoaXMubXVsdGlSZWdleGVzW2VdKXJldHVybiB0aGlzLm11bHRpUmVnZXhlc1tlXTtjb25zdCB0PW5ldyBuCjtyZXR1cm4gdGhpcy5ydWxlcy5zbGljZShlKS5mb3JFYWNoKCgoW2Usbl0pPT50LmFkZFJ1bGUoZSxuKSkpLAp0LmNvbXBpbGUoKSx0aGlzLm11bHRpUmVnZXhlc1tlXT10LHR9cmVzdW1pbmdTY2FuQXRTYW1lUG9zaXRpb24oKXsKcmV0dXJuIDAhPT10aGlzLnJlZ2V4SW5kZXh9Y29uc2lkZXJBbGwoKXt0aGlzLnJlZ2V4SW5kZXg9MH1hZGRSdWxlKGUsdCl7CnRoaXMucnVsZXMucHVzaChbZSx0XSksImJlZ2luIj09PXQudHlwZSYmdGhpcy5jb3VudCsrfWV4ZWMoZSl7CmNvbnN0IHQ9dGhpcy5nZXRNYXRjaGVyKHRoaXMucmVnZXhJbmRleCk7dC5sYXN0SW5kZXg9dGhpcy5sYXN0SW5kZXgKO2xldCBuPXQuZXhlYyhlKQo7aWYodGhpcy5yZXN1bWluZ1NjYW5BdFNhbWVQb3NpdGlvbigpKWlmKG4mJm4uaW5kZXg9PT10aGlzLmxhc3RJbmRleCk7ZWxzZXsKY29uc3QgdD10aGlzLmdldE1hdGNoZXIoMCk7dC5sYXN0SW5kZXg9dGhpcy5sYXN0SW5kZXgrMSxuPXQuZXhlYyhlKX0KcmV0dXJuIG4mJih0aGlzLnJlZ2V4SW5kZXgrPW4ucG9zaXRpb24rMSwKdGhpcy5yZWdleEluZGV4PT09dGhpcy5jb3VudCYmdGhpcy5jb25zaWRlckFsbCgpKSxufX0KaWYoZS5jb21waWxlckV4dGVuc2lvbnN8fChlLmNvbXBpbGVyRXh0ZW5zaW9ucz1bXSksCmUuY29udGFpbnMmJmUuY29udGFpbnMuaW5jbHVkZXMoInNlbGYiKSl0aHJvdyBFcnJvcigiRVJSOiBjb250YWlucyBgc2VsZmAgaXMgbm90IHN1cHBvcnRlZCBhdCB0aGUgdG9wLWxldmVsIG9mIGEgbGFuZ3VhZ2UuICBTZWUgZG9jdW1lbnRhdGlvbi4iKQo7cmV0dXJuIGUuY2xhc3NOYW1lQWxpYXNlcz1pKGUuY2xhc3NOYW1lQWxpYXNlc3x8e30pLGZ1bmN0aW9uIG4obyxyKXtjb25zdCBhPW8KO2lmKG8uaXNDb21waWxlZClyZXR1cm4gYQo7W0ksQixaLERdLmZvckVhY2goKGU9PmUobyxyKSkpLGUuY29tcGlsZXJFeHRlbnNpb25zLmZvckVhY2goKGU9PmUobyxyKSkpLApvLl9fYmVmb3JlQmVnaW49bnVsbCxbVCxMLFBdLmZvckVhY2goKGU9PmUobyxyKSkpLG8uaXNDb21waWxlZD0hMDtsZXQgYz1udWxsCjtyZXR1cm4ib2JqZWN0Ij09dHlwZW9mIG8ua2V5d29yZHMmJm8ua2V5d29yZHMuJHBhdHRlcm4mJihvLmtleXdvcmRzPU9iamVjdC5hc3NpZ24oe30sby5rZXl3b3JkcyksCmM9by5rZXl3b3Jkcy4kcGF0dGVybiwKZGVsZXRlIG8ua2V5d29yZHMuJHBhdHRlcm4pLGM9Y3x8L1x3Ky8sby5rZXl3b3JkcyYmKG8ua2V5d29yZHM9JChvLmtleXdvcmRzLGUuY2FzZV9pbnNlbnNpdGl2ZSkpLAphLmtleXdvcmRQYXR0ZXJuUmU9dChjLCEwKSwKciYmKG8uYmVnaW58fChvLmJlZ2luPS9cQnxcYi8pLGEuYmVnaW5SZT10KGEuYmVnaW4pLG8uZW5kfHxvLmVuZHNXaXRoUGFyZW50fHwoby5lbmQ9L1xCfFxiLyksCm8uZW5kJiYoYS5lbmRSZT10KGEuZW5kKSksCmEudGVybWluYXRvckVuZD1sKGEuZW5kKXx8IiIsby5lbmRzV2l0aFBhcmVudCYmci50ZXJtaW5hdG9yRW5kJiYoYS50ZXJtaW5hdG9yRW5kKz0oby5lbmQ/InwiOiIiKStyLnRlcm1pbmF0b3JFbmQpKSwKby5pbGxlZ2FsJiYoYS5pbGxlZ2FsUmU9dChvLmlsbGVnYWwpKSwKby5jb250YWluc3x8KG8uY29udGFpbnM9W10pLG8uY29udGFpbnM9W10uY29uY2F0KC4uLm8uY29udGFpbnMubWFwKChlPT4oZT0+KGUudmFyaWFudHMmJiFlLmNhY2hlZFZhcmlhbnRzJiYoZS5jYWNoZWRWYXJpYW50cz1lLnZhcmlhbnRzLm1hcCgodD0+aShlLHsKdmFyaWFudHM6bnVsbH0sdCkpKSksZS5jYWNoZWRWYXJpYW50cz9lLmNhY2hlZFZhcmlhbnRzOnEoZSk/aShlLHsKc3RhcnRzOmUuc3RhcnRzP2koZS5zdGFydHMpOm51bGwKfSk6T2JqZWN0LmlzRnJvemVuKGUpP2koZSk6ZSkpKCJzZWxmIj09PWU/bzplKSkpKSxvLmNvbnRhaW5zLmZvckVhY2goKGU9PntuKGUsYSkKfSkpLG8uc3RhcnRzJiZuKG8uc3RhcnRzLHIpLGEubWF0Y2hlcj0oZT0+e2NvbnN0IHQ9bmV3IHMKO3JldHVybiBlLmNvbnRhaW5zLmZvckVhY2goKGU9PnQuYWRkUnVsZShlLmJlZ2luLHtydWxlOmUsdHlwZToiYmVnaW4iCn0pKSksZS50ZXJtaW5hdG9yRW5kJiZ0LmFkZFJ1bGUoZS50ZXJtaW5hdG9yRW5kLHt0eXBlOiJlbmQiCn0pLGUuaWxsZWdhbCYmdC5hZGRSdWxlKGUuaWxsZWdhbCx7dHlwZToiaWxsZWdhbCJ9KSx0fSkoYSksYX0oZSl9ZnVuY3Rpb24gcShlKXsKcmV0dXJuISFlJiYoZS5lbmRzV2l0aFBhcmVudHx8cShlLnN0YXJ0cykpfWNsYXNzIEogZXh0ZW5kcyBFcnJvcnsKY29uc3RydWN0b3IoZSx0KXtzdXBlcihlKSx0aGlzLm5hbWU9IkhUTUxJbmplY3Rpb25FcnJvciIsdGhpcy5odG1sPXR9fQpjb25zdCBZPW4sUT1pLGVlPVN5bWJvbCgibm9tYXRjaCIpLHRlPW49PnsKY29uc3QgaT1PYmplY3QuY3JlYXRlKG51bGwpLHM9T2JqZWN0LmNyZWF0ZShudWxsKSxvPVtdO2xldCByPSEwCjtjb25zdCBhPSJDb3VsZCBub3QgZmluZCB0aGUgbGFuZ3VhZ2UgJ3t9JywgZGlkIHlvdSBmb3JnZXQgdG8gbG9hZC9pbmNsdWRlIGEgbGFuZ3VhZ2UgbW9kdWxlPyIsbD17CmRpc2FibGVBdXRvZGV0ZWN0OiEwLG5hbWU6IlBsYWluIHRleHQiLGNvbnRhaW5zOltdfTtsZXQgcD17Cmlnbm9yZVVuZXNjYXBlZEhUTUw6ITEsdGhyb3dVbmVzY2FwZWRIVE1MOiExLG5vSGlnaGxpZ2h0UmU6L14obm8tP2hpZ2hsaWdodCkkL2ksCmxhbmd1YWdlRGV0ZWN0UmU6L1xibGFuZyg/OnVhZ2UpPy0oW1x3LV0rKVxiL2ksY2xhc3NQcmVmaXg6ImhsanMtIiwKY3NzU2VsZWN0b3I6InByZSBjb2RlIixsYW5ndWFnZXM6bnVsbCxfX2VtaXR0ZXI6Y307ZnVuY3Rpb24gYihlKXsKcmV0dXJuIHAubm9IaWdobGlnaHRSZS50ZXN0KGUpfWZ1bmN0aW9uIG0oZSx0LG4pe2xldCBpPSIiLHM9IiIKOyJvYmplY3QiPT10eXBlb2YgdD8oaT1lLApuPXQuaWdub3JlSWxsZWdhbHMscz10Lmxhbmd1YWdlKTooRygiMTAuNy4wIiwiaGlnaGxpZ2h0KGxhbmcsIGNvZGUsIC4uLmFyZ3MpIGhhcyBiZWVuIGRlcHJlY2F0ZWQuIiksCkcoIjEwLjcuMCIsIlBsZWFzZSB1c2UgaGlnaGxpZ2h0KGNvZGUsIG9wdGlvbnMpIGluc3RlYWQuXG5odHRwczovL2dpdGh1Yi5jb20vaGlnaGxpZ2h0anMvaGlnaGxpZ2h0LmpzL2lzc3Vlcy8yMjc3IiksCnM9ZSxpPXQpLHZvaWQgMD09PW4mJihuPSEwKTtjb25zdCBvPXtjb2RlOmksbGFuZ3VhZ2U6c307TigiYmVmb3JlOmhpZ2hsaWdodCIsbykKO2NvbnN0IHI9by5yZXN1bHQ/by5yZXN1bHQ6RShvLmxhbmd1YWdlLG8uY29kZSxuKQo7cmV0dXJuIHIuY29kZT1vLmNvZGUsTigiYWZ0ZXI6aGlnaGxpZ2h0IixyKSxyfWZ1bmN0aW9uIEUoZSxuLHMsbyl7CmNvbnN0IGM9T2JqZWN0LmNyZWF0ZShudWxsKTtmdW5jdGlvbiBsKCl7aWYoIU4ua2V5d29yZHMpcmV0dXJuIHZvaWQgTS5hZGRUZXh0KFIpCjtsZXQgZT0wO04ua2V5d29yZFBhdHRlcm5SZS5sYXN0SW5kZXg9MDtsZXQgdD1OLmtleXdvcmRQYXR0ZXJuUmUuZXhlYyhSKSxuPSIiCjtmb3IoO3Q7KXtuKz1SLnN1YnN0cmluZyhlLHQuaW5kZXgpCjtjb25zdCBzPV8uY2FzZV9pbnNlbnNpdGl2ZT90WzBdLnRvTG93ZXJDYXNlKCk6dFswXSxvPShpPXMsTi5rZXl3b3Jkc1tpXSk7aWYobyl7CmNvbnN0W2UsaV09bwo7aWYoTS5hZGRUZXh0KG4pLG49IiIsY1tzXT0oY1tzXXx8MCkrMSxjW3NdPD03JiYoais9aSksZS5zdGFydHNXaXRoKCJfIikpbis9dFswXTtlbHNlewpjb25zdCBuPV8uY2xhc3NOYW1lQWxpYXNlc1tlXXx8ZTt1KHRbMF0sbil9fWVsc2Ugbis9dFswXQo7ZT1OLmtleXdvcmRQYXR0ZXJuUmUubGFzdEluZGV4LHQ9Ti5rZXl3b3JkUGF0dGVyblJlLmV4ZWMoUil9dmFyIGkKO24rPVIuc3Vic3RyaW5nKGUpLE0uYWRkVGV4dChuKX1mdW5jdGlvbiBnKCl7bnVsbCE9Ti5zdWJMYW5ndWFnZT8oKCk9PnsKaWYoIiI9PT1SKXJldHVybjtsZXQgZT1udWxsO2lmKCJzdHJpbmciPT10eXBlb2YgTi5zdWJMYW5ndWFnZSl7CmlmKCFpW04uc3ViTGFuZ3VhZ2VdKXJldHVybiB2b2lkIE0uYWRkVGV4dChSKQo7ZT1FKE4uc3ViTGFuZ3VhZ2UsUiwhMCxTW04uc3ViTGFuZ3VhZ2VdKSxTW04uc3ViTGFuZ3VhZ2VdPWUuX3RvcAp9ZWxzZSBlPXgoUixOLnN1Ykxhbmd1YWdlLmxlbmd0aD9OLnN1Ykxhbmd1YWdlOm51bGwpCjtOLnJlbGV2YW5jZT4wJiYoais9ZS5yZWxldmFuY2UpLE0uX19hZGRTdWJsYW5ndWFnZShlLl9lbWl0dGVyLGUubGFuZ3VhZ2UpCn0pKCk6bCgpLFI9IiJ9ZnVuY3Rpb24gdShlLHQpewoiIiE9PWUmJihNLnN0YXJ0U2NvcGUodCksTS5hZGRUZXh0KGUpLE0uZW5kU2NvcGUoKSl9ZnVuY3Rpb24gZChlLHQpe2xldCBuPTEKO2NvbnN0IGk9dC5sZW5ndGgtMTtmb3IoO248PWk7KXtpZighZS5fZW1pdFtuXSl7bisrO2NvbnRpbnVlfQpjb25zdCBpPV8uY2xhc3NOYW1lQWxpYXNlc1tlW25dXXx8ZVtuXSxzPXRbbl07aT91KHMsaSk6KFI9cyxsKCksUj0iIiksbisrfX0KZnVuY3Rpb24gaChlLHQpewpyZXR1cm4gZS5zY29wZSYmInN0cmluZyI9PXR5cGVvZiBlLnNjb3BlJiZNLm9wZW5Ob2RlKF8uY2xhc3NOYW1lQWxpYXNlc1tlLnNjb3BlXXx8ZS5zY29wZSksCmUuYmVnaW5TY29wZSYmKGUuYmVnaW5TY29wZS5fd3JhcD8odShSLF8uY2xhc3NOYW1lQWxpYXNlc1tlLmJlZ2luU2NvcGUuX3dyYXBdfHxlLmJlZ2luU2NvcGUuX3dyYXApLApSPSIiKTplLmJlZ2luU2NvcGUuX211bHRpJiYoZChlLmJlZ2luU2NvcGUsdCksUj0iIikpLE49T2JqZWN0LmNyZWF0ZShlLHtwYXJlbnQ6ewp2YWx1ZTpOfX0pLE59ZnVuY3Rpb24gZihlLG4saSl7bGV0IHM9KChlLHQpPT57Y29uc3Qgbj1lJiZlLmV4ZWModCkKO3JldHVybiBuJiYwPT09bi5pbmRleH0pKGUuZW5kUmUsaSk7aWYocyl7aWYoZVsib246ZW5kIl0pe2NvbnN0IGk9bmV3IHQoZSkKO2VbIm9uOmVuZCJdKG4saSksaS5pc01hdGNoSWdub3JlZCYmKHM9ITEpfWlmKHMpewpmb3IoO2UuZW5kc1BhcmVudCYmZS5wYXJlbnQ7KWU9ZS5wYXJlbnQ7cmV0dXJuIGV9fQppZihlLmVuZHNXaXRoUGFyZW50KXJldHVybiBmKGUucGFyZW50LG4saSl9ZnVuY3Rpb24gYihlKXsKcmV0dXJuIDA9PT1OLm1hdGNoZXIucmVnZXhJbmRleD8oUis9ZVswXSwxKTooVD0hMCwwKX1mdW5jdGlvbiBtKGUpewpjb25zdCB0PWVbMF0saT1uLnN1YnN0cmluZyhlLmluZGV4KSxzPWYoTixlLGkpO2lmKCFzKXJldHVybiBlZTtjb25zdCBvPU4KO04uZW5kU2NvcGUmJk4uZW5kU2NvcGUuX3dyYXA/KGcoKSwKdSh0LE4uZW5kU2NvcGUuX3dyYXApKTpOLmVuZFNjb3BlJiZOLmVuZFNjb3BlLl9tdWx0aT8oZygpLApkKE4uZW5kU2NvcGUsZSkpOm8uc2tpcD9SKz10OihvLnJldHVybkVuZHx8by5leGNsdWRlRW5kfHwoUis9dCksCmcoKSxvLmV4Y2x1ZGVFbmQmJihSPXQpKTtkb3sKTi5zY29wZSYmTS5jbG9zZU5vZGUoKSxOLnNraXB8fE4uc3ViTGFuZ3VhZ2V8fChqKz1OLnJlbGV2YW5jZSksTj1OLnBhcmVudAp9d2hpbGUoTiE9PXMucGFyZW50KTtyZXR1cm4gcy5zdGFydHMmJmgocy5zdGFydHMsZSksby5yZXR1cm5FbmQ/MDp0Lmxlbmd0aH0KbGV0IHc9e307ZnVuY3Rpb24geShpLG8pe2NvbnN0IGE9byYmb1swXTtpZihSKz1pLG51bGw9PWEpcmV0dXJuIGcoKSwwCjtpZigiYmVnaW4iPT09dy50eXBlJiYiZW5kIj09PW8udHlwZSYmdy5pbmRleD09PW8uaW5kZXgmJiIiPT09YSl7CmlmKFIrPW4uc2xpY2Uoby5pbmRleCxvLmluZGV4KzEpLCFyKXtjb25zdCB0PUVycm9yKGAwIHdpZHRoIG1hdGNoIHJlZ2V4ICgke2V9KWApCjt0aHJvdyB0Lmxhbmd1YWdlTmFtZT1lLHQuYmFkUnVsZT13LnJ1bGUsdH1yZXR1cm4gMX0KaWYodz1vLCJiZWdpbiI9PT1vLnR5cGUpcmV0dXJuKGU9PnsKY29uc3Qgbj1lWzBdLGk9ZS5ydWxlLHM9bmV3IHQoaSksbz1baS5fX2JlZm9yZUJlZ2luLGlbIm9uOmJlZ2luIl1dCjtmb3IoY29uc3QgdCBvZiBvKWlmKHQmJih0KGUscykscy5pc01hdGNoSWdub3JlZCkpcmV0dXJuIGIobikKO3JldHVybiBpLnNraXA/Uis9bjooaS5leGNsdWRlQmVnaW4mJihSKz1uKSwKZygpLGkucmV0dXJuQmVnaW58fGkuZXhjbHVkZUJlZ2lufHwoUj1uKSksaChpLGUpLGkucmV0dXJuQmVnaW4/MDpuLmxlbmd0aH0pKG8pCjtpZigiaWxsZWdhbCI9PT1vLnR5cGUmJiFzKXsKY29uc3QgZT1FcnJvcignSWxsZWdhbCBsZXhlbWUgIicrYSsnIiBmb3IgbW9kZSAiJysoTi5zY29wZXx8Ijx1bm5hbWVkPiIpKyciJykKO3Rocm93IGUubW9kZT1OLGV9aWYoImVuZCI9PT1vLnR5cGUpe2NvbnN0IGU9bShvKTtpZihlIT09ZWUpcmV0dXJuIGV9CmlmKCJpbGxlZ2FsIj09PW8udHlwZSYmIiI9PT1hKXJldHVybiAxCjtpZihJPjFlNSYmST4zKm8uaW5kZXgpdGhyb3cgRXJyb3IoInBvdGVudGlhbCBpbmZpbml0ZSBsb29wLCB3YXkgbW9yZSBpdGVyYXRpb25zIHRoYW4gbWF0Y2hlcyIpCjtyZXR1cm4gUis9YSxhLmxlbmd0aH1jb25zdCBfPU8oZSkKO2lmKCFfKXRocm93IFcoYS5yZXBsYWNlKCJ7fSIsZSkpLEVycm9yKCdVbmtub3duIGxhbmd1YWdlOiAiJytlKyciJykKO2NvbnN0IHY9VihfKTtsZXQgaz0iIixOPW98fHY7Y29uc3QgUz17fSxNPW5ldyBwLl9fZW1pdHRlcihwKTsoKCk9Pntjb25zdCBlPVtdCjtmb3IobGV0IHQ9Tjt0IT09Xzt0PXQucGFyZW50KXQuc2NvcGUmJmUudW5zaGlmdCh0LnNjb3BlKQo7ZS5mb3JFYWNoKChlPT5NLm9wZW5Ob2RlKGUpKSl9KSgpO2xldCBSPSIiLGo9MCxBPTAsST0wLFQ9ITE7dHJ5ewppZihfLl9fZW1pdFRva2VucylfLl9fZW1pdFRva2VucyhuLE0pO2Vsc2V7Zm9yKE4ubWF0Y2hlci5jb25zaWRlckFsbCgpOzspewpJKyssVD9UPSExOk4ubWF0Y2hlci5jb25zaWRlckFsbCgpLE4ubWF0Y2hlci5sYXN0SW5kZXg9QQo7Y29uc3QgZT1OLm1hdGNoZXIuZXhlYyhuKTtpZighZSlicmVhaztjb25zdCB0PXkobi5zdWJzdHJpbmcoQSxlLmluZGV4KSxlKQo7QT1lLmluZGV4K3R9eShuLnN1YnN0cmluZyhBKSl9cmV0dXJuIE0uZmluYWxpemUoKSxrPU0udG9IVE1MKCkse2xhbmd1YWdlOmUsCnZhbHVlOmsscmVsZXZhbmNlOmosaWxsZWdhbDohMSxfZW1pdHRlcjpNLF90b3A6Tn19Y2F0Y2godCl7CmlmKHQubWVzc2FnZSYmdC5tZXNzYWdlLmluY2x1ZGVzKCJJbGxlZ2FsIikpcmV0dXJue2xhbmd1YWdlOmUsdmFsdWU6WShuKSwKaWxsZWdhbDohMCxyZWxldmFuY2U6MCxfaWxsZWdhbEJ5OnttZXNzYWdlOnQubWVzc2FnZSxpbmRleDpBLApjb250ZXh0Om4uc2xpY2UoQS0xMDAsQSsxMDApLG1vZGU6dC5tb2RlLHJlc3VsdFNvRmFyOmt9LF9lbWl0dGVyOk19O2lmKHIpcmV0dXJuewpsYW5ndWFnZTplLHZhbHVlOlkobiksaWxsZWdhbDohMSxyZWxldmFuY2U6MCxlcnJvclJhaXNlZDp0LF9lbWl0dGVyOk0sX3RvcDpOfQo7dGhyb3cgdH19ZnVuY3Rpb24geChlLHQpe3Q9dHx8cC5sYW5ndWFnZXN8fE9iamVjdC5rZXlzKGkpO2NvbnN0IG49KGU9PnsKY29uc3QgdD17dmFsdWU6WShlKSxpbGxlZ2FsOiExLHJlbGV2YW5jZTowLF90b3A6bCxfZW1pdHRlcjpuZXcgcC5fX2VtaXR0ZXIocCl9CjtyZXR1cm4gdC5fZW1pdHRlci5hZGRUZXh0KGUpLHR9KShlKSxzPXQuZmlsdGVyKE8pLmZpbHRlcihrKS5tYXAoKHQ9PkUodCxlLCExKSkpCjtzLnVuc2hpZnQobik7Y29uc3Qgbz1zLnNvcnQoKChlLHQpPT57CmlmKGUucmVsZXZhbmNlIT09dC5yZWxldmFuY2UpcmV0dXJuIHQucmVsZXZhbmNlLWUucmVsZXZhbmNlCjtpZihlLmxhbmd1YWdlJiZ0Lmxhbmd1YWdlKXtpZihPKGUubGFuZ3VhZ2UpLnN1cGVyc2V0T2Y9PT10Lmxhbmd1YWdlKXJldHVybiAxCjtpZihPKHQubGFuZ3VhZ2UpLnN1cGVyc2V0T2Y9PT1lLmxhbmd1YWdlKXJldHVybi0xfXJldHVybiAwfSkpLFtyLGFdPW8sYz1yCjtyZXR1cm4gYy5zZWNvbmRCZXN0PWEsY31mdW5jdGlvbiB3KGUpe2xldCB0PW51bGw7Y29uc3Qgbj0oZT0+ewpsZXQgdD1lLmNsYXNzTmFtZSsiICI7dCs9ZS5wYXJlbnROb2RlP2UucGFyZW50Tm9kZS5jbGFzc05hbWU6IiIKO2NvbnN0IG49cC5sYW5ndWFnZURldGVjdFJlLmV4ZWModCk7aWYobil7Y29uc3QgdD1PKG5bMV0pCjtyZXR1cm4gdHx8KFgoYS5yZXBsYWNlKCJ7fSIsblsxXSkpLApYKCJGYWxsaW5nIGJhY2sgdG8gbm8taGlnaGxpZ2h0IG1vZGUgZm9yIHRoaXMgYmxvY2suIixlKSksdD9uWzFdOiJuby1oaWdobGlnaHQifQpyZXR1cm4gdC5zcGxpdCgvXHMrLykuZmluZCgoZT0+YihlKXx8TyhlKSkpfSkoZSk7aWYoYihuKSlyZXR1cm4KO2lmKE4oImJlZm9yZTpoaWdobGlnaHRFbGVtZW50Iix7ZWw6ZSxsYW5ndWFnZTpuCn0pLGUuZGF0YXNldC5oaWdobGlnaHRlZClyZXR1cm4gdm9pZCBjb25zb2xlLmxvZygiRWxlbWVudCBwcmV2aW91c2x5IGhpZ2hsaWdodGVkLiBUbyBoaWdobGlnaHQgYWdhaW4sIGZpcnN0IHVuc2V0IGBkYXRhc2V0LmhpZ2hsaWdodGVkYC4iLGUpCjtpZihlLmNoaWxkcmVuLmxlbmd0aD4wJiYocC5pZ25vcmVVbmVzY2FwZWRIVE1MfHwoY29uc29sZS53YXJuKCJPbmUgb2YgeW91ciBjb2RlIGJsb2NrcyBpbmNsdWRlcyB1bmVzY2FwZWQgSFRNTC4gVGhpcyBpcyBhIHBvdGVudGlhbGx5IHNlcmlvdXMgc2VjdXJpdHkgcmlzay4iKSwKY29uc29sZS53YXJuKCJodHRwczovL2dpdGh1Yi5jb20vaGlnaGxpZ2h0anMvaGlnaGxpZ2h0LmpzL3dpa2kvc2VjdXJpdHkiKSwKY29uc29sZS53YXJuKCJUaGUgZWxlbWVudCB3aXRoIHVuZXNjYXBlZCBIVE1MOiIpLApjb25zb2xlLndhcm4oZSkpLHAudGhyb3dVbmVzY2FwZWRIVE1MKSl0aHJvdyBuZXcgSigiT25lIG9mIHlvdXIgY29kZSBibG9ja3MgaW5jbHVkZXMgdW5lc2NhcGVkIEhUTUwuIixlLmlubmVySFRNTCkKO3Q9ZTtjb25zdCBpPXQudGV4dENvbnRlbnQsbz1uP20oaSx7bGFuZ3VhZ2U6bixpZ25vcmVJbGxlZ2FsczohMH0pOngoaSkKO2UuaW5uZXJIVE1MPW8udmFsdWUsZS5kYXRhc2V0LmhpZ2hsaWdodGVkPSJ5ZXMiLCgoZSx0LG4pPT57Y29uc3QgaT10JiZzW3RdfHxuCjtlLmNsYXNzTGlzdC5hZGQoImhsanMiKSxlLmNsYXNzTGlzdC5hZGQoImxhbmd1YWdlLSIraSkKfSkoZSxuLG8ubGFuZ3VhZ2UpLGUucmVzdWx0PXtsYW5ndWFnZTpvLmxhbmd1YWdlLHJlOm8ucmVsZXZhbmNlLApyZWxldmFuY2U6by5yZWxldmFuY2V9LG8uc2Vjb25kQmVzdCYmKGUuc2Vjb25kQmVzdD17Cmxhbmd1YWdlOm8uc2Vjb25kQmVzdC5sYW5ndWFnZSxyZWxldmFuY2U6by5zZWNvbmRCZXN0LnJlbGV2YW5jZQp9KSxOKCJhZnRlcjpoaWdobGlnaHRFbGVtZW50Iix7ZWw6ZSxyZXN1bHQ6byx0ZXh0Oml9KX1sZXQgeT0hMTtmdW5jdGlvbiBfKCl7CiJsb2FkaW5nIiE9PWRvY3VtZW50LnJlYWR5U3RhdGU/ZG9jdW1lbnQucXVlcnlTZWxlY3RvckFsbChwLmNzc1NlbGVjdG9yKS5mb3JFYWNoKHcpOnk9ITAKfWZ1bmN0aW9uIE8oZSl7cmV0dXJuIGU9KGV8fCIiKS50b0xvd2VyQ2FzZSgpLGlbZV18fGlbc1tlXV19CmZ1bmN0aW9uIHYoZSx7bGFuZ3VhZ2VOYW1lOnR9KXsic3RyaW5nIj09dHlwZW9mIGUmJihlPVtlXSksZS5mb3JFYWNoKChlPT57CnNbZS50b0xvd2VyQ2FzZSgpXT10fSkpfWZ1bmN0aW9uIGsoZSl7Y29uc3QgdD1PKGUpCjtyZXR1cm4gdCYmIXQuZGlzYWJsZUF1dG9kZXRlY3R9ZnVuY3Rpb24gTihlLHQpe2NvbnN0IG49ZTtvLmZvckVhY2goKGU9PnsKZVtuXSYmZVtuXSh0KX0pKX0KInVuZGVmaW5lZCIhPXR5cGVvZiB3aW5kb3cmJndpbmRvdy5hZGRFdmVudExpc3RlbmVyJiZ3aW5kb3cuYWRkRXZlbnRMaXN0ZW5lcigiRE9NQ29udGVudExvYWRlZCIsKCgpPT57CnkmJl8oKX0pLCExKSxPYmplY3QuYXNzaWduKG4se2hpZ2hsaWdodDptLGhpZ2hsaWdodEF1dG86eCxoaWdobGlnaHRBbGw6XywKaGlnaGxpZ2h0RWxlbWVudDp3LApoaWdobGlnaHRCbG9jazplPT4oRygiMTAuNy4wIiwiaGlnaGxpZ2h0QmxvY2sgd2lsbCBiZSByZW1vdmVkIGVudGlyZWx5IGluIHYxMi4wIiksCkcoIjEwLjcuMCIsIlBsZWFzZSB1c2UgaGlnaGxpZ2h0RWxlbWVudCBub3cuIiksdyhlKSksY29uZmlndXJlOmU9PntwPVEocCxlKX0sCmluaXRIaWdobGlnaHRpbmc6KCk9PnsKXygpLEcoIjEwLjYuMCIsImluaXRIaWdobGlnaHRpbmcoKSBkZXByZWNhdGVkLiAgVXNlIGhpZ2hsaWdodEFsbCgpIG5vdy4iKX0sCmluaXRIaWdobGlnaHRpbmdPbkxvYWQ6KCk9PnsKXygpLEcoIjEwLjYuMCIsImluaXRIaWdobGlnaHRpbmdPbkxvYWQoKSBkZXByZWNhdGVkLiAgVXNlIGhpZ2hsaWdodEFsbCgpIG5vdy4iKQp9LHJlZ2lzdGVyTGFuZ3VhZ2U6KGUsdCk9PntsZXQgcz1udWxsO3RyeXtzPXQobil9Y2F0Y2godCl7CmlmKFcoIkxhbmd1YWdlIGRlZmluaXRpb24gZm9yICd7fScgY291bGQgbm90IGJlIHJlZ2lzdGVyZWQuIi5yZXBsYWNlKCJ7fSIsZSkpLAohcil0aHJvdyB0O1codCkscz1sfQpzLm5hbWV8fChzLm5hbWU9ZSksaVtlXT1zLHMucmF3RGVmaW5pdGlvbj10LmJpbmQobnVsbCxuKSxzLmFsaWFzZXMmJnYocy5hbGlhc2VzLHsKbGFuZ3VhZ2VOYW1lOmV9KX0sdW5yZWdpc3Rlckxhbmd1YWdlOmU9PntkZWxldGUgaVtlXQo7Zm9yKGNvbnN0IHQgb2YgT2JqZWN0LmtleXMocykpc1t0XT09PWUmJmRlbGV0ZSBzW3RdfSwKbGlzdExhbmd1YWdlczooKT0+T2JqZWN0LmtleXMoaSksZ2V0TGFuZ3VhZ2U6TyxyZWdpc3RlckFsaWFzZXM6diwKYXV0b0RldGVjdGlvbjprLGluaGVyaXQ6USxhZGRQbHVnaW46ZT0+eyhlPT57CmVbImJlZm9yZTpoaWdobGlnaHRCbG9jayJdJiYhZVsiYmVmb3JlOmhpZ2hsaWdodEVsZW1lbnQiXSYmKGVbImJlZm9yZTpoaWdobGlnaHRFbGVtZW50Il09dD0+ewplWyJiZWZvcmU6aGlnaGxpZ2h0QmxvY2siXShPYmplY3QuYXNzaWduKHtibG9jazp0LmVsfSx0KSkKfSksZVsiYWZ0ZXI6aGlnaGxpZ2h0QmxvY2siXSYmIWVbImFmdGVyOmhpZ2hsaWdodEVsZW1lbnQiXSYmKGVbImFmdGVyOmhpZ2hsaWdodEVsZW1lbnQiXT10PT57CmVbImFmdGVyOmhpZ2hsaWdodEJsb2NrIl0oT2JqZWN0LmFzc2lnbih7YmxvY2s6dC5lbH0sdCkpfSl9KShlKSxvLnB1c2goZSl9LApyZW1vdmVQbHVnaW46ZT0+e2NvbnN0IHQ9by5pbmRleE9mKGUpOy0xIT09dCYmby5zcGxpY2UodCwxKX19KSxuLmRlYnVnTW9kZT0oKT0+ewpyPSExfSxuLnNhZmVNb2RlPSgpPT57cj0hMH0sbi52ZXJzaW9uU3RyaW5nPSIxMS45LjAiLG4ucmVnZXg9e2NvbmNhdDpoLApsb29rYWhlYWQ6ZyxlaXRoZXI6ZixvcHRpb25hbDpkLGFueU51bWJlck9mVGltZXM6dX0KO2Zvcihjb25zdCB0IGluIGopIm9iamVjdCI9PXR5cGVvZiBqW3RdJiZlKGpbdF0pO3JldHVybiBPYmplY3QuYXNzaWduKG4saiksbgp9LG5lPXRlKHt9KTtyZXR1cm4gbmUubmV3SW5zdGFuY2U9KCk9PnRlKHt9KSxuZX0oKQo7Im9iamVjdCI9PXR5cGVvZiBleHBvcnRzJiYidW5kZWZpbmVkIiE9dHlwZW9mIG1vZHVsZSYmKG1vZHVsZS5leHBvcnRzPWhsanMpOy8qISBgY3BwYCBncmFtbWFyIGNvbXBpbGVkIGZvciBIaWdobGlnaHQuanMgMTEuOS4wICovCigoKT0+e3ZhciBlPSgoKT0+eyJ1c2Ugc3RyaWN0IjtyZXR1cm4gZT0+e2NvbnN0IHQ9ZS5yZWdleCxhPWUuQ09NTUVOVCgiLy8iLCIkIix7CmNvbnRhaW5zOlt7YmVnaW46L1xcXG4vfV0KfSksbj0iZGVjbHR5cGVcXChhdXRvXFwpIixyPSJbYS16QS1aX11cXHcqOjoiLGk9Iig/IXN0cnVjdCkoIituKyJ8Iit0Lm9wdGlvbmFsKHIpKyJbYS16QS1aX11cXHcqIit0Lm9wdGlvbmFsKCI8W148Pl0rPiIpKyIpIixzPXsKY2xhc3NOYW1lOiJ0eXBlIixiZWdpbjoiXFxiW2EtelxcZF9dKl90XFxiIn0sYz17Y2xhc3NOYW1lOiJzdHJpbmciLHZhcmlhbnRzOlt7CmJlZ2luOicodTg/fFV8TCk/IicsZW5kOiciJyxpbGxlZ2FsOiJcXG4iLGNvbnRhaW5zOltlLkJBQ0tTTEFTSF9FU0NBUEVdfSx7CmJlZ2luOiIodTg/fFV8TCk/JyhcXFxcKHhbMC05QS1GYS1mXXsyfXx1WzAtOUEtRmEtZl17NCw4fXxbMC03XXszfXxcXFMpfC4pIiwKZW5kOiInIixpbGxlZ2FsOiIuIn0sZS5FTkRfU0FNRV9BU19CRUdJTih7CmJlZ2luOi8oPzp1OD98VXxMKT9SIihbXigpXFwgXXswLDE2fSlcKC8sZW5kOi9cKShbXigpXFwgXXswLDE2fSkiL30pXX0sbz17CmNsYXNzTmFtZToibnVtYmVyIix2YXJpYW50czpbewpiZWdpbjoiWystXT8oPzooPzpbMC05XSg/Oic/WzAtOV0pKlxcLig/OlswLTldKD86Jz9bMC05XSkqKT98XFwuWzAtOV0oPzonP1swLTldKSopKD86W0VlXVsrLV0/WzAtOV0oPzonP1swLTldKSopP3xbMC05XSg/Oic/WzAtOV0pKltFZV1bKy1dP1swLTldKD86Jz9bMC05XSkqfDBbWHhdKD86WzAtOUEtRmEtZl0oPzonP1swLTlBLUZhLWZdKSooPzpcXC4oPzpbMC05QS1GYS1mXSg/Oic/WzAtOUEtRmEtZl0pKik/KT98XFwuWzAtOUEtRmEtZl0oPzonP1swLTlBLUZhLWZdKSopW1BwXVsrLV0/WzAtOV0oPzonP1swLTldKSopKD86W0ZmXSg/OjE2fDMyfDY0fDEyOCk/fChCRnxiZikxNnxbTGxdfCkiCn0sewpiZWdpbjoiWystXT9cXGIoPzowW0JiXVswMV0oPzonP1swMV0pKnwwW1h4XVswLTlBLUZhLWZdKD86Jz9bMC05QS1GYS1mXSkqfDAoPzonP1swLTddKSp8WzEtOV0oPzonP1swLTldKSopKD86W1V1XSg/OkxMP3xsbD8pfFtVdV1bWnpdP3woPzpMTD98bGw/KVtVdV0/fFtael1bVXVdfCkiCn1dLHJlbGV2YW5jZTowfSxsPXtjbGFzc05hbWU6Im1ldGEiLGJlZ2luOi8jXHMqW2Etel0rXGIvLGVuZDovJC8sa2V5d29yZHM6ewprZXl3b3JkOiJpZiBlbHNlIGVsaWYgZW5kaWYgZGVmaW5lIHVuZGVmIHdhcm5pbmcgZXJyb3IgbGluZSBwcmFnbWEgX1ByYWdtYSBpZmRlZiBpZm5kZWYgaW5jbHVkZSIKfSxjb250YWluczpbe2JlZ2luOi9cXFxuLyxyZWxldmFuY2U6MH0sZS5pbmhlcml0KGMse2NsYXNzTmFtZToic3RyaW5nIn0pLHsKY2xhc3NOYW1lOiJzdHJpbmciLGJlZ2luOi88Lio/Pi99LGEsZS5DX0JMT0NLX0NPTU1FTlRfTU9ERV19LHU9ewpjbGFzc05hbWU6InRpdGxlIixiZWdpbjp0Lm9wdGlvbmFsKHIpK2UuSURFTlRfUkUscmVsZXZhbmNlOjAKfSxkPXQub3B0aW9uYWwocikrZS5JREVOVF9SRSsiXFxzKlxcKCIscD17CnR5cGU6WyJib29sIiwiY2hhciIsImNoYXIxNl90IiwiY2hhcjMyX3QiLCJjaGFyOF90IiwiZG91YmxlIiwiZmxvYXQiLCJpbnQiLCJsb25nIiwic2hvcnQiLCJ2b2lkIiwid2NoYXJfdCIsInVuc2lnbmVkIiwic2lnbmVkIiwiY29uc3QiLCJzdGF0aWMiXSwKa2V5d29yZDpbImFsaWduYXMiLCJhbGlnbm9mIiwiYW5kIiwiYW5kX2VxIiwiYXNtIiwiYXRvbWljX2NhbmNlbCIsImF0b21pY19jb21taXQiLCJhdG9taWNfbm9leGNlcHQiLCJhdXRvIiwiYml0YW5kIiwiYml0b3IiLCJicmVhayIsImNhc2UiLCJjYXRjaCIsImNsYXNzIiwiY29fYXdhaXQiLCJjb19yZXR1cm4iLCJjb195aWVsZCIsImNvbXBsIiwiY29uY2VwdCIsImNvbnN0X2Nhc3R8MTAiLCJjb25zdGV2YWwiLCJjb25zdGV4cHIiLCJjb25zdGluaXQiLCJjb250aW51ZSIsImRlY2x0eXBlIiwiZGVmYXVsdCIsImRlbGV0ZSIsImRvIiwiZHluYW1pY19jYXN0fDEwIiwiZWxzZSIsImVudW0iLCJleHBsaWNpdCIsImV4cG9ydCIsImV4dGVybiIsImZhbHNlIiwiZmluYWwiLCJmb3IiLCJmcmllbmQiLCJnb3RvIiwiaWYiLCJpbXBvcnQiLCJpbmxpbmUiLCJtb2R1bGUiLCJtdXRhYmxlIiwibmFtZXNwYWNlIiwibmV3Iiwibm9leGNlcHQiLCJub3QiLCJub3RfZXEiLCJudWxscHRyIiwib3BlcmF0b3IiLCJvciIsIm9yX2VxIiwib3ZlcnJpZGUiLCJwcml2YXRlIiwicHJvdGVjdGVkIiwicHVibGljIiwicmVmbGV4cHIiLCJyZWdpc3RlciIsInJlaW50ZXJwcmV0X2Nhc3R8MTAiLCJyZXF1aXJlcyIsInJldHVybiIsInNpemVvZiIsInN0YXRpY19hc3NlcnQiLCJzdGF0aWNfY2FzdHwxMCIsInN0cnVjdCIsInN3aXRjaCIsInN5bmNocm9uaXplZCIsInRlbXBsYXRlIiwidGhpcyIsInRocmVhZF9sb2NhbCIsInRocm93IiwidHJhbnNhY3Rpb25fc2FmZSIsInRyYW5zYWN0aW9uX3NhZmVfZHluYW1pYyIsInRydWUiLCJ0cnkiLCJ0eXBlZGVmIiwidHlwZWlkIiwidHlwZW5hbWUiLCJ1bmlvbiIsInVzaW5nIiwidmlydHVhbCIsInZvbGF0aWxlIiwid2hpbGUiLCJ4b3IiLCJ4b3JfZXEiXSwKbGl0ZXJhbDpbIk5VTEwiLCJmYWxzZSIsIm51bGxvcHQiLCJudWxscHRyIiwidHJ1ZSJdLGJ1aWx0X2luOlsiX1ByYWdtYSJdLApfdHlwZV9oaW50czpbImFueSIsImF1dG9fcHRyIiwiYmFycmllciIsImJpbmFyeV9zZW1hcGhvcmUiLCJiaXRzZXQiLCJjb21wbGV4IiwiY29uZGl0aW9uX3ZhcmlhYmxlIiwiY29uZGl0aW9uX3ZhcmlhYmxlX2FueSIsImNvdW50aW5nX3NlbWFwaG9yZSIsImRlcXVlIiwiZmFsc2VfdHlwZSIsImZ1dHVyZSIsImltYWdpbmFyeSIsImluaXRpYWxpemVyX2xpc3QiLCJpc3RyaW5nc3RyZWFtIiwianRocmVhZCIsImxhdGNoIiwibG9ja19ndWFyZCIsIm11bHRpbWFwIiwibXVsdGlzZXQiLCJtdXRleCIsIm9wdGlvbmFsIiwib3N0cmluZ3N0cmVhbSIsInBhY2thZ2VkX3Rhc2siLCJwYWlyIiwicHJvbWlzZSIsInByaW9yaXR5X3F1ZXVlIiwicXVldWUiLCJyZWN1cnNpdmVfbXV0ZXgiLCJyZWN1cnNpdmVfdGltZWRfbXV0ZXgiLCJzY29wZWRfbG9jayIsInNldCIsInNoYXJlZF9mdXR1cmUiLCJzaGFyZWRfbG9jayIsInNoYXJlZF9tdXRleCIsInNoYXJlZF90aW1lZF9tdXRleCIsInNoYXJlZF9wdHIiLCJzdGFjayIsInN0cmluZ192aWV3Iiwic3RyaW5nc3RyZWFtIiwidGltZWRfbXV0ZXgiLCJ0aHJlYWQiLCJ0cnVlX3R5cGUiLCJ0dXBsZSIsInVuaXF1ZV9sb2NrIiwidW5pcXVlX3B0ciIsInVub3JkZXJlZF9tYXAiLCJ1bm9yZGVyZWRfbXVsdGltYXAiLCJ1bm9yZGVyZWRfbXVsdGlzZXQiLCJ1bm9yZGVyZWRfc2V0IiwidmFyaWFudCIsInZlY3RvciIsIndlYWtfcHRyIiwid3N0cmluZyIsIndzdHJpbmdfdmlldyJdCn0sXz17Y2xhc3NOYW1lOiJmdW5jdGlvbi5kaXNwYXRjaCIscmVsZXZhbmNlOjAsa2V5d29yZHM6ewpfaGludDpbImFib3J0IiwiYWJzIiwiYWNvcyIsImFwcGx5IiwiYXNfY29uc3QiLCJhc2luIiwiYXRhbiIsImF0YW4yIiwiY2FsbG9jIiwiY2VpbCIsImNlcnIiLCJjaW4iLCJjbG9nIiwiY29zIiwiY29zaCIsImNvdXQiLCJkZWNsdmFsIiwiZW5kbCIsImV4Y2hhbmdlIiwiZXhpdCIsImV4cCIsImZhYnMiLCJmbG9vciIsImZtb2QiLCJmb3J3YXJkIiwiZnByaW50ZiIsImZwdXRzIiwiZnJlZSIsImZyZXhwIiwiZnNjYW5mIiwiZnV0dXJlIiwiaW52b2tlIiwiaXNhbG51bSIsImlzYWxwaGEiLCJpc2NudHJsIiwiaXNkaWdpdCIsImlzZ3JhcGgiLCJpc2xvd2VyIiwiaXNwcmludCIsImlzcHVuY3QiLCJpc3NwYWNlIiwiaXN1cHBlciIsImlzeGRpZ2l0IiwibGFicyIsImxhdW5kZXIiLCJsZGV4cCIsImxvZyIsImxvZzEwIiwibWFrZV9wYWlyIiwibWFrZV9zaGFyZWQiLCJtYWtlX3NoYXJlZF9mb3Jfb3ZlcndyaXRlIiwibWFrZV90dXBsZSIsIm1ha2VfdW5pcXVlIiwibWFsbG9jIiwibWVtY2hyIiwibWVtY21wIiwibWVtY3B5IiwibWVtc2V0IiwibW9kZiIsIm1vdmUiLCJwb3ciLCJwcmludGYiLCJwdXRjaGFyIiwicHV0cyIsInJlYWxsb2MiLCJzY2FuZiIsInNpbiIsInNpbmgiLCJzbnByaW50ZiIsInNwcmludGYiLCJzcXJ0Iiwic3NjYW5mIiwic3RkIiwic3RkZXJyIiwic3RkaW4iLCJzdGRvdXQiLCJzdHJjYXQiLCJzdHJjaHIiLCJzdHJjbXAiLCJzdHJjcHkiLCJzdHJjc3BuIiwic3RybGVuIiwic3RybmNhdCIsInN0cm5jbXAiLCJzdHJuY3B5Iiwic3RycGJyayIsInN0cnJjaHIiLCJzdHJzcG4iLCJzdHJzdHIiLCJzd2FwIiwidGFuIiwidGFuaCIsInRlcm1pbmF0ZSIsInRvX3VuZGVybHlpbmciLCJ0b2xvd2VyIiwidG91cHBlciIsInZmcHJpbnRmIiwidmlzaXQiLCJ2cHJpbnRmIiwidnNwcmludGYiXQp9LApiZWdpbjp0LmNvbmNhdCgvXGIvLC8oPyFkZWNsdHlwZSkvLC8oPyFpZikvLC8oPyFmb3IpLywvKD8hc3dpdGNoKS8sLyg/IXdoaWxlKS8sZS5JREVOVF9SRSx0Lmxvb2thaGVhZCgvKDxbXjw+XSs+fClccypcKC8pKQp9LG09W18sbCxzLGEsZS5DX0JMT0NLX0NPTU1FTlRfTU9ERSxvLGNdLGY9e3ZhcmlhbnRzOlt7YmVnaW46Lz0vLGVuZDovOy99LHsKYmVnaW46L1woLyxlbmQ6L1wpL30se2JlZ2luS2V5d29yZHM6Im5ldyB0aHJvdyByZXR1cm4gZWxzZSIsZW5kOi87L31dLAprZXl3b3JkczpwLGNvbnRhaW5zOm0uY29uY2F0KFt7YmVnaW46L1woLyxlbmQ6L1wpLyxrZXl3b3JkczpwLApjb250YWluczptLmNvbmNhdChbInNlbGYiXSkscmVsZXZhbmNlOjB9XSkscmVsZXZhbmNlOjB9LGc9e2NsYXNzTmFtZToiZnVuY3Rpb24iLApiZWdpbjoiKCIraSsiW1xcKiZcXHNdKykrIitkLHJldHVybkJlZ2luOiEwLGVuZDovW3s7PV0vLGV4Y2x1ZGVFbmQ6ITAsCmtleXdvcmRzOnAsaWxsZWdhbDovW15cd1xzXComOjw+Ll0vLGNvbnRhaW5zOlt7YmVnaW46bixrZXl3b3JkczpwLHJlbGV2YW5jZTowfSx7CmJlZ2luOmQscmV0dXJuQmVnaW46ITAsY29udGFpbnM6W3VdLHJlbGV2YW5jZTowfSx7YmVnaW46Lzo6LyxyZWxldmFuY2U6MH0sewpiZWdpbjovOi8sZW5kc1dpdGhQYXJlbnQ6ITAsY29udGFpbnM6W2Msb119LHtyZWxldmFuY2U6MCxtYXRjaDovLC99LHsKY2xhc3NOYW1lOiJwYXJhbXMiLGJlZ2luOi9cKC8sZW5kOi9cKS8sa2V5d29yZHM6cCxyZWxldmFuY2U6MCwKY29udGFpbnM6W2EsZS5DX0JMT0NLX0NPTU1FTlRfTU9ERSxjLG8scyx7YmVnaW46L1woLyxlbmQ6L1wpLyxrZXl3b3JkczpwLApyZWxldmFuY2U6MCxjb250YWluczpbInNlbGYiLGEsZS5DX0JMT0NLX0NPTU1FTlRfTU9ERSxjLG8sc119XQp9LHMsYSxlLkNfQkxPQ0tfQ09NTUVOVF9NT0RFLGxdfTtyZXR1cm57bmFtZToiQysrIiwKYWxpYXNlczpbImNjIiwiYysrIiwiaCsrIiwiaHBwIiwiaGgiLCJoeHgiLCJjeHgiXSxrZXl3b3JkczpwLGlsbGVnYWw6IjwvIiwKY2xhc3NOYW1lQWxpYXNlczp7ImZ1bmN0aW9uLmRpc3BhdGNoIjoiYnVpbHRfaW4ifSwKY29udGFpbnM6W10uY29uY2F0KGYsZyxfLG0sW2wsewpiZWdpbjoiXFxiKGRlcXVlfGxpc3R8cXVldWV8cHJpb3JpdHlfcXVldWV8cGFpcnxzdGFja3x2ZWN0b3J8bWFwfHNldHxiaXRzZXR8bXVsdGlzZXR8bXVsdGltYXB8dW5vcmRlcmVkX21hcHx1bm9yZGVyZWRfc2V0fHVub3JkZXJlZF9tdWx0aXNldHx1bm9yZGVyZWRfbXVsdGltYXB8YXJyYXl8dHVwbGV8b3B0aW9uYWx8dmFyaWFudHxmdW5jdGlvbilcXHMqPCg/ITwpIiwKZW5kOiI+IixrZXl3b3JkczpwLGNvbnRhaW5zOlsic2VsZiIsc119LHtiZWdpbjplLklERU5UX1JFKyI6OiIsa2V5d29yZHM6cH0sewptYXRjaDpbL1xiKD86ZW51bSg/OlxzKyg/OmNsYXNzfHN0cnVjdCkpP3xjbGFzc3xzdHJ1Y3R8dW5pb24pLywvXHMrLywvXHcrL10sCmNsYXNzTmFtZTp7MToia2V5d29yZCIsMzoidGl0bGUuY2xhc3MifX1dKX19fSkoKTtobGpzLnJlZ2lzdGVyTGFuZ3VhZ2UoImNwcCIsZSkKfSkoKTs="></script>
<script src="data:text/javascript;base64,dmFyIG1lcmdlSFRNTFBsdWdpbiA9IChmdW5jdGlvbiAoKSB7CiAgJ3VzZSBzdHJpY3QnOwoKICB2YXIgb3JpZ2luYWxTdHJlYW07CgogIC8qKgogICAqIEBwYXJhbSB7c3RyaW5nfSB2YWx1ZQogICAqIEByZXR1cm5zIHtzdHJpbmd9CiAgICovCiAgZnVuY3Rpb24gZXNjYXBlSFRNTCh2YWx1ZSkgewogICAgcmV0dXJuIHZhbHVlCiAgICAgIC5yZXBsYWNlKC8mL2csICcmYW1wOycpCiAgICAgIC5yZXBsYWNlKC88L2csICcmbHQ7JykKICAgICAgLnJlcGxhY2UoLz4vZywgJyZndDsnKQogICAgICAucmVwbGFjZSgvIi9nLCAnJnF1b3Q7JykKICAgICAgLnJlcGxhY2UoLycvZywgJyYjeDI3OycpOwogIH0KCiAgLyogcGx1Z2luIGl0c2VsZiAqLwoKICAvKiogQHR5cGUge0hMSlNQbHVnaW59ICovCiAgY29uc3QgbWVyZ2VIVE1MUGx1Z2luID0gewogICAgLy8gcHJlc2VydmUgdGhlIG9yaWdpbmFsIEhUTUwgdG9rZW4gc3RyZWFtCiAgICAiYmVmb3JlOmhpZ2hsaWdodEVsZW1lbnQiOiAoeyBlbCB9KSA9PiB7CiAgICAgIG9yaWdpbmFsU3RyZWFtID0gbm9kZVN0cmVhbShlbCk7CiAgICB9LAogICAgLy8gbWVyZ2UgaXQgYWZ0ZXJ3YXJkcyB3aXRoIHRoZSBoaWdobGlnaHRlZCB0b2tlbiBzdHJlYW0KICAgICJhZnRlcjpoaWdobGlnaHRFbGVtZW50IjogKHsgZWwsIHJlc3VsdCwgdGV4dCB9KSA9PiB7CiAgICAgIGlmICghb3JpZ2luYWxTdHJlYW0ubGVuZ3RoKSByZXR1cm47CgogICAgICBjb25zdCByZXN1bHROb2RlID0gZG9jdW1lbnQuY3JlYXRlRWxlbWVudCgnZGl2Jyk7CiAgICAgIHJlc3VsdE5vZGUuaW5uZXJIVE1MID0gcmVzdWx0LnZhbHVlOwogICAgICByZXN1bHQudmFsdWUgPSBtZXJnZVN0cmVhbXMob3JpZ2luYWxTdHJlYW0sIG5vZGVTdHJlYW0ocmVzdWx0Tm9kZSksIHRleHQpOwogICAgICBlbC5pbm5lckhUTUwgPSByZXN1bHQudmFsdWU7CiAgICB9CiAgfTsKCiAgLyogU3RyZWFtIG1lcmdpbmcgc3VwcG9ydCBmdW5jdGlvbnMgKi8KCiAgLyoqCiAgICogQHR5cGVkZWYgRXZlbnQKICAgKiBAcHJvcGVydHkgeydzdGFydCd8J3N0b3AnfSBldmVudAogICAqIEBwcm9wZXJ0eSB7bnVtYmVyfSBvZmZzZXQKICAgKiBAcHJvcGVydHkge05vZGV9IG5vZGUKICAgKi8KCiAgLyoqCiAgICogQHBhcmFtIHtOb2RlfSBub2RlCiAgICovCiAgZnVuY3Rpb24gdGFnKG5vZGUpIHsKICAgIHJldHVybiBub2RlLm5vZGVOYW1lLnRvTG93ZXJDYXNlKCk7CiAgfQoKICAvKioKICAgKiBAcGFyYW0ge05vZGV9IG5vZGUKICAgKi8KICBmdW5jdGlvbiBub2RlU3RyZWFtKG5vZGUpIHsKICAgIC8qKiBAdHlwZSBFdmVudFtdICovCiAgICBjb25zdCByZXN1bHQgPSBbXTsKICAgIChmdW5jdGlvbiBfbm9kZVN0cmVhbShub2RlLCBvZmZzZXQpIHsKICAgICAgZm9yIChsZXQgY2hpbGQgPSBub2RlLmZpcnN0Q2hpbGQ7IGNoaWxkOyBjaGlsZCA9IGNoaWxkLm5leHRTaWJsaW5nKSB7CiAgICAgICAgaWYgKGNoaWxkLm5vZGVUeXBlID09PSAzKSB7CiAgICAgICAgICBvZmZzZXQgKz0gY2hpbGQubm9kZVZhbHVlLmxlbmd0aDsKICAgICAgICB9IGVsc2UgaWYgKGNoaWxkLm5vZGVUeXBlID09PSAxKSB7CiAgICAgICAgICByZXN1bHQucHVzaCh7CiAgICAgICAgICAgIGV2ZW50OiAnc3RhcnQnLAogICAgICAgICAgICBvZmZzZXQ6IG9mZnNldCwKICAgICAgICAgICAgbm9kZTogY2hpbGQKICAgICAgICAgIH0pOwogICAgICAgICAgb2Zmc2V0ID0gX25vZGVTdHJlYW0oY2hpbGQsIG9mZnNldCk7CiAgICAgICAgICAvLyBQcmV2ZW50IHZvaWQgZWxlbWVudHMgZnJvbSBoYXZpbmcgYW4gZW5kIHRhZyB0aGF0IHdvdWxkIGFjdHVhbGx5CiAgICAgICAgICAvLyBkb3VibGUgdGhlbSBpbiB0aGUgb3V0cHV0LiBUaGVyZSBhcmUgbW9yZSB2b2lkIGVsZW1lbnRzIGluIEhUTUwKICAgICAgICAgIC8vIGJ1dCB3ZSBsaXN0IG9ubHkgdGhvc2UgcmVhbGlzdGljYWxseSBleHBlY3RlZCBpbiBjb2RlIGRpc3BsYXkuCiAgICAgICAgICBpZiAoIXRhZyhjaGlsZCkubWF0Y2goL2JyfGhyfGltZ3xpbnB1dC8pKSB7CiAgICAgICAgICAgIHJlc3VsdC5wdXNoKHsKICAgICAgICAgICAgICBldmVudDogJ3N0b3AnLAogICAgICAgICAgICAgIG9mZnNldDogb2Zmc2V0LAogICAgICAgICAgICAgIG5vZGU6IGNoaWxkCiAgICAgICAgICAgIH0pOwogICAgICAgICAgfQogICAgICAgIH0KICAgICAgfQogICAgICByZXR1cm4gb2Zmc2V0OwogICAgfSkobm9kZSwgMCk7CiAgICByZXR1cm4gcmVzdWx0OwogIH0KCiAgLyoqCiAgICogQHBhcmFtIHthbnl9IG9yaWdpbmFsIC0gdGhlIG9yaWdpbmFsIHN0cmVhbQogICAqIEBwYXJhbSB7YW55fSBoaWdobGlnaHRlZCAtIHN0cmVhbSBvZiB0aGUgaGlnaGxpZ2h0ZWQgc291cmNlCiAgICogQHBhcmFtIHtzdHJpbmd9IHZhbHVlIC0gdGhlIG9yaWdpbmFsIHNvdXJjZSBpdHNlbGYKICAgKi8KICBmdW5jdGlvbiBtZXJnZVN0cmVhbXMob3JpZ2luYWwsIGhpZ2hsaWdodGVkLCB2YWx1ZSkgewogICAgbGV0IHByb2Nlc3NlZCA9IDA7CiAgICBsZXQgcmVzdWx0ID0gJyc7CiAgICBjb25zdCBub2RlU3RhY2sgPSBbXTsKCiAgICBmdW5jdGlvbiBzZWxlY3RTdHJlYW0oKSB7CiAgICAgIGlmICghb3JpZ2luYWwubGVuZ3RoIHx8ICFoaWdobGlnaHRlZC5sZW5ndGgpIHsKICAgICAgICByZXR1cm4gb3JpZ2luYWwubGVuZ3RoID8gb3JpZ2luYWwgOiBoaWdobGlnaHRlZDsKICAgICAgfQogICAgICBpZiAob3JpZ2luYWxbMF0ub2Zmc2V0ICE9PSBoaWdobGlnaHRlZFswXS5vZmZzZXQpIHsKICAgICAgICByZXR1cm4gKG9yaWdpbmFsWzBdLm9mZnNldCA8IGhpZ2hsaWdodGVkWzBdLm9mZnNldCkgPyBvcmlnaW5hbCA6IGhpZ2hsaWdodGVkOwogICAgICB9CgogICAgICAvKgogICAgICBUbyBhdm9pZCBzdGFydGluZyB0aGUgc3RyZWFtIGp1c3QgYmVmb3JlIGl0IHNob3VsZCBzdG9wIHRoZSBvcmRlciBpcwogICAgICBlbnN1cmVkIHRoYXQgb3JpZ2luYWwgYWx3YXlzIHN0YXJ0cyBmaXJzdCBhbmQgY2xvc2VzIGxhc3Q6CgogICAgICBpZiAoZXZlbnQxID09ICdzdGFydCcgJiYgZXZlbnQyID09ICdzdGFydCcpCiAgICAgICAgcmV0dXJuIG9yaWdpbmFsOwogICAgICBpZiAoZXZlbnQxID09ICdzdGFydCcgJiYgZXZlbnQyID09ICdzdG9wJykKICAgICAgICByZXR1cm4gaGlnaGxpZ2h0ZWQ7CiAgICAgIGlmIChldmVudDEgPT0gJ3N0b3AnICYmIGV2ZW50MiA9PSAnc3RhcnQnKQogICAgICAgIHJldHVybiBvcmlnaW5hbDsKICAgICAgaWYgKGV2ZW50MSA9PSAnc3RvcCcgJiYgZXZlbnQyID09ICdzdG9wJykKICAgICAgICByZXR1cm4gaGlnaGxpZ2h0ZWQ7CgogICAgICAuLi4gd2hpY2ggaXMgY29sbGFwc2VkIHRvOgogICAgICAqLwogICAgICByZXR1cm4gaGlnaGxpZ2h0ZWRbMF0uZXZlbnQgPT09ICdzdGFydCcgPyBvcmlnaW5hbCA6IGhpZ2hsaWdodGVkOwogICAgfQoKICAgIC8qKgogICAgICogQHBhcmFtIHtOb2RlfSBub2RlCiAgICAgKi8KICAgIGZ1bmN0aW9uIG9wZW4obm9kZSkgewogICAgICAvKiogQHBhcmFtIHtBdHRyfSBhdHRyICovCiAgICAgIGZ1bmN0aW9uIGF0dHJpYnV0ZVN0cmluZyhhdHRyKSB7CiAgICAgICAgcmV0dXJuICcgJyArIGF0dHIubm9kZU5hbWUgKyAnPSInICsgZXNjYXBlSFRNTChhdHRyLnZhbHVlKSArICciJzsKICAgICAgfQogICAgICAvLyBAdHMtaWdub3JlCiAgICAgIHJlc3VsdCArPSAnPCcgKyB0YWcobm9kZSkgKyBbXS5tYXAuY2FsbChub2RlLmF0dHJpYnV0ZXMsIGF0dHJpYnV0ZVN0cmluZykuam9pbignJykgKyAnPic7CiAgICB9CgogICAgLyoqCiAgICAgKiBAcGFyYW0ge05vZGV9IG5vZGUKICAgICAqLwogICAgZnVuY3Rpb24gY2xvc2Uobm9kZSkgewogICAgICByZXN1bHQgKz0gJzwvJyArIHRhZyhub2RlKSArICc+JzsKICAgIH0KCiAgICAvKioKICAgICAqIEBwYXJhbSB7RXZlbnR9IGV2ZW50CiAgICAgKi8KICAgIGZ1bmN0aW9uIHJlbmRlcihldmVudCkgewogICAgICAoZXZlbnQuZXZlbnQgPT09ICdzdGFydCcgPyBvcGVuIDogY2xvc2UpKGV2ZW50Lm5vZGUpOwogICAgfQoKICAgIHdoaWxlIChvcmlnaW5hbC5sZW5ndGggfHwgaGlnaGxpZ2h0ZWQubGVuZ3RoKSB7CiAgICAgIGxldCBzdHJlYW0gPSBzZWxlY3RTdHJlYW0oKTsKICAgICAgcmVzdWx0ICs9IGVzY2FwZUhUTUwodmFsdWUuc3Vic3RyaW5nKHByb2Nlc3NlZCwgc3RyZWFtWzBdLm9mZnNldCkpOwogICAgICBwcm9jZXNzZWQgPSBzdHJlYW1bMF0ub2Zmc2V0OwogICAgICBpZiAoc3RyZWFtID09PSBvcmlnaW5hbCkgewogICAgICAgIC8qCiAgICAgICAgT24gYW55IG9wZW5pbmcgb3IgY2xvc2luZyB0YWcgb2YgdGhlIG9yaWdpbmFsIG1hcmt1cCB3ZSBmaXJzdCBjbG9zZQogICAgICAgIHRoZSBlbnRpcmUgaGlnaGxpZ2h0ZWQgbm9kZSBzdGFjaywgdGhlbiByZW5kZXIgdGhlIG9yaWdpbmFsIHRhZyBhbG9uZwogICAgICAgIHdpdGggYWxsIHRoZSBmb2xsb3dpbmcgb3JpZ2luYWwgdGFncyBhdCB0aGUgc2FtZSBvZmZzZXQgYW5kIHRoZW4KICAgICAgICByZW9wZW4gYWxsIHRoZSB0YWdzIG9uIHRoZSBoaWdobGlnaHRlZCBzdGFjay4KICAgICAgICAqLwogICAgICAgIG5vZGVTdGFjay5yZXZlcnNlKCkuZm9yRWFjaChjbG9zZSk7CiAgICAgICAgZG8gewogICAgICAgICAgcmVuZGVyKHN0cmVhbS5zcGxpY2UoMCwgMSlbMF0pOwogICAgICAgICAgc3RyZWFtID0gc2VsZWN0U3RyZWFtKCk7CiAgICAgICAgfSB3aGlsZSAoc3RyZWFtID09PSBvcmlnaW5hbCAmJiBzdHJlYW0ubGVuZ3RoICYmIHN0cmVhbVswXS5vZmZzZXQgPT09IHByb2Nlc3NlZCk7CiAgICAgICAgbm9kZVN0YWNrLnJldmVyc2UoKS5mb3JFYWNoKG9wZW4pOwogICAgICB9IGVsc2UgewogICAgICAgIGlmIChzdHJlYW1bMF0uZXZlbnQgPT09ICdzdGFydCcpIHsKICAgICAgICAgIG5vZGVTdGFjay5wdXNoKHN0cmVhbVswXS5ub2RlKTsKICAgICAgICB9IGVsc2UgewogICAgICAgICAgbm9kZVN0YWNrLnBvcCgpOwogICAgICAgIH0KICAgICAgICByZW5kZXIoc3RyZWFtLnNwbGljZSgwLCAxKVswXSk7CiAgICAgIH0KICAgIH0KICAgIHJldHVybiByZXN1bHQgKyBlc2NhcGVIVE1MKHZhbHVlLnN1YnN0cihwcm9jZXNzZWQpKTsKICB9CgogIHJldHVybiBtZXJnZUhUTUxQbHVnaW47Cgp9KCkpOw=="></script>
</head>
<body><div>
<nav><div><div>
<h1 class="hide-on-wide name-of-paper">Allowing exception throwing in constant-evaluation</h1>
<div class="paper-info">
	<div><span class="key">Number:</span> P3068R4</div>
	<div><span class="key">Date:</span> <time>2024-08-15</time></div>
	<div><span class="key">Audience:</span> CWG &amp; LEWG</div>
	<div><span class="key">Reply-to:</span> <a href="mailto:cpp@hanicka.net">Hana Dusíková</a></div>
</div>

<h2 id="table-of-contents"><a href="#table-of-contents">Table of contents</a></h2>
<ul>
	<li><a href="#introduction">Introduction</a></li>
	<li><a href="#changes">Changes</a></li>
	<li><a href="#hello-constexpr-exceptions-world">Motivational example</a></li>
	
	
	<li><a href="#implementation-experience">Implementation experience</a></li>
	<li><a href="#impact-on-existing-code">Impact on existing code</a></li>
	<li><a href="#examples">Examples</a>
		<ul>
			<li><a href="#parsing-date">Parsing a date</a></li>
			<li><a href="#non-transient-exceptions">Non-transient exceptions</a></li>
			<li><a href="#exceptions-must-be-caught">Exceptions must be caught</a></li>
			<li><a href="#constant-evaluation-violation-behavior-wont-be-changed">Constant evaluation violation behavior won't be changed</a></li>
			<li><a href="#lifetime-of-exception-object-must-stay-inside-constant-evaluation">Lifetime of exception object must stay inside constant evaluation</a></li>
		</ul>
	</li>
	<li><a href="#special-thanks">Special thanks</a></li>
	<li><a href="#wording">Wording</a>
		<ul>
			<li><a href="#library-wording">Library wording</a></li>
			<li><a href="#feature-test-macro">Feature test macro</a></li>
		</ul>
	</li>
</ul>
</div></div></nav>
<article>
<div><div>
	<h1 class="hide-on-narrow name-of-paper">Allowing exception throwing in constant-evaluation</h1>
	<h2 id="introduction"><a href="#introduction">Introduction</a></h2>
<p>Since adding the <code>constexpr</code> keyword in C++11, WG21 has gradually expanded the scope of language features  for use in constant-evaluated code. At first, users couldn't even use <code>if</code>, <code>else</code>, or loops. C++14 added support for them. C++17 added support for constexpr lambdas. C++20 finally added the ability to use allocation, <code>std::vector</code> and <code>std::string</code>. These improvements have been widely appreciated, and lead to simpler code that doesn't need to work around differences between normal and constexpr C++.</p>
<p>The last major language feature from C++ still not present in constexpr code is the ability to throw an exception. This absence forces library authors to use more intrusive error reporting mechanisms. One example would be the use of <code>std::expected</code> and <code>std::optional</code>. Another one is the complete omission of error handling. This leaves users with long and confusing errors generated by the compiler.</p>
<p>Throwing exceptions in constant evaluated code is the preferred way of error reporting in the proposal adding <em><a href="https://www.open-std.org/jtc1/sc22/wg21/docs/papers/2024/p2996r2.html">Static Reflection for C++26</a></em>. Some meta-functions can fail, and allowing them to throw will significantly simplify reflection code.</p>

<h2 id="changes"><a href="#changes">Changes</a></h2>
<ul>
	<li><a href="https://www.open-std.org/jtc1/sc22/wg21/docs/papers/2024/p3068r3.html">R3</a>&#x2005;→&#x2005;R4: Added missing library exception type <code>bad_typeid</code>. Added wording to specify literal encoding of <code>std::exception::what()</code> member function's result during constant evaluation.</li>
	<li><a href="https://www.open-std.org/jtc1/sc22/wg21/docs/papers/2024/p3068r2.html">R2</a>&#x2005;→&#x2005;<a href="https://www.open-std.org/jtc1/sc22/wg21/docs/papers/2024/p3068r3.html">R3</a>: Added library exception types <code>bad_alloc</code>, <code>bad_array_new_length</code>, and <code>bad_typeid</code>, removed recommended practice in the language wording part, remove part of language wording to allow exception throwing from <code>dynamic_cast</code> and <code>typeid</code>. Adding feature test macro, moving language and library wording to bottom of the paper.</li>
	<li><a href="https://www.open-std.org/jtc1/sc22/wg21/docs/papers/2024/p3068r1.pdf">R1</a>&#x2005;→&#x2005;<a href="https://www.open-std.org/jtc1/sc22/wg21/docs/papers/2024/p3068r2.html">R2</a>: Added library wording, new examples, implementation description, and updated impact of changes.</li>
	<li><a href="https://www.open-std.org/jtc1/sc22/wg21/docs/papers/2024/p3068r0.pdf">R0</a>&#x2005;→&#x2005;<a href="https://www.open-std.org/jtc1/sc22/wg21/docs/papers/2024/p3068r1.pdf">R1</a>: Changed wording after consultation with Jens, added example to show exception can't leak via <code>std::exception_ptr</code></li>
</ul>

<h2 id="hello-constexpr-exceptions-world"><a href="#hello-constexpr-exceptions-world">Motivational example</a></h2>
<pre><code class="language-cpp">consteval auto hello(std::string_view input) {
	if (input.empty()) {
		throw invalid_argument{"empty name provided"}; <span class="before">// BEFORE: compile-time error at throw expression site when reached</span>
	}
	
	return concat_into_a_fixed_string("hello ",input);
}</code></pre>

<pre><code class="language-cpp">const auto a = hello(""); <span class="unchanged">// AFTER: compile-time error at call site "empty name provided"</span>
const auto b = hello("Hana");

try {
	const auto c = hello(""); <span class="after">// AFTER: this exception is caught</span>
} catch (const validation_error &) {
	// everything is fine
}

const auto d = hello("Adolph Blaine Charles David Earl Frederick Gerald Hubert Irvin John Kenneth Lloyd Martin Nero Oliver Paul Quincy Randolph Sherman Thomas Uncas Victor William Xerxes Yancy Zeus Wolfeschlegelsteinhausen­bergerdorff­welche­vor­altern­waren­gewissenhaft­schafers­wessen­schafe­waren­wohl­gepflege­und­sorgfaltigkeit­beschutzen­von­angreifen­durch­ihr­raubgierig­feinde­welche­vor­altern­zwolf­tausend­jahres­voran­die­erscheinen­van­der­erste­erdemensch­der­raumschiff­gebrauch­licht­als­sein­ursprung­von­kraft­gestart­sein­lange­fahrt­hinzwischen­sternartig­raum­auf­der­suchen­ach­die­stern­welche­gehabt­bewohnbar­planeten­kreise­drehen­sich­und­wohin­der­neu­rasse­von­verstandig­menschlichkeit­konnte­fortpflanzen­und­sich­erfreuen­an­lebenslanglich­freude­und­ruhe­mit­nicht­ein­furcht­vor­angreifen­von­anderer­intelligent­geschopfs­von­hinzwischen­sternartig­raum."); <span class="before">// BEFORE: compile-time error at throw expression site deep in the concat function</span>
<span class="invisible">const auto d = hello("Adolph Blaine Charles David Earl Frederick Gerald Hubert Irvin John Kenneth Lloyd Martin Nero Oliver Paul Quincy Randolph Sherman Thomas Uncas Victor William Xerxes Yancy Zeus Wolfeschlegelsteinhausen­bergerdorff­welche­vor­altern­waren­gewissenhaft­schafers­wessen­schafe­waren­wohl­gepflege­und­sorgfaltigkeit­beschutzen­von­angreifen­durch­ihr­raubgierig­feinde­welche­vor­altern­zwolf­tausend­jahres­voran­die­erscheinen­van­der­erste­erdemensch­der­raumschiff­gebrauch­licht­als­sein­ursprung­von­kraft­gestart­sein­lange­fahrt­hinzwischen­sternartig­raum­auf­der­suchen­ach­die­stern­welche­gehabt­bewohnbar­planeten­kreise­drehen­sich­und­wohin­der­neu­rasse­von­verstandig­menschlichkeit­konnte­fortpflanzen­und­sich­erfreuen­an­lebenslanglich­freude­und­ruhe­mit­nicht­ein­furcht­vor­angreifen­von­anderer­intelligent­geschopfs­von­hinzwischen­sternartig­raum."); </span><span class="unchanged">// AFTER: compile-time error at call site "<a href="https://en.wikipedia.org/wiki/Hubert_Blaine_Wolfeschlegelsteinhausenbergerdorff_Sr.">too long name provided</a>"</span></code></pre>

<h2 id="implementation-experience"><a href="#implementation-experience">Implementation experience</a></h2>
<p>A partial implementation in Clang is available on <a href="https://compiler-explorer.com/z/h1Tff5d3P">compiler-explorer.com</a>. I expect it to be feature complete in time for the presentation at the St. Louis meeting.</p>
<p>The implementation approach is an <em>exception</em> slot to for <code>throw</code>-statements to store it in the same way as <code>return</code>-statements do. Every <code>try</code> block creates a new <em>exception</em> slot and try to match the appropriate <code>catch</code> block.</p>
<p>Library support is implemented via a set of new compiler builtins.</p>
<p>Three other compiler vendors were consulted and raised no implementability concerns.</p>


<h2 id="impact-on-existing-code"><a href="#impact-on-existing-code">Impact on existing code</a></h2>
<p>This change doesn't break any existing code as throwing exceptions without catching them is already an error and is used by various libraries (<a href="https://github.com/fmtlib/fmt/blob/8.1.1/include/fmt/format.h#L1619">fmt</a>, <a href="https://github.com/hanickadot/cthash/commit/46c8b6db59217827bf4ac0a53e8b13ca03861089#diff-67bca1e9849772f871bd9d89e6ad975ce3aacc061e77ddd80d84c1d8de6e1fc3R18">CTHASH</a>) to improve compile-time errors.</p>
<p>This proposal can make previously non-compiling code which reached a <code>throw</code>-statement compile by catching the thrown exception.</p>
<p>The intent is to keep this useful mechanism intact. The proposed wording change will only modify behavior in cases where a <code>try</code>/<code>catch</code> block is present.</p>

<h2 id="examples"><a href="#examples">Examples</a></h2>
<h3 id="parsing-date">Parsing date</h3>
<pre><code class="language-cpp">constexpr date parse_date(std::string_view input) {
	auto [correct, year, month, day] = ctre::match&lt;"([0-9]{4})-([0-9]{1,2})-([0-9]{1,2})"&gt;(input);
	
	if (!correct) {
		throw incorrect_date{input};
	}
	
	return build_date(year, month, day);
}

constexpr auto birthday = parse_date("1991-07-21"); // fine
constexpr auto wrong_day = parse_date("1-2-3"); <span class="error">// COMPILE-TIME ERROR: provided incorrect date "1-2-3"</span>
constexpr auto weird_day = parse_date("2023-03-29"); <span class="error">// COMPILE-TIME ERROR: year 2023 doesn't have a leap day</span>
</code></pre>
<h3 id="non-transient-exceptions"><a href="#non-transient-exceptions">Non-transient exceptions</a></h3>
<p>The current wording matches pre-<a href="https://www.open-std.org/jtc1/sc22/wg21/docs/papers/2024/p3032r2.html">P3032</a> wording and treats an exception basically as an allocation, and such allocation can't escape any <code>constexpr</code> variable initialization.</p>
<pre><code class="language-cpp">constexpr auto just_error() { 
	throw my_exception{};
}

constexpr void foo() {
	try {
		auto v = just_error(); // OK
	} catch (my_exception) {
		// do nothing
	}
	try {
		constexpr auto v = just_error(); <span class="error">// COMPILE-TIME ERROR: uncaught exception of type "my_exception"</span>
	} catch (my_exception) { }
}</code></pre>

<h3 id="exceptions-must-be-caught"><a href="#exceptions-must-be-caught">Exceptions must be caught</a></h3>
<pre><code class="language-cpp">constexpr unsigned divide(unsigned n, unsigned d) {
	if (d == 0u) {
		throw invalid_argument{"division by zero"};
	}
	return n / d;
}

constexpr auto b = divide(5, 0); <span class="before">// BEFORE: compilation error due reaching a throw expression</span>
<span class="invisible">constexpr auto b = divide(5, 0); </span><span class="unchanged">// AFTER: still a compilation error but due the uncaught exception</span>

constexpr std::optional&lt;unsigned&gt; checked_divide(unsigned n, unsigned d) {
	try {
		return divide(n, d);
	} catch (...) {
		return std::nullopt;
	}
}

constexpr auto a = checked_divide(5, 0); <span class="before">// BEFORE: compilation error</span>
<span class="invisible">constexpr auto a = checked_divide(5, 0); </span><span class="after">// AFTER: std::nullopt value</span>
</code></pre>
<h3 id="constant-evaluation-violation-behavior-wont-be-changed"><a href="#constant-evaluation-violation-behavior-wont-be-changed">Constant evaluation violation behavior won't be changed</a></h3>
<p>This paper <b>doesn't propose</b> throwing an exception for any other constant evaluation error.</p>
<pre><code class="language-cpp">constexpr unsigned read_pointer(const unsigned* p) {
	return *p;
}

constexpr unsigned try_to_ignore_ub() {
	try {
		return read_pointer(nullptr);
	} catch (...) {
		return 0;
	}
}

constexpr auto v = try_to_ignore_ub(); <span class="unchanged">// UNCHANGED: error due reaching UB by dereferencing the NULL pointer (no exception is involved)</span>
</code></pre>
<h3 id="lifetime-of-exception-object-must-stay-inside-constant-evaluation"><a href="#lifetime-of-exception-object-must-stay-inside-constant-evaluation">Lifetime of exception object must stay inside constant evaluation</a></h3>
<p>Exception objects thrown at compile-time must be caught before leaving their respective constant-evaluated scope, and can't be stored for run-time access. This is similar to constexpr allocations, which must be deallocated before leaving their respective scopes, and any memory that's reserved at compile-time is inaccessible to run-time evaluations.</p>
<pre><code class="language-cpp">consteval auto fail() -&gt; std::exception_ptr{
	try {
		throw failure{};
	} catch (...) {
		return std::current_exception();
	}
}

constexpr auto stored_exception = fail(); <span class="error">// NOT ALLOWED to store std::exception_ptr in a constexpr variable</span>
</code></pre>
<h2 id="special-thanks"><a href="#special-thanks">Special thanks</a></h2>
To Richard&nbsp;Smith, Barry&nbsp;Revzin, Daveed&nbsp;Vandevoorde, Jana&nbsp;Machutová, Christopher&nbsp;Di&nbsp;Bella, Jens&nbsp;Maurer, Robert&nbsp;C.&nbsp;Seacord, Lewis&nbsp;Baker, David&nbsp;Sankel, and Guy&nbsp;Davidson.

<h2 id="wording"><a href="#wording">Wording</a></h2>
<div class="wording">
<h2><a href="https://eel.is/c++draft/expr.const">7.7 Constant expressions [expr.const]</a></h2>
<p><span class="removed">(<a href="https://eel.is/c++draft/expr.const#5.25">5.25</a>) a throw-expression ([expr.throw]);</span></p>
<p>(<a href="https://eel.is/c++draft/expr.const#5.26">5.26</a>) a <code>dynamic_cast</code> ([expr.dynamic.cast]) or <code>typeid</code> ([expr.typeid]) expression on a glvalue that refers to an object whose dynamic type is constexpr-unknown<span class="removed"> or that would throw an exception</span>;</p>
<p><span class="added">(5.?) an exception object thrown ([<a href="https://eel.is/c++draft/expr.throw">expr.throw</a>]) without its type definition reachable;</span></p>
<p style="font-size: 0.8em">Note: This is to disallow throwing <code>bad_alloc</code> exception object without having its definition available.</p>
<p>(after 7) <span class="added">For the purposes of determining whether an expression <code>E</code> is a core constant expression, lifetimes of all thrown exception objects and any implicit copies of exception objects created by invocations of <code>std::current_exception</code> or <code>std::rethrow_exception</code> ([<a href="https://eel.is/c++draft/support.exception#propagation">propagation</a>]) during evaluation of <code>E</code> shall end within the evaluation of <code>E</code>.</span></p>
</div>

<h3 id="library-wording"><a href="#library-wording">Library wording</a></h3>
<p><em>Note:</em> This paper doesn't contain wording for any <code>&lt;stdexcept&gt;</code> changes as these are proposed already in <em><a href="https://isocpp.org/files/papers/P3295R0.html">P3295R0: Freestanding constexpr containers and constexpr exception types</a></em></p>

<div class="wording">

<h2><a href="http://eel.is/c++draft/alloc.errors#bad.alloc">17.6.4.1 Class <code>bad_alloc</code> [bad.alloc]</a></h2>
<div class="description">
<pre class="language-cpp"><code>namespace std {
  class bad_alloc : public exception {
  public:
    // see [exception] for the specification of the special member functions
    <span class="added">constexpr </span>const char* what() const noexcept override;
  };
}</code></pre>
<pre class="language-cpp"><code><span class="added">constexpr </span>const char* what() const noexcept override;</code></pre>
</div>

<h2><a href="http://eel.is/c++draft/alloc.errors#new.badlength">17.6.4.1 Class <code>bad_array_new_length</code> [new.badlength]</a></h2>

<div class="description">
<pre class="language-cpp"><code>namespace std {
  class bad_array_new_length : public bad_alloc {
  public:
    // see [exception] for the specification of the special member functions
    <span class="added">constexpr </span>const char* what() const noexcept override;
  };
}</code></pre>
<pre class="language-cpp"><code><span class="added">constexpr </span>const char* what() const noexcept override;</code></pre>
</div>

<h2><a href="http://eel.is/c++draft/bad.cast">17.7.4 Class <code>bad_cast</code> [bad.cast]</a></h2>
<div class="description">
<pre class="language-cpp"><code>namespace std {
  class bad_cast : public exception {
  public:
    // see [exception] for the specification of the special member functions
    <span class="added">constexpr </span>const char* what() const noexcept override;
  };
}</code></pre>
<pre class="language-cpp"><code><span class="added">constexpr </span>const char* what() const noexcept override;</code></pre>
</div>

<h2><a href="http://eel.is/c++draft/bad.typeid">17.7.5 Class <code>bad_typeid</code> [bad.typeid]</a></h2>
<div class="description">
<pre class="language-cpp"><code>namespace std {
  class bad_typeid : public exception {
  public:
    // see [exception] for the specification of the special member functions
    <span class="added">constexpr </span>const char* what() const noexcept override;
  };
}</code></pre>
<pre class="language-cpp"><code><span class="added">constexpr </span>const char* what() const noexcept override;</code></pre>
</div>

<h2><a href="https://eel.is/c++draft/exception.syn">17.9.2 Header &lt;exception&gt; synopsis [exception.syn]</a></h2>
<pre class="language-cpp"><code>// all freestanding
namespace std {
  class exception;
  class bad_exception;
  class nested_exception;

  using terminate_handler = void (*)();
  terminate_handler get_terminate() noexcept;
  terminate_handler set_terminate(terminate_handler f) noexcept;
  [[noreturn]] void terminate() noexcept;

  <span class="added">constexpr </span>int uncaught_exceptions() noexcept;

  using exception_ptr = <em>unspecified</em>;

  <span class="added">constexpr </span>exception_ptr current_exception() noexcept;
  [[noreturn]] <span class="added">constexpr </span>void rethrow_exception(exception_ptr p);
  template&lt;class E&gt; <span class="added">constexpr </span>exception_ptr make_exception_ptr(E e) noexcept;

  template&lt;class T&gt; <span class="added">constexpr </span>[[noreturn]] void throw_with_nested(T&& t);
  template&lt;class E&gt; <span class="added">constexpr </span>void rethrow_if_nested(const E& e);
}</code></pre>
<h2><a href="https://eel.is/c++draft/exception">17.9.3 Class exception [exception]</a></h2>
<pre class="language-cpp"><code>namespace std {
  class exception {
  public:
    <span class="added">constexpr </span>exception() noexcept;
    <span class="added">constexpr </span>exception(const exception&) noexcept;
    <span class="added">constexpr </span>exception& operator=(const exception&) noexcept;
    <span class="added">constexpr </span>virtual ~exception();
    <span class="added">constexpr </span>virtual const char* what() const noexcept;
  };
}</code></pre>
<div class="description">
<p id="exception.par1"><span class="parnum"><a href="#exception.par1">1</a></span>The class <code>exception</code> defines the base class for the types of objects thrown as exceptions by C++ standard library components, and certain expressions, to report errors detected during program execution.</p>
<div id="exception.par2"><p><span class="parnum"><a href="#exception.par2">2</a></span>Except where explicitly specified otherwise, each standard library class <code>T</code> that derives from class <code>exception</code> has the following publicly accessible member functions, each of them having a non-throwing exception specification (<a href="http://eel.is/c++draft/except.spec">[except.spec]</a>):
<ul>
<li id="exception.par2.1"><span class="parnum"><a href="#exception.par2.1">(2.1)</a></span>default constructor (unless the class synopsis shows other constructors)</li>
<li id="exception.par2.2"><span class="parnum"><a href="#exception.par2.2">(2.2)</a></span>copy constructor</li>
<li id="exception.par2.3"><span class="parnum"><a href="#exception.par2.3">(2.3)</a></span>copy assignment operator</li>
</ul>
The copy constructor and the copy assignment operator meet the following postcondition: If two objects <code>lhs</code> and <code>rhs</code> both have dynamic type <code>T</code> and <code>lhs</code> is a copy of <code>rhs</code>, then <code>strcmp(lhs.what(), rhs.what())</code> is equal to <code>0</code>. <span id="exception2">The <code>what()</code> member function of each such <code>T</code> satisfies the constraints specified for <code>exception​::​what()</code> (see below).</span></p></div></div>
<pre class="language-cpp"><code><span class="added">constexpr </span>exception(const exception& rhs) noexcept;
<span class="added">constexpr </span>exception& operator=(const exception& rhs) noexcept;</code></pre>

<div class="description"><p id="exception.par3">
<span class="parnum"><a href="#exception.par3">3</a></span><em>Postconditions:</em> If <code>*this</code> and <code>rhs</code> both have dynamic type exception then the value of the expression <code>strcmp(what(), rhs.what())</code> shall equal <code>0</code>.
</p></div>

<pre class="language-cpp"><code>virtual <span class="added">constexpr </span>~exception();</code></pre>

<div class="description"><p id="exception.par4">
<span class="parnum"><a href="#exception.par4">4</a></span><em>Effects:</em> Destroys an object of class exception.
</p></div>

<pre class="language-cpp"><code>virtual <span class="added">constexpr </span>const char* what() const noexcept;</code></pre>

<div class="description">
<p id="exception.par5"><span class="parnum"><a href="#exception.par5">5</a></span><em>Returns:</em> An implementation-defined <span style="font-variant: small-caps;">ntbs</span><span class="added">, which during constant evaluation shall be encoded with the ordinary literal encoding (<a href="http://eel.is/c++draft/lex.ccon">[lex.ccon]</a>)</span>.</p>
<div class="wording-note"><strong>note for editor:</strong> this imposes requirement on all inherited types as stated in <a href="#exception2">[exception#2]</a>.</div>
<p id="exception.par6"><span class="parnum"><a href="#exception.par6">6</a></span><em>Remarks:</em> The message may be a <a href="https://eel.is/c++draft/multibyte.strings#def:ntmbs">null-terminated multibyte string</a>, suitable for conversion and display as a <code>wstring</code> (<a href="https://eel.is/c++draft/string.classes">[string.classes]</a>, <a href="https://eel.is/c++draft/locale.codecvt">[locale.codecvt]</a>). The return value remains valid until the exception object from which it is obtained is destroyed or a non-<code>const</code> member function of the exception object is called.</p>
</div>
<h2><a href="https://eel.is/c++draft/bad.exception">17.9.4 Class bad_exception [bad.exception]</a></h2>
<pre class="language-cpp"><code>namespace std {
  class bad_exception : public exception {
  public:
    // see [exception] for the specification of the special member functions
    <span class="added">constexpr </span>const char* what() const noexcept override;
  };
}</code></pre>
<pre class="language-cpp"><code>virtual <span class="added">constexpr </span>const char* what() const noexcept override;</code></pre>
<h2><a href="https://eel.is/c++draft/uncaught.exceptions">17.9.6 uncaught_exceptions [uncaught.exceptions]</a></h2>
<pre class="language-cpp"><code><span class="added">constexpr </span>int uncaught_exceptions() noexcept;</code></pre>
<h2><a href="https://eel.is/c++draft/propagation">17.9.7 Exception propagation [propagation]</a></h2>
<pre class="language-cpp"><code>using exception_ptr = <em>unspecified</em>;</code></pre>
<p><span class="added">(8) All member functions are marked constexpr.</span></p>

<pre class="language-cpp"><code><span class="added">constexpr </span>exception_ptr current_exception() noexcept;</code></pre>

<pre class="language-cpp"><code>[[noreturn]] <span class="added">constexpr </span>void rethrow_exception(exception_ptr p);</code></pre>

<pre class="language-cpp"><code>template&lt;class E&gt; exception_ptr <span class="added">constexpr </span>make_exception_ptr(E e) noexcept;</code></pre>

<h2><a href="https://eel.is/c++draft/except.nested">17.9.8 nested_exception [except.nested]</a></h2>
<pre class="language-cpp"><code>namespace std {
  class nested_exception {
  public:
    <span class="added">constexpr </span>nested_exception() noexcept;
    <span class="added">constexpr </span>nested_exception(const nested_exception&) noexcept = default;
    <span class="added">constexpr </span>nested_exception& operator=(const nested_exception&) noexcept = default;
    virtual <span class="added">constexpr </span>~nested_exception() = default;

    // access functions
    [[noreturn]] <span class="added">constexpr </span>void rethrow_nested() const;
    <span class="added">constexpr </span>exception_ptr nested_ptr() const noexcept;
  };

  template&lt;class T&gt; [[noreturn]] <span class="added">constexpr </span>void throw_with_nested(T&& t);
  template&lt;class E&gt; <span class="added">constexpr </span>void rethrow_if_nested(const E& e);
}</code></pre>
<pre class="language-cpp"><code><span class="added">constexpr </span>nested_exception() noexcept;</code></pre>
<pre class="language-cpp"><code>[[noreturn]] <span class="added">constexpr </span>void rethrow_nested() const;</code></pre>
<pre class="language-cpp"><code><span class="added">constexpr </span>exception_ptr nested_ptr() const noexcept;</code></pre>
<pre class="language-cpp"><code>template&lt;class T&gt; [[noreturn]] <span class="added">constexpr </span>void throw_with_nested(T&& t);</code></pre>
<pre class="language-cpp"><code>template&lt;class E&gt; void <span class="added">constexpr </span>rethrow_if_nested(const E& e);</code></pre>



</div>

<h3 id="feature-test-macro"><a href="#feature-test-macro">Feature test macro</a></h3>
<div class="wording">
<h2><a href="http://eel.is/c++draft/cpp.predefined">15.11 Predefined macro names [cpp.predefined]</a></h2>
<div class="description">
<span class="added"><code>__cpp_constexpr_exceptions 2024??L</code></span>
</div>
<h2><a href="http://eel.is/c++draft/version.syn">17.3.2 Header &lt;version&gt; synopsis [version.syn]</a></h2>
<div class="description">
<span class="added"><code>#define __cpp_lib_constexpr_exceptions 2024??L</code></span>
</div>

</div>


</div></div></article>
</div><script>
	hljs.addPlugin(mergeHTMLPlugin);
	hljs.highlightAll();
</script>
</body>
</html>
