Ly8KLy8gqSBDb3B5cmlnaHQgSGVucmlrIFJhdm4gMjAwNAovLwovLyBVc2UsIG1vZGlmaWNhdGlvbiBhbmQgZGlzdHJpYnV0aW9uIGFyZSBzdWJqZWN0IHRvIHRoZSBCb29zdCBTb2Z0d2FyZSBMaWNlbnNlLCBWZXJzaW9uIDEuMC4gCi8vIChTZWUgYWNjb21wYW55aW5nIGZpbGUgTElDRU5TRV8xXzAudHh0IG9yIGNvcHkgYXQgaHR0cDovL3d3dy5ib29zdC5vcmcvTElDRU5TRV8xXzAudHh0KQovLwoKdXNpbmcgU3lzdGVtOwp1c2luZyBTeXN0ZW0uUnVudGltZS5JbnRlcm9wU2VydmljZXM7CnVzaW5nIFN5c3RlbS5UZXh0OwoKCm5hbWVzcGFjZSBEb3RaTGliCnsKICAgICNyZWdpb24gQ2hlY2tzdW1HZW5lcmF0b3JCYXNlCiAgICAvLy8gPHN1bW1hcnk+CiAgICAvLy8gSW1wbGVtZW50cyB0aGUgY29tbW9uIGZ1bmN0aW9uYWxpdHkgbmVlZGVkIGZvciBhbGwgPHNlZSBjcmVmPSJDaGVja3N1bUdlbmVyYXRvciIvPnMKICAgIC8vLyA8L3N1bW1hcnk+CiAgICAvLy8gPGV4YW1wbGU+PC9leGFtcGxlPgogICAgcHVibGljIGFic3RyYWN0IGNsYXNzIENoZWNrc3VtR2VuZXJhdG9yQmFzZSA6IENoZWNrc3VtR2VuZXJhdG9yCiAgICB7CiAgICAgICAgLy8vIDxzdW1tYXJ5PgogICAgICAgIC8vLyBUaGUgdmFsdWUgb2YgdGhlIGN1cnJlbnQgY2hlY2tzdW0KICAgICAgICAvLy8gPC9zdW1tYXJ5PgogICAgICAgIHByb3RlY3RlZCB1aW50IF9jdXJyZW50OwoKICAgICAgICAvLy8gPHN1bW1hcnk+CiAgICAgICAgLy8vIEluaXRpYWxpemVzIGEgbmV3IGluc3RhbmNlIG9mIHRoZSBjaGVja3N1bSBnZW5lcmF0b3IgYmFzZSAtIHRoZSBjdXJyZW50IGNoZWNrc3VtIGlzIAogICAgICAgIC8vLyBzZXQgdG8gemVybwogICAgICAgIC8vLyA8L3N1bW1hcnk+CiAgICAgICAgcHVibGljIENoZWNrc3VtR2VuZXJhdG9yQmFzZSgpCiAgICAgICAgewogICAgICAgICAgICBfY3VycmVudCA9IDA7CiAgICAgICAgfQoKICAgICAgICAvLy8gPHN1bW1hcnk+CiAgICAgICAgLy8vIEluaXRpYWxpemVzIGEgbmV3IGluc3RhbmNlIG9mIHRoZSBjaGVja3N1bSBnZW5lcmF0b3IgYmFzZXdpdGggYSBzcGVjaWZpZWQgdmFsdWUKICAgICAgICAvLy8gPC9zdW1tYXJ5PgogICAgICAgIC8vLyA8cGFyYW0gbmFtZT0iaW5pdGlhbFZhbHVlIj5UaGUgdmFsdWUgdG8gc2V0IHRoZSBjdXJyZW50IGNoZWNrc3VtIHRvPC9wYXJhbT4KICAgICAgICBwdWJsaWMgQ2hlY2tzdW1HZW5lcmF0b3JCYXNlKHVpbnQgaW5pdGlhbFZhbHVlKQogICAgICAgIHsKICAgICAgICAgICAgX2N1cnJlbnQgPSBpbml0aWFsVmFsdWU7CiAgICAgICAgfQoKICAgICAgICAvLy8gPHN1bW1hcnk+CiAgICAgICAgLy8vIFJlc2V0cyB0aGUgY3VycmVudCBjaGVja3N1bSB0byB6ZXJvCiAgICAgICAgLy8vIDwvc3VtbWFyeT4KICAgICAgICBwdWJsaWMgdm9pZCBSZXNldCgpIHsgX2N1cnJlbnQgPSAwOyB9CgogICAgICAgIC8vLyA8c3VtbWFyeT4KICAgICAgICAvLy8gR2V0cyB0aGUgY3VycmVudCBjaGVja3N1bSB2YWx1ZQogICAgICAgIC8vLyA8L3N1bW1hcnk+CiAgICAgICAgcHVibGljIHVpbnQgVmFsdWUgeyBnZXQgeyByZXR1cm4gX2N1cnJlbnQ7IH0gfQoKICAgICAgICAvLy8gPHN1bW1hcnk+CiAgICAgICAgLy8vIFVwZGF0ZXMgdGhlIGN1cnJlbnQgY2hlY2tzdW0gd2l0aCBwYXJ0IG9mIGFuIGFycmF5IG9mIGJ5dGVzCiAgICAgICAgLy8vIDwvc3VtbWFyeT4KICAgICAgICAvLy8gPHBhcmFtIG5hbWU9ImRhdGEiPlRoZSBkYXRhIHRvIHVwZGF0ZSB0aGUgY2hlY2tzdW0gd2l0aDwvcGFyYW0+CiAgICAgICAgLy8vIDxwYXJhbSBuYW1lPSJvZmZzZXQiPldoZXJlIGluIDxjPmRhdGE8L2M+IHRvIHN0YXJ0IHVwZGF0aW5nPC9wYXJhbT4KICAgICAgICAvLy8gPHBhcmFtIG5hbWU9ImNvdW50Ij5UaGUgbnVtYmVyIG9mIGJ5dGVzIGZyb20gPGM+ZGF0YTwvYz4gdG8gdXNlPC9wYXJhbT4KICAgICAgICAvLy8gPGV4Y2VwdGlvbiBjcmVmPSJBcmd1bWVudEV4Y2VwdGlvbiI+VGhlIHN1bSBvZiBvZmZzZXQgYW5kIGNvdW50IGlzIGxhcmdlciB0aGFuIHRoZSBsZW5ndGggb2YgPGM+ZGF0YTwvYz48L2V4Y2VwdGlvbj4KICAgICAgICAvLy8gPGV4Y2VwdGlvbiBjcmVmPSJOdWxsUmVmZXJlbmNlRXhjZXB0aW9uIj48Yz5kYXRhPC9jPiBpcyBhIG51bGwgcmVmZXJlbmNlPC9leGNlcHRpb24+CiAgICAgICAgLy8vIDxleGNlcHRpb24gY3JlZj0iQXJndW1lbnRPdXRPZlJhbmdlRXhjZXB0aW9uIj5PZmZzZXQgb3IgY291bnQgaXMgbmVnYXRpdmUuPC9leGNlcHRpb24+CiAgICAgICAgLy8vIDxyZW1hcmtzPkFsbCB0aGUgb3RoZXIgPGM+VXBkYXRlPC9jPiBtZXRob2RzIGFyZSBpbXBsbWVuZXRlZCBpbiB0ZXJtcyBvZiB0aGlzIG9uZS4gCiAgICAgICAgLy8vIFRoaXMgaXMgdGhlcmVmb3JlIHRoZSBvbmx5IG1ldGhvZCBhIGRlcml2ZWQgY2xhc3MgaGFzIHRvIGltcGxlbWVudDwvcmVtYXJrcz4KICAgICAgICBwdWJsaWMgYWJzdHJhY3Qgdm9pZCBVcGRhdGUoYnl0ZVtdIGRhdGEsIGludCBvZmZzZXQsIGludCBjb3VudCk7CgogICAgICAgIC8vLyA8c3VtbWFyeT4KICAgICAgICAvLy8gVXBkYXRlcyB0aGUgY3VycmVudCBjaGVja3N1bSB3aXRoIGFuIGFycmF5IG9mIGJ5dGVzLgogICAgICAgIC8vLyA8L3N1bW1hcnk+CiAgICAgICAgLy8vIDxwYXJhbSBuYW1lPSJkYXRhIj5UaGUgZGF0YSB0byB1cGRhdGUgdGhlIGNoZWNrc3VtIHdpdGg8L3BhcmFtPgogICAgICAgIHB1YmxpYyB2b2lkIFVwZGF0ZShieXRlW10gZGF0YSkKICAgICAgICB7CiAgICAgICAgICAgIFVwZGF0ZShkYXRhLCAwLCBkYXRhLkxlbmd0aCk7CiAgICAgICAgfQoKICAgICAgICAvLy8gPHN1bW1hcnk+CiAgICAgICAgLy8vIFVwZGF0ZXMgdGhlIGN1cnJlbnQgY2hlY2tzdW0gd2l0aCB0aGUgZGF0YSBmcm9tIGEgc3RyaW5nCiAgICAgICAgLy8vIDwvc3VtbWFyeT4KICAgICAgICAvLy8gPHBhcmFtIG5hbWU9ImRhdGEiPlRoZSBzdHJpbmcgdG8gdXBkYXRlIHRoZSBjaGVja3N1bSB3aXRoPC9wYXJhbT4KICAgICAgICAvLy8gPHJlbWFya3M+VGhlIGNoYXJhY3RlcnMgaW4gdGhlIHN0cmluZyBhcmUgY29udmVydGVkIGJ5IHRoZSBVVEYtOCBlbmNvZGluZzwvcmVtYXJrcz4KICAgICAgICBwdWJsaWMgdm9pZCBVcGRhdGUoc3RyaW5nIGRhdGEpCiAgICAgICAgewoJCQlVcGRhdGUoRW5jb2RpbmcuVVRGOC5HZXRCeXRlcyhkYXRhKSk7CiAgICAgICAgfQoKICAgICAgICAvLy8gPHN1bW1hcnk+CiAgICAgICAgLy8vIFVwZGF0ZXMgdGhlIGN1cnJlbnQgY2hlY2tzdW0gd2l0aCB0aGUgZGF0YSBmcm9tIGEgc3RyaW5nLCB1c2luZyBhIHNwZWNpZmljIGVuY29kaW5nCiAgICAgICAgLy8vIDwvc3VtbWFyeT4KICAgICAgICAvLy8gPHBhcmFtIG5hbWU9ImRhdGEiPlRoZSBzdHJpbmcgdG8gdXBkYXRlIHRoZSBjaGVja3N1bSB3aXRoPC9wYXJhbT4KICAgICAgICAvLy8gPHBhcmFtIG5hbWU9ImVuY29kaW5nIj5UaGUgZW5jb2RpbmcgdG8gdXNlPC9wYXJhbT4KICAgICAgICBwdWJsaWMgdm9pZCBVcGRhdGUoc3RyaW5nIGRhdGEsIEVuY29kaW5nIGVuY29kaW5nKQogICAgICAgIHsKICAgICAgICAgICAgVXBkYXRlKGVuY29kaW5nLkdldEJ5dGVzKGRhdGEpKTsKICAgICAgICB9CgogICAgfQogICAgI2VuZHJlZ2lvbgoKICAgICNyZWdpb24gQ1JDMzIKICAgIC8vLyA8c3VtbWFyeT4KICAgIC8vLyBJbXBsZW1lbnRzIGEgQ1JDMzIgY2hlY2tzdW0gZ2VuZXJhdG9yCiAgICAvLy8gPC9zdW1tYXJ5PgogICAgcHVibGljIHNlYWxlZCBjbGFzcyBDUkMzMkNoZWNrc3VtIDogQ2hlY2tzdW1HZW5lcmF0b3JCYXNlICAgIAogICAgewogICAgICAgICNyZWdpb24gRExMIGltcG9ydHMKCiAgICAgICAgW0RsbEltcG9ydCgiWkxJQjEuZGxsIiwgQ2FsbGluZ0NvbnZlbnRpb249Q2FsbGluZ0NvbnZlbnRpb24uQ2RlY2wpXQogICAgICAgIHByaXZhdGUgc3RhdGljIGV4dGVybiB1aW50IGNyYzMyKHVpbnQgY3JjLCBpbnQgZGF0YSwgdWludCBsZW5ndGgpOwoKICAgICAgICAjZW5kcmVnaW9uCgogICAgICAgIC8vLyA8c3VtbWFyeT4KICAgICAgICAvLy8gSW5pdGlhbGl6ZXMgYSBuZXcgaW5zdGFuY2Ugb2YgdGhlIENSQzMyIGNoZWNrc3VtIGdlbmVyYXRvcgogICAgICAgIC8vLyA8L3N1bW1hcnk+CiAgICAgICAgcHVibGljIENSQzMyQ2hlY2tzdW0oKSA6IGJhc2UoKSB7fQoKICAgICAgICAvLy8gPHN1bW1hcnk+CiAgICAgICAgLy8vIEluaXRpYWxpemVzIGEgbmV3IGluc3RhbmNlIG9mIHRoZSBDUkMzMiBjaGVja3N1bSBnZW5lcmF0b3Igd2l0aCBhIHNwZWNpZmllZCB2YWx1ZQogICAgICAgIC8vLyA8L3N1bW1hcnk+CiAgICAgICAgLy8vIDxwYXJhbSBuYW1lPSJpbml0aWFsVmFsdWUiPlRoZSB2YWx1ZSB0byBzZXQgdGhlIGN1cnJlbnQgY2hlY2tzdW0gdG88L3BhcmFtPgogICAgICAgIHB1YmxpYyBDUkMzMkNoZWNrc3VtKHVpbnQgaW5pdGlhbFZhbHVlKSA6IGJhc2UoaW5pdGlhbFZhbHVlKSB7fQoKICAgICAgICAvLy8gPHN1bW1hcnk+CiAgICAgICAgLy8vIFVwZGF0ZXMgdGhlIGN1cnJlbnQgY2hlY2tzdW0gd2l0aCBwYXJ0IG9mIGFuIGFycmF5IG9mIGJ5dGVzCiAgICAgICAgLy8vIDwvc3VtbWFyeT4KICAgICAgICAvLy8gPHBhcmFtIG5hbWU9ImRhdGEiPlRoZSBkYXRhIHRvIHVwZGF0ZSB0aGUgY2hlY2tzdW0gd2l0aDwvcGFyYW0+CiAgICAgICAgLy8vIDxwYXJhbSBuYW1lPSJvZmZzZXQiPldoZXJlIGluIDxjPmRhdGE8L2M+IHRvIHN0YXJ0IHVwZGF0aW5nPC9wYXJhbT4KICAgICAgICAvLy8gPHBhcmFtIG5hbWU9ImNvdW50Ij5UaGUgbnVtYmVyIG9mIGJ5dGVzIGZyb20gPGM+ZGF0YTwvYz4gdG8gdXNlPC9wYXJhbT4KICAgICAgICAvLy8gPGV4Y2VwdGlvbiBjcmVmPSJBcmd1bWVudEV4Y2VwdGlvbiI+VGhlIHN1bSBvZiBvZmZzZXQgYW5kIGNvdW50IGlzIGxhcmdlciB0aGFuIHRoZSBsZW5ndGggb2YgPGM+ZGF0YTwvYz48L2V4Y2VwdGlvbj4KICAgICAgICAvLy8gPGV4Y2VwdGlvbiBjcmVmPSJOdWxsUmVmZXJlbmNlRXhjZXB0aW9uIj48Yz5kYXRhPC9jPiBpcyBhIG51bGwgcmVmZXJlbmNlPC9leGNlcHRpb24+CiAgICAgICAgLy8vIDxleGNlcHRpb24gY3JlZj0iQXJndW1lbnRPdXRPZlJhbmdlRXhjZXB0aW9uIj5PZmZzZXQgb3IgY291bnQgaXMgbmVnYXRpdmUuPC9leGNlcHRpb24+CiAgICAgICAgcHVibGljIG92ZXJyaWRlIHZvaWQgVXBkYXRlKGJ5dGVbXSBkYXRhLCBpbnQgb2Zmc2V0LCBpbnQgY291bnQpCiAgICAgICAgewogICAgICAgICAgICBpZiAob2Zmc2V0IDwgMCB8fCBjb3VudCA8IDApIHRocm93IG5ldyBBcmd1bWVudE91dE9mUmFuZ2VFeGNlcHRpb24oKTsKICAgICAgICAgICAgaWYgKChvZmZzZXQrY291bnQpID4gZGF0YS5MZW5ndGgpIHRocm93IG5ldyBBcmd1bWVudEV4Y2VwdGlvbigpOwogICAgICAgICAgICBHQ0hhbmRsZSBoRGF0YSA9IEdDSGFuZGxlLkFsbG9jKGRhdGEsIEdDSGFuZGxlVHlwZS5QaW5uZWQpOwogICAgICAgICAgICB0cnkKICAgICAgICAgICAgewogICAgICAgICAgICAgICAgX2N1cnJlbnQgPSBjcmMzMihfY3VycmVudCwgaERhdGEuQWRkck9mUGlubmVkT2JqZWN0KCkuVG9JbnQzMigpK29mZnNldCwgKHVpbnQpY291bnQpOwogICAgICAgICAgICB9CiAgICAgICAgICAgIGZpbmFsbHkKICAgICAgICAgICAgewogICAgICAgICAgICAgICAgaERhdGEuRnJlZSgpOwogICAgICAgICAgICB9CiAgICAgICAgfQoKICAgIH0KICAgICNlbmRyZWdpb24KCiAgICAjcmVnaW9uIEFkbGVyCiAgICAvLy8gPHN1bW1hcnk+CiAgICAvLy8gSW1wbGVtZW50cyBhIGNoZWNrc3VtIGdlbmVyYXRvciB0aGF0IGNvbXB1dGVzIHRoZSBBZGxlciBjaGVja3N1bSBvbiBkYXRhCiAgICAvLy8gPC9zdW1tYXJ5PgogICAgcHVibGljIHNlYWxlZCBjbGFzcyBBZGxlckNoZWNrc3VtIDogQ2hlY2tzdW1HZW5lcmF0b3JCYXNlICAgIAogICAgewogICAgICAgICNyZWdpb24gRExMIGltcG9ydHMKCiAgICAgICAgW0RsbEltcG9ydCgiWkxJQjEuZGxsIiwgQ2FsbGluZ0NvbnZlbnRpb249Q2FsbGluZ0NvbnZlbnRpb24uQ2RlY2wpXQogICAgICAgIHByaXZhdGUgc3RhdGljIGV4dGVybiB1aW50IGFkbGVyMzIodWludCBhZGxlciwgaW50IGRhdGEsIHVpbnQgbGVuZ3RoKTsKCiAgICAgICAgI2VuZHJlZ2lvbgoKICAgICAgICAvLy8gPHN1bW1hcnk+CiAgICAgICAgLy8vIEluaXRpYWxpemVzIGEgbmV3IGluc3RhbmNlIG9mIHRoZSBBZGxlciBjaGVja3N1bSBnZW5lcmF0b3IKICAgICAgICAvLy8gPC9zdW1tYXJ5PgogICAgICAgIHB1YmxpYyBBZGxlckNoZWNrc3VtKCkgOiBiYXNlKCkge30KCiAgICAgICAgLy8vIDxzdW1tYXJ5PgogICAgICAgIC8vLyBJbml0aWFsaXplcyBhIG5ldyBpbnN0YW5jZSBvZiB0aGUgQWRsZXIgY2hlY2tzdW0gZ2VuZXJhdG9yIHdpdGggYSBzcGVjaWZpZWQgdmFsdWUKICAgICAgICAvLy8gPC9zdW1tYXJ5PgogICAgICAgIC8vLyA8cGFyYW0gbmFtZT0iaW5pdGlhbFZhbHVlIj5UaGUgdmFsdWUgdG8gc2V0IHRoZSBjdXJyZW50IGNoZWNrc3VtIHRvPC9wYXJhbT4KICAgICAgICBwdWJsaWMgQWRsZXJDaGVja3N1bSh1aW50IGluaXRpYWxWYWx1ZSkgOiBiYXNlKGluaXRpYWxWYWx1ZSkge30KCiAgICAgICAgLy8vIDxzdW1tYXJ5PgogICAgICAgIC8vLyBVcGRhdGVzIHRoZSBjdXJyZW50IGNoZWNrc3VtIHdpdGggcGFydCBvZiBhbiBhcnJheSBvZiBieXRlcwogICAgICAgIC8vLyA8L3N1bW1hcnk+CiAgICAgICAgLy8vIDxwYXJhbSBuYW1lPSJkYXRhIj5UaGUgZGF0YSB0byB1cGRhdGUgdGhlIGNoZWNrc3VtIHdpdGg8L3BhcmFtPgogICAgICAgIC8vLyA8cGFyYW0gbmFtZT0ib2Zmc2V0Ij5XaGVyZSBpbiA8Yz5kYXRhPC9jPiB0byBzdGFydCB1cGRhdGluZzwvcGFyYW0+CiAgICAgICAgLy8vIDxwYXJhbSBuYW1lPSJjb3VudCI+VGhlIG51bWJlciBvZiBieXRlcyBmcm9tIDxjPmRhdGE8L2M+IHRvIHVzZTwvcGFyYW0+CiAgICAgICAgLy8vIDxleGNlcHRpb24gY3JlZj0iQXJndW1lbnRFeGNlcHRpb24iPlRoZSBzdW0gb2Ygb2Zmc2V0IGFuZCBjb3VudCBpcyBsYXJnZXIgdGhhbiB0aGUgbGVuZ3RoIG9mIDxjPmRhdGE8L2M+PC9leGNlcHRpb24+CiAgICAgICAgLy8vIDxleGNlcHRpb24gY3JlZj0iTnVsbFJlZmVyZW5jZUV4Y2VwdGlvbiI+PGM+ZGF0YTwvYz4gaXMgYSBudWxsIHJlZmVyZW5jZTwvZXhjZXB0aW9uPgogICAgICAgIC8vLyA8ZXhjZXB0aW9uIGNyZWY9IkFyZ3VtZW50T3V0T2ZSYW5nZUV4Y2VwdGlvbiI+T2Zmc2V0IG9yIGNvdW50IGlzIG5lZ2F0aXZlLjwvZXhjZXB0aW9uPgogICAgICAgIHB1YmxpYyBvdmVycmlkZSB2b2lkIFVwZGF0ZShieXRlW10gZGF0YSwgaW50IG9mZnNldCwgaW50IGNvdW50KQogICAgICAgIHsKICAgICAgICAgICAgaWYgKG9mZnNldCA8IDAgfHwgY291bnQgPCAwKSB0aHJvdyBuZXcgQXJndW1lbnRPdXRPZlJhbmdlRXhjZXB0aW9uKCk7CiAgICAgICAgICAgIGlmICgob2Zmc2V0K2NvdW50KSA+IGRhdGEuTGVuZ3RoKSB0aHJvdyBuZXcgQXJndW1lbnRFeGNlcHRpb24oKTsKICAgICAgICAgICAgR0NIYW5kbGUgaERhdGEgPSBHQ0hhbmRsZS5BbGxvYyhkYXRhLCBHQ0hhbmRsZVR5cGUuUGlubmVkKTsKICAgICAgICAgICAgdHJ5CiAgICAgICAgICAgIHsKICAgICAgICAgICAgICAgIF9jdXJyZW50ID0gYWRsZXIzMihfY3VycmVudCwgaERhdGEuQWRkck9mUGlubmVkT2JqZWN0KCkuVG9JbnQzMigpK29mZnNldCwgKHVpbnQpY291bnQpOwogICAgICAgICAgICB9CiAgICAgICAgICAgIGZpbmFsbHkKICAgICAgICAgICAgewogICAgICAgICAgICAgICAgaERhdGEuRnJlZSgpOwogICAgICAgICAgICB9CiAgICAgICAgfQoKICAgIH0KICAgICNlbmRyZWdpb24KCn0=