LyohIFxmaWxlIGJ0R0ltcGFjdFRyaWFuZ2xlU2hhcGUuaApcYXV0aG9yIEZyYW5jaXNjbyBMZX9uIE7famVyYQoqLwovKgpUaGlzIHNvdXJjZSBmaWxlIGlzIHBhcnQgb2YgR0lNUEFDVCBMaWJyYXJ5LgoKRm9yIHRoZSBsYXRlc3QgaW5mbywgc2VlIGh0dHA6Ly9naW1wYWN0LnNvdXJjZWZvcmdlLm5ldC8KCkNvcHlyaWdodCAoYykgMjAwNyBGcmFuY2lzY28gTGVvbiBOYWplcmEuIEMuQy4gODAwODczNzEuCmVtYWlsOiBwcm9qZWN0aWxlbWFuQHlhaG9vLmNvbQoKClRoaXMgc29mdHdhcmUgaXMgcHJvdmlkZWQgJ2FzLWlzJywgd2l0aG91dCBhbnkgZXhwcmVzcyBvciBpbXBsaWVkIHdhcnJhbnR5LgpJbiBubyBldmVudCB3aWxsIHRoZSBhdXRob3JzIGJlIGhlbGQgbGlhYmxlIGZvciBhbnkgZGFtYWdlcyBhcmlzaW5nIGZyb20gdGhlIHVzZSBvZiB0aGlzIHNvZnR3YXJlLgpQZXJtaXNzaW9uIGlzIGdyYW50ZWQgdG8gYW55b25lIHRvIHVzZSB0aGlzIHNvZnR3YXJlIGZvciBhbnkgcHVycG9zZSwKaW5jbHVkaW5nIGNvbW1lcmNpYWwgYXBwbGljYXRpb25zLCBhbmQgdG8gYWx0ZXIgaXQgYW5kIHJlZGlzdHJpYnV0ZSBpdCBmcmVlbHksCnN1YmplY3QgdG8gdGhlIGZvbGxvd2luZyByZXN0cmljdGlvbnM6CgoxLiBUaGUgb3JpZ2luIG9mIHRoaXMgc29mdHdhcmUgbXVzdCBub3QgYmUgbWlzcmVwcmVzZW50ZWQ7IHlvdSBtdXN0IG5vdCBjbGFpbSB0aGF0IHlvdSB3cm90ZSB0aGUgb3JpZ2luYWwgc29mdHdhcmUuIElmIHlvdSB1c2UgdGhpcyBzb2Z0d2FyZSBpbiBhIHByb2R1Y3QsIGFuIGFja25vd2xlZGdtZW50IGluIHRoZSBwcm9kdWN0IGRvY3VtZW50YXRpb24gd291bGQgYmUgYXBwcmVjaWF0ZWQgYnV0IGlzIG5vdCByZXF1aXJlZC4KMi4gQWx0ZXJlZCBzb3VyY2UgdmVyc2lvbnMgbXVzdCBiZSBwbGFpbmx5IG1hcmtlZCBhcyBzdWNoLCBhbmQgbXVzdCBub3QgYmUgbWlzcmVwcmVzZW50ZWQgYXMgYmVpbmcgdGhlIG9yaWdpbmFsIHNvZnR3YXJlLgozLiBUaGlzIG5vdGljZSBtYXkgbm90IGJlIHJlbW92ZWQgb3IgYWx0ZXJlZCBmcm9tIGFueSBzb3VyY2UgZGlzdHJpYnV0aW9uLgoqLwoKI2luY2x1ZGUgIkJ1bGxldENvbGxpc2lvbi9HaW1wYWN0L2J0VHJpYW5nbGVTaGFwZUV4LmgiCgoKCnZvaWQgR0lNX1RSSUFOR0xFX0NPTlRBQ1Q6Om1lcmdlX3BvaW50cyhjb25zdCBidFZlY3RvcjQgJiBwbGFuZSwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgYnRTY2FsYXIgbWFyZ2luLCBjb25zdCBidFZlY3RvcjMgKiBwb2ludHMsIGludCBwb2ludF9jb3VudCkKewogICAgbV9wb2ludF9jb3VudCA9IDA7CiAgICBtX3BlbmV0cmF0aW9uX2RlcHRoPSAtMTAwMC4wZjsKCiAgICBpbnQgcG9pbnRfaW5kaWNlc1tNQVhfVFJJX0NMSVBQSU5HXTsKCglpbnQgX2s7CgogICAgZm9yICggX2s9MDtfazxwb2ludF9jb3VudDtfaysrKQogICAgewogICAgICAgIGJ0U2NhbGFyIF9kaXN0ID0gLSBidF9kaXN0YW5jZV9wb2ludF9wbGFuZShwbGFuZSxwb2ludHNbX2tdKSArIG1hcmdpbjsKCiAgICAgICAgaWYgKF9kaXN0Pj0wLjBmKQogICAgICAgIHsKICAgICAgICAgICAgaWYgKF9kaXN0Pm1fcGVuZXRyYXRpb25fZGVwdGgpCiAgICAgICAgICAgIHsKICAgICAgICAgICAgICAgIG1fcGVuZXRyYXRpb25fZGVwdGggPSBfZGlzdDsKICAgICAgICAgICAgICAgIHBvaW50X2luZGljZXNbMF0gPSBfazsKICAgICAgICAgICAgICAgIG1fcG9pbnRfY291bnQ9MTsKICAgICAgICAgICAgfQogICAgICAgICAgICBlbHNlIGlmICgoX2Rpc3QrU0lNRF9FUFNJTE9OKT49bV9wZW5ldHJhdGlvbl9kZXB0aCkKICAgICAgICAgICAgewogICAgICAgICAgICAgICAgcG9pbnRfaW5kaWNlc1ttX3BvaW50X2NvdW50XSA9IF9rOwogICAgICAgICAgICAgICAgbV9wb2ludF9jb3VudCsrOwogICAgICAgICAgICB9CiAgICAgICAgfQogICAgfQoKICAgIGZvciAoIF9rPTA7X2s8bV9wb2ludF9jb3VudDtfaysrKQogICAgewogICAgICAgIG1fcG9pbnRzW19rXSA9IHBvaW50c1twb2ludF9pbmRpY2VzW19rXV07CiAgICB9Cn0KCi8vL2NsYXNzIGJ0UHJpbWl0aXZlVHJpYW5nbGUKYm9vbCBidFByaW1pdGl2ZVRyaWFuZ2xlOjpvdmVybGFwX3Rlc3RfY29uc2VydmF0aXZlKGNvbnN0IGJ0UHJpbWl0aXZlVHJpYW5nbGUmIG90aGVyKQp7CiAgICBidFNjYWxhciB0b3RhbF9tYXJnaW4gPSBtX21hcmdpbiArIG90aGVyLm1fbWFyZ2luOwogICAgLy8gY2xhc3NpZnkgcG9pbnRzIG9uIG90aGVyIHRyaWFuZ2xlCiAgICBidFNjYWxhciBkaXMwID0gYnRfZGlzdGFuY2VfcG9pbnRfcGxhbmUobV9wbGFuZSxvdGhlci5tX3ZlcnRpY2VzWzBdKSAtIHRvdGFsX21hcmdpbjsKCiAgICBidFNjYWxhciBkaXMxID0gYnRfZGlzdGFuY2VfcG9pbnRfcGxhbmUobV9wbGFuZSxvdGhlci5tX3ZlcnRpY2VzWzFdKSAtIHRvdGFsX21hcmdpbjsKCiAgICBidFNjYWxhciBkaXMyID0gYnRfZGlzdGFuY2VfcG9pbnRfcGxhbmUobV9wbGFuZSxvdGhlci5tX3ZlcnRpY2VzWzJdKSAtIHRvdGFsX21hcmdpbjsKCiAgICBpZiAoZGlzMD4wLjBmJiZkaXMxPjAuMGYmJmRpczI+MC4wZikgcmV0dXJuIGZhbHNlOwoKICAgIC8vIGNsYXNzaWZ5IHBvaW50cyBvbiB0aGlzIHRyaWFuZ2xlCiAgICBkaXMwID0gYnRfZGlzdGFuY2VfcG9pbnRfcGxhbmUob3RoZXIubV9wbGFuZSxtX3ZlcnRpY2VzWzBdKSAtIHRvdGFsX21hcmdpbjsKCiAgICBkaXMxID0gYnRfZGlzdGFuY2VfcG9pbnRfcGxhbmUob3RoZXIubV9wbGFuZSxtX3ZlcnRpY2VzWzFdKSAtIHRvdGFsX21hcmdpbjsKCiAgICBkaXMyID0gYnRfZGlzdGFuY2VfcG9pbnRfcGxhbmUob3RoZXIubV9wbGFuZSxtX3ZlcnRpY2VzWzJdKSAtIHRvdGFsX21hcmdpbjsKCiAgICBpZiAoZGlzMD4wLjBmJiZkaXMxPjAuMGYmJmRpczI+MC4wZikgcmV0dXJuIGZhbHNlOwoKICAgIHJldHVybiB0cnVlOwp9CgppbnQgYnRQcmltaXRpdmVUcmlhbmdsZTo6Y2xpcF90cmlhbmdsZShidFByaW1pdGl2ZVRyaWFuZ2xlICYgb3RoZXIsIGJ0VmVjdG9yMyAqIGNsaXBwZWRfcG9pbnRzICkKewogICAgLy8gZWRnZSAwCgogICAgYnRWZWN0b3IzIHRlbXBfcG9pbnRzW01BWF9UUklfQ0xJUFBJTkddOwoKCiAgICBidFZlY3RvcjQgZWRnZXBsYW5lOwoKICAgIGdldF9lZGdlX3BsYW5lKDAsZWRnZXBsYW5lKTsKCgogICAgaW50IGNsaXBwZWRfY291bnQgPSBidF9wbGFuZV9jbGlwX3RyaWFuZ2xlKAogICAgICAgICAgICAgICAgICAgICAgICAgICAgZWRnZXBsYW5lLG90aGVyLm1fdmVydGljZXNbMF0sb3RoZXIubV92ZXJ0aWNlc1sxXSxvdGhlci5tX3ZlcnRpY2VzWzJdLHRlbXBfcG9pbnRzKTsKCiAgICBpZiAoY2xpcHBlZF9jb3VudCA9PSAwKSByZXR1cm4gMDsKCiAgICBidFZlY3RvcjMgdGVtcF9wb2ludHMxW01BWF9UUklfQ0xJUFBJTkddOwoKCiAgICAvLyBlZGdlIDEKICAgIGdldF9lZGdlX3BsYW5lKDEsZWRnZXBsYW5lKTsKCgogICAgY2xpcHBlZF9jb3VudCA9IGJ0X3BsYW5lX2NsaXBfcG9seWdvbihlZGdlcGxhbmUsdGVtcF9wb2ludHMsY2xpcHBlZF9jb3VudCx0ZW1wX3BvaW50czEpOwoKICAgIGlmIChjbGlwcGVkX2NvdW50ID09IDApIHJldHVybiAwOwoKICAgIC8vIGVkZ2UgMgogICAgZ2V0X2VkZ2VfcGxhbmUoMixlZGdlcGxhbmUpOwoKICAgIGNsaXBwZWRfY291bnQgPSBidF9wbGFuZV9jbGlwX3BvbHlnb24oCiAgICAgICAgICAgICAgICAgICAgICAgIGVkZ2VwbGFuZSx0ZW1wX3BvaW50czEsY2xpcHBlZF9jb3VudCxjbGlwcGVkX3BvaW50cyk7CgogICAgcmV0dXJuIGNsaXBwZWRfY291bnQ7Cn0KCmJvb2wgYnRQcmltaXRpdmVUcmlhbmdsZTo6ZmluZF90cmlhbmdsZV9jb2xsaXNpb25fY2xpcF9tZXRob2QoYnRQcmltaXRpdmVUcmlhbmdsZSAmIG90aGVyLCBHSU1fVFJJQU5HTEVfQ09OVEFDVCAmIGNvbnRhY3RzKQp7CiAgICBidFNjYWxhciBtYXJnaW4gPSBtX21hcmdpbiArIG90aGVyLm1fbWFyZ2luOwoKICAgIGJ0VmVjdG9yMyBjbGlwcGVkX3BvaW50c1tNQVhfVFJJX0NMSVBQSU5HXTsKICAgIGludCBjbGlwcGVkX2NvdW50OwogICAgLy9jcmVhdGUgcGxhbmVzCiAgICAvLyBwbGFuZSB2IHZzIFUgcG9pbnRzCgogICAgR0lNX1RSSUFOR0xFX0NPTlRBQ1QgY29udGFjdHMxOwoKICAgIGNvbnRhY3RzMS5tX3NlcGFyYXRpbmdfbm9ybWFsID0gbV9wbGFuZTsKCgogICAgY2xpcHBlZF9jb3VudCA9IGNsaXBfdHJpYW5nbGUob3RoZXIsY2xpcHBlZF9wb2ludHMpOwoKICAgIGlmIChjbGlwcGVkX2NvdW50ID09IDAgKQogICAgewogICAgICAgIHJldHVybiBmYWxzZTsvL1JlamVjdAogICAgfQoKICAgIC8vZmluZCBtb3N0IGRlZXAgaW50ZXJ2YWwgZmFjZTEKICAgIGNvbnRhY3RzMS5tZXJnZV9wb2ludHMoY29udGFjdHMxLm1fc2VwYXJhdGluZ19ub3JtYWwsbWFyZ2luLGNsaXBwZWRfcG9pbnRzLGNsaXBwZWRfY291bnQpOwogICAgaWYgKGNvbnRhY3RzMS5tX3BvaW50X2NvdW50ID09IDApIHJldHVybiBmYWxzZTsgLy8gdG9vIGZhcgogICAgLy9Ob3JtYWwgcG9pbnRpbmcgdG8gdGhpcyB0cmlhbmdsZQogICAgY29udGFjdHMxLm1fc2VwYXJhdGluZ19ub3JtYWwgKj0gLTEuZjsKCgogICAgLy9DbGlwIHRyaTEgYnkgdHJpMiBlZGdlcwogICAgR0lNX1RSSUFOR0xFX0NPTlRBQ1QgY29udGFjdHMyOwogICAgY29udGFjdHMyLm1fc2VwYXJhdGluZ19ub3JtYWwgPSBvdGhlci5tX3BsYW5lOwoKICAgIGNsaXBwZWRfY291bnQgPSBvdGhlci5jbGlwX3RyaWFuZ2xlKCp0aGlzLGNsaXBwZWRfcG9pbnRzKTsKCiAgICBpZiAoY2xpcHBlZF9jb3VudCA9PSAwICkKICAgIHsKICAgICAgICByZXR1cm4gZmFsc2U7Ly9SZWplY3QKICAgIH0KCiAgICAvL2ZpbmQgbW9zdCBkZWVwIGludGVydmFsIGZhY2UxCiAgICBjb250YWN0czIubWVyZ2VfcG9pbnRzKGNvbnRhY3RzMi5tX3NlcGFyYXRpbmdfbm9ybWFsLG1hcmdpbixjbGlwcGVkX3BvaW50cyxjbGlwcGVkX2NvdW50KTsKICAgIGlmIChjb250YWN0czIubV9wb2ludF9jb3VudCA9PSAwKSByZXR1cm4gZmFsc2U7IC8vIHRvbyBmYXIKCgoKCiAgICAvLy8vY2hlY2sgbW9zdCBkaXIgZm9yIGNvbnRhY3RzCiAgICBpZiAoY29udGFjdHMyLm1fcGVuZXRyYXRpb25fZGVwdGg8Y29udGFjdHMxLm1fcGVuZXRyYXRpb25fZGVwdGgpCiAgICB7CiAgICAgICAgY29udGFjdHMuY29weV9mcm9tKGNvbnRhY3RzMik7CiAgICB9CiAgICBlbHNlCiAgICB7CiAgICAgICAgY29udGFjdHMuY29weV9mcm9tKGNvbnRhY3RzMSk7CiAgICB9CiAgICByZXR1cm4gdHJ1ZTsKfQoKCgovLy9jbGFzcyBidFRyaWFuZ2xlU2hhcGVFeDogcHVibGljIGJ0VHJpYW5nbGVTaGFwZQoKYm9vbCBidFRyaWFuZ2xlU2hhcGVFeDo6b3ZlcmxhcF90ZXN0X2NvbnNlcnZhdGl2ZShjb25zdCBidFRyaWFuZ2xlU2hhcGVFeCYgb3RoZXIpCnsKICAgIGJ0U2NhbGFyIHRvdGFsX21hcmdpbiA9IGdldE1hcmdpbigpICsgb3RoZXIuZ2V0TWFyZ2luKCk7CgogICAgYnRWZWN0b3I0IHBsYW5lMDsKICAgIGJ1aWxkVHJpUGxhbmUocGxhbmUwKTsKICAgIGJ0VmVjdG9yNCBwbGFuZTE7CiAgICBvdGhlci5idWlsZFRyaVBsYW5lKHBsYW5lMSk7CgogICAgLy8gY2xhc3NpZnkgcG9pbnRzIG9uIG90aGVyIHRyaWFuZ2xlCiAgICBidFNjYWxhciBkaXMwID0gYnRfZGlzdGFuY2VfcG9pbnRfcGxhbmUocGxhbmUwLG90aGVyLm1fdmVydGljZXMxWzBdKSAtIHRvdGFsX21hcmdpbjsKCiAgICBidFNjYWxhciBkaXMxID0gYnRfZGlzdGFuY2VfcG9pbnRfcGxhbmUocGxhbmUwLG90aGVyLm1fdmVydGljZXMxWzFdKSAtIHRvdGFsX21hcmdpbjsKCiAgICBidFNjYWxhciBkaXMyID0gYnRfZGlzdGFuY2VfcG9pbnRfcGxhbmUocGxhbmUwLG90aGVyLm1fdmVydGljZXMxWzJdKSAtIHRvdGFsX21hcmdpbjsKCiAgICBpZiAoZGlzMD4wLjBmJiZkaXMxPjAuMGYmJmRpczI+MC4wZikgcmV0dXJuIGZhbHNlOwoKICAgIC8vIGNsYXNzaWZ5IHBvaW50cyBvbiB0aGlzIHRyaWFuZ2xlCiAgICBkaXMwID0gYnRfZGlzdGFuY2VfcG9pbnRfcGxhbmUocGxhbmUxLG1fdmVydGljZXMxWzBdKSAtIHRvdGFsX21hcmdpbjsKCiAgICBkaXMxID0gYnRfZGlzdGFuY2VfcG9pbnRfcGxhbmUocGxhbmUxLG1fdmVydGljZXMxWzFdKSAtIHRvdGFsX21hcmdpbjsKCiAgICBkaXMyID0gYnRfZGlzdGFuY2VfcG9pbnRfcGxhbmUocGxhbmUxLG1fdmVydGljZXMxWzJdKSAtIHRvdGFsX21hcmdpbjsKCiAgICBpZiAoZGlzMD4wLjBmJiZkaXMxPjAuMGYmJmRpczI+MC4wZikgcmV0dXJuIGZhbHNlOwoKICAgIHJldHVybiB0cnVlOwp9CgoK