Ly8NCi8vIKkgQ29weXJpZ2h0IEhlbnJpayBSYXZuIDIwMDQNCi8vDQovLyBVc2UsIG1vZGlmaWNhdGlvbiBhbmQgZGlzdHJpYnV0aW9uIGFyZSBzdWJqZWN0IHRvIHRoZSBCb29zdCBTb2Z0d2FyZSBMaWNlbnNlLCBWZXJzaW9uIDEuMC4gDQovLyAoU2VlIGFjY29tcGFueWluZyBmaWxlIExJQ0VOU0VfMV8wLnR4dCBvciBjb3B5IGF0IGh0dHA6Ly93d3cuYm9vc3Qub3JnL0xJQ0VOU0VfMV8wLnR4dCkNCi8vDQoNCnVzaW5nIFN5c3RlbTsNCnVzaW5nIFN5c3RlbS5SdW50aW1lLkludGVyb3BTZXJ2aWNlczsNCg0KbmFtZXNwYWNlIERvdFpMaWINCnsNCgkvLy8gPHN1bW1hcnk+DQoJLy8vIEltcGxlbWVudHMgdGhlIGNvbW1vbiBmdW5jdGlvbmFsaXR5IG5lZWRlZCBmb3IgYWxsIDxzZWUgY3JlZj0iQ29kZWMiLz5zDQoJLy8vIDwvc3VtbWFyeT4NCglwdWJsaWMgYWJzdHJhY3QgY2xhc3MgQ29kZWNCYXNlIDogQ29kZWMsIElEaXNwb3NhYmxlDQoJew0KDQogICAgICAgICNyZWdpb24gRGF0YSBtZW1iZXJzDQoNCiAgICAgICAgLy8vIDxzdW1tYXJ5Pg0KICAgICAgICAvLy8gSW5zdGFuY2Ugb2YgdGhlIGludGVybmFsIHpsaWIgYnVmZmVyIHN0cnVjdHVyZSB0aGF0IGlzIA0KICAgICAgICAvLy8gcGFzc2VkIHRvIGFsbCBmdW5jdGlvbnMgaW4gdGhlIHpsaWIgZGxsDQogICAgICAgIC8vLyA8L3N1bW1hcnk+DQogICAgICAgIGludGVybmFsIFpTdHJlYW0gX3p0cmVhbSA9IG5ldyBaU3RyZWFtKCk7DQoNCiAgICAgICAgLy8vIDxzdW1tYXJ5Pg0KICAgICAgICAvLy8gVHJ1ZSBpZiB0aGUgb2JqZWN0IGluc3RhbmNlIGhhcyBiZWVuIGRpc3Bvc2VkLCBmYWxzZSBvdGhlcndpc2UNCiAgICAgICAgLy8vIDwvc3VtbWFyeT4NCiAgICAgICAgcHJvdGVjdGVkIGJvb2wgX2lzRGlzcG9zZWQgPSBmYWxzZTsNCg0KICAgICAgICAvLy8gPHN1bW1hcnk+DQogICAgICAgIC8vLyBUaGUgc2l6ZSBvZiB0aGUgaW50ZXJuYWwgYnVmZmVycw0KICAgICAgICAvLy8gPC9zdW1tYXJ5Pg0KICAgICAgICBwcm90ZWN0ZWQgY29uc3QgaW50IGtCdWZmZXJTaXplID0gMTYzODQ7DQoNCiAgICAgICAgcHJpdmF0ZSBieXRlW10gX291dEJ1ZmZlciA9IG5ldyBieXRlW2tCdWZmZXJTaXplXTsNCiAgICAgICAgcHJpdmF0ZSBieXRlW10gX2luQnVmZmVyID0gbmV3IGJ5dGVba0J1ZmZlclNpemVdOw0KDQogICAgICAgIHByaXZhdGUgR0NIYW5kbGUgX2hJbnB1dDsNCiAgICAgICAgcHJpdmF0ZSBHQ0hhbmRsZSBfaE91dHB1dDsNCg0KICAgICAgICBwcml2YXRlIHVpbnQgX2NoZWNrc3VtID0gMDsNCg0KICAgICAgICAjZW5kcmVnaW9uDQoNCiAgICAgICAgLy8vIDxzdW1tYXJ5Pg0KICAgICAgICAvLy8gSW5pdGlhbGl6ZXMgYSBuZXcgaW5zdGFuY2Ugb2YgdGhlIDxjPkNvZGVCYXNlPC9jPiBjbGFzcy4gDQogICAgICAgIC8vLyA8L3N1bW1hcnk+DQoJCXB1YmxpYyBDb2RlY0Jhc2UoKQ0KCQl7DQogICAgICAgICAgICB0cnkNCiAgICAgICAgICAgIHsNCiAgICAgICAgICAgICAgICBfaElucHV0ID0gR0NIYW5kbGUuQWxsb2MoX2luQnVmZmVyLCBHQ0hhbmRsZVR5cGUuUGlubmVkKTsNCiAgICAgICAgICAgICAgICBfaE91dHB1dCA9IEdDSGFuZGxlLkFsbG9jKF9vdXRCdWZmZXIsIEdDSGFuZGxlVHlwZS5QaW5uZWQpOw0KICAgICAgICAgICAgfQ0KICAgICAgICAgICAgY2F0Y2ggKEV4Y2VwdGlvbikNCiAgICAgICAgICAgIHsNCiAgICAgICAgICAgICAgICBDbGVhblVwKGZhbHNlKTsNCiAgICAgICAgICAgICAgICB0aHJvdzsNCiAgICAgICAgICAgIH0NCiAgICAgICAgfQ0KDQoNCiAgICAgICAgI3JlZ2lvbiBDb2RlYyBNZW1iZXJzDQoNCiAgICAgICAgLy8vIDxzdW1tYXJ5Pg0KICAgICAgICAvLy8gT2NjdXJzIHdoZW4gbW9yZSBwcm9jZXNzZWQgZGF0YSBhcmUgYXZhaWxhYmxlLg0KICAgICAgICAvLy8gPC9zdW1tYXJ5Pg0KICAgICAgICBwdWJsaWMgZXZlbnQgRGF0YUF2YWlsYWJsZUhhbmRsZXIgRGF0YUF2YWlsYWJsZTsNCg0KICAgICAgICAvLy8gPHN1bW1hcnk+DQogICAgICAgIC8vLyBGaXJlcyB0aGUgPHNlZSBjcmVmPSJEYXRhQXZhaWxhYmxlIi8+IGV2ZW50DQogICAgICAgIC8vLyA8L3N1bW1hcnk+DQogICAgICAgIHByb3RlY3RlZCB2b2lkIE9uRGF0YUF2YWlsYWJsZSgpDQogICAgICAgIHsNCiAgICAgICAgICAgIGlmIChfenRyZWFtLnRvdGFsX291dCA+IDApDQogICAgICAgICAgICB7DQogICAgICAgICAgICAgICAgaWYgKERhdGFBdmFpbGFibGUgIT0gbnVsbCkNCiAgICAgICAgICAgICAgICAgICAgRGF0YUF2YWlsYWJsZSggX291dEJ1ZmZlciwgMCwgKGludClfenRyZWFtLnRvdGFsX291dCk7IA0KICAgICAgICAgICAgICAgIHJlc2V0T3V0cHV0KCk7DQogICAgICAgICAgICB9DQogICAgICAgIH0NCg0KICAgICAgICAvLy8gPHN1bW1hcnk+DQogICAgICAgIC8vLyBBZGRzIG1vcmUgZGF0YSB0byB0aGUgY29kZWMgdG8gYmUgcHJvY2Vzc2VkLg0KICAgICAgICAvLy8gPC9zdW1tYXJ5Pg0KICAgICAgICAvLy8gPHBhcmFtIG5hbWU9ImRhdGEiPkJ5dGUgYXJyYXkgY29udGFpbmluZyB0aGUgZGF0YSB0byBiZSBhZGRlZCB0byB0aGUgY29kZWM8L3BhcmFtPg0KICAgICAgICAvLy8gPHJlbWFya3M+QWRkaW5nIGRhdGEgbWF5LCBvciBtYXkgbm90LCByYWlzZSB0aGUgPGM+RGF0YUF2YWlsYWJsZTwvYz4gZXZlbnQ8L3JlbWFya3M+DQogICAgICAgIHB1YmxpYyB2b2lkIEFkZChieXRlW10gZGF0YSkNCiAgICAgICAgew0KICAgICAgICAgICAgQWRkKGRhdGEsMCxkYXRhLkxlbmd0aCk7DQogICAgICAgIH0NCg0KICAgICAgICAvLy8gPHN1bW1hcnk+DQogICAgICAgIC8vLyBBZGRzIG1vcmUgZGF0YSB0byB0aGUgY29kZWMgdG8gYmUgcHJvY2Vzc2VkLg0KICAgICAgICAvLy8gPC9zdW1tYXJ5Pg0KICAgICAgICAvLy8gPHBhcmFtIG5hbWU9ImRhdGEiPkJ5dGUgYXJyYXkgY29udGFpbmluZyB0aGUgZGF0YSB0byBiZSBhZGRlZCB0byB0aGUgY29kZWM8L3BhcmFtPg0KICAgICAgICAvLy8gPHBhcmFtIG5hbWU9Im9mZnNldCI+VGhlIGluZGV4IG9mIHRoZSBmaXJzdCBieXRlIHRvIGFkZCBmcm9tIDxjPmRhdGE8L2M+PC9wYXJhbT4NCiAgICAgICAgLy8vIDxwYXJhbSBuYW1lPSJjb3VudCI+VGhlIG51bWJlciBvZiBieXRlcyB0byBhZGQ8L3BhcmFtPg0KICAgICAgICAvLy8gPHJlbWFya3M+QWRkaW5nIGRhdGEgbWF5LCBvciBtYXkgbm90LCByYWlzZSB0aGUgPGM+RGF0YUF2YWlsYWJsZTwvYz4gZXZlbnQ8L3JlbWFya3M+DQogICAgICAgIC8vLyA8cmVtYXJrcz5UaGlzIG11c3QgYmUgaW1wbGVtZW50ZWQgYnkgYSBkZXJpdmVkIGNsYXNzPC9yZW1hcmtzPg0KICAgICAgICBwdWJsaWMgYWJzdHJhY3Qgdm9pZCBBZGQoYnl0ZVtdIGRhdGEsIGludCBvZmZzZXQsIGludCBjb3VudCk7DQoNCiAgICAgICAgLy8vIDxzdW1tYXJ5Pg0KICAgICAgICAvLy8gRmluaXNoZXMgdXAgYW55IHBlbmRpbmcgZGF0YSB0aGF0IG5lZWRzIHRvIGJlIHByb2Nlc3NlZCBhbmQgaGFuZGxlZC4NCiAgICAgICAgLy8vIDwvc3VtbWFyeT4NCiAgICAgICAgLy8vIDxyZW1hcmtzPlRoaXMgbXVzdCBiZSBpbXBsZW1lbnRlZCBieSBhIGRlcml2ZWQgY2xhc3M8L3JlbWFya3M+DQogICAgICAgIHB1YmxpYyBhYnN0cmFjdCB2b2lkIEZpbmlzaCgpOw0KDQogICAgICAgIC8vLyA8c3VtbWFyeT4NCiAgICAgICAgLy8vIEdldHMgdGhlIGNoZWNrc3VtIG9mIHRoZSBkYXRhIHRoYXQgaGFzIGJlZW4gYWRkZWQgc28gZmFyDQogICAgICAgIC8vLyA8L3N1bW1hcnk+DQogICAgICAgIHB1YmxpYyB1aW50IENoZWNrc3VtIHsgZ2V0IHsgcmV0dXJuIF9jaGVja3N1bTsgfSB9DQoNCiAgICAgICAgI2VuZHJlZ2lvbg0KDQogICAgICAgICNyZWdpb24gRGVzdHJ1Y3RvciAmIElEaXNwb3NhYmxlIHN0dWZmDQoNCiAgICAgICAgLy8vIDxzdW1tYXJ5Pg0KICAgICAgICAvLy8gRGVzdHJveXMgdGhpcyBpbnN0YW5jZQ0KICAgICAgICAvLy8gPC9zdW1tYXJ5Pg0KICAgICAgICB+Q29kZWNCYXNlKCkNCiAgICAgICAgew0KICAgICAgICAgICAgQ2xlYW5VcChmYWxzZSk7DQogICAgICAgIH0NCg0KICAgICAgICAvLy8gPHN1bW1hcnk+DQogICAgICAgIC8vLyBSZWxlYXNlcyBhbnkgdW5tYW5hZ2VkIHJlc291cmNlcyBhbmQgY2FsbHMgdGhlIDxzZWUgY3JlZj0iQ2xlYW5VcCgpIi8+IG1ldGhvZCBvZiB0aGUgZGVyaXZlZCBjbGFzcw0KICAgICAgICAvLy8gPC9zdW1tYXJ5Pg0KICAgICAgICBwdWJsaWMgdm9pZCBEaXNwb3NlKCkNCiAgICAgICAgew0KICAgICAgICAgICAgQ2xlYW5VcCh0cnVlKTsNCiAgICAgICAgfQ0KDQogICAgICAgIC8vLyA8c3VtbWFyeT4NCiAgICAgICAgLy8vIFBlcmZvcm1zIGFueSBjb2RlYyBzcGVjaWZpYyBjbGVhbnVwDQogICAgICAgIC8vLyA8L3N1bW1hcnk+DQogICAgICAgIC8vLyA8cmVtYXJrcz5UaGlzIG11c3QgYmUgaW1wbGVtZW50ZWQgYnkgYSBkZXJpdmVkIGNsYXNzPC9yZW1hcmtzPg0KICAgICAgICBwcm90ZWN0ZWQgYWJzdHJhY3Qgdm9pZCBDbGVhblVwKCk7DQoNCiAgICAgICAgLy8gcGVyZm9ybXMgdGhlIHJlbGVhc2Ugb2YgdGhlIGhhbmRsZXMgYW5kIGNhbGxzIHRoZSBkZXJlaXZlZCBDbGVhblVwKCkNCiAgICAgICAgcHJpdmF0ZSB2b2lkIENsZWFuVXAoYm9vbCBpc0Rpc3Bvc2luZykNCiAgICAgICAgew0KICAgICAgICAgICAgaWYgKCFfaXNEaXNwb3NlZCkNCiAgICAgICAgICAgIHsNCiAgICAgICAgICAgICAgICBDbGVhblVwKCk7DQogICAgICAgICAgICAgICAgaWYgKF9oSW5wdXQuSXNBbGxvY2F0ZWQpDQogICAgICAgICAgICAgICAgICAgIF9oSW5wdXQuRnJlZSgpOw0KICAgICAgICAgICAgICAgIGlmIChfaE91dHB1dC5Jc0FsbG9jYXRlZCkNCiAgICAgICAgICAgICAgICAgICAgX2hPdXRwdXQuRnJlZSgpOw0KDQogICAgICAgICAgICAgICAgX2lzRGlzcG9zZWQgPSB0cnVlOw0KICAgICAgICAgICAgfQ0KICAgICAgICB9DQoNCg0KICAgICAgICAjZW5kcmVnaW9uDQoNCiAgICAgICAgI3JlZ2lvbiBIZWxwZXIgbWV0aG9kcw0KDQogICAgICAgIC8vLyA8c3VtbWFyeT4NCiAgICAgICAgLy8vIENvcGllcyBhIG51bWJlciBvZiBieXRlcyB0byB0aGUgaW50ZXJuYWwgY29kZWMgYnVmZmVyIC0gcmVhZHkgZm9yIHByb2NjZXNpbmcNCiAgICAgICAgLy8vIDwvc3VtbWFyeT4NCiAgICAgICAgLy8vIDxwYXJhbSBuYW1lPSJkYXRhIj5UaGUgYnl0ZSBhcnJheSB0aGF0IGNvbnRhaW5zIHRoZSBkYXRhIHRvIGNvcHk8L3BhcmFtPg0KICAgICAgICAvLy8gPHBhcmFtIG5hbWU9InN0YXJ0SW5kZXgiPlRoZSBpbmRleCBvZiB0aGUgZmlyc3QgYnl0ZSB0byBjb3B5PC9wYXJhbT4NCiAgICAgICAgLy8vIDxwYXJhbSBuYW1lPSJjb3VudCI+VGhlIG51bWJlciBvZiBieXRlcyB0byBjb3B5IGZyb20gPGM+ZGF0YTwvYz48L3BhcmFtPg0KICAgICAgICBwcm90ZWN0ZWQgdm9pZCBjb3B5SW5wdXQoYnl0ZVtdIGRhdGEsIGludCBzdGFydEluZGV4LCBpbnQgY291bnQpDQogICAgICAgIHsNCiAgICAgICAgICAgIEFycmF5LkNvcHkoZGF0YSwgc3RhcnRJbmRleCwgX2luQnVmZmVyLDAsIGNvdW50KTsNCiAgICAgICAgICAgIF96dHJlYW0ubmV4dF9pbiA9IF9oSW5wdXQuQWRkck9mUGlubmVkT2JqZWN0KCk7DQogICAgICAgICAgICBfenRyZWFtLnRvdGFsX2luID0gMDsNCiAgICAgICAgICAgIF96dHJlYW0uYXZhaWxfaW4gPSAodWludCljb3VudDsNCg0KICAgICAgICB9DQoNCiAgICAgICAgLy8vIDxzdW1tYXJ5Pg0KICAgICAgICAvLy8gUmVzZXRzIHRoZSBpbnRlcm5hbCBvdXRwdXQgYnVmZmVycyB0byBhIGtub3duIHN0YXRlIC0gcmVhZHkgZm9yIHByb2Nlc3NpbmcNCiAgICAgICAgLy8vIDwvc3VtbWFyeT4NCiAgICAgICAgcHJvdGVjdGVkIHZvaWQgcmVzZXRPdXRwdXQoKQ0KICAgICAgICB7DQogICAgICAgICAgICBfenRyZWFtLnRvdGFsX291dCA9IDA7DQogICAgICAgICAgICBfenRyZWFtLmF2YWlsX291dCA9IGtCdWZmZXJTaXplOw0KICAgICAgICAgICAgX3p0cmVhbS5uZXh0X291dCA9IF9oT3V0cHV0LkFkZHJPZlBpbm5lZE9iamVjdCgpOw0KICAgICAgICB9DQoNCiAgICAgICAgLy8vIDxzdW1tYXJ5Pg0KICAgICAgICAvLy8gVXBkYXRlcyB0aGUgcnVubmluZyBjaGVja3N1bSBwcm9wZXJ0eQ0KICAgICAgICAvLy8gPC9zdW1tYXJ5Pg0KICAgICAgICAvLy8gPHBhcmFtIG5hbWU9Im5ld1N1bSI+VGhlIG5ldyBjaGVja3N1bSB2YWx1ZTwvcGFyYW0+DQogICAgICAgIHByb3RlY3RlZCB2b2lkIHNldENoZWNrc3VtKHVpbnQgbmV3U3VtKQ0KICAgICAgICB7DQogICAgICAgICAgICBfY2hlY2tzdW0gPSBuZXdTdW07DQogICAgICAgIH0NCiAgICAgICAgI2VuZHJlZ2lvbg0KDQogICAgfQ0KfQ0K