LyoKICogTGljZW5zZWQgdG8gdGhlIEFwYWNoZSBTb2Z0d2FyZSBGb3VuZGF0aW9uIChBU0YpIHVuZGVyIG9uZSBvciBtb3JlCiAqIGNvbnRyaWJ1dG9yIGxpY2Vuc2UgYWdyZWVtZW50cy4gIFNlZSB0aGUgTk9USUNFIGZpbGUgZGlzdHJpYnV0ZWQgd2l0aAogKiB0aGlzIHdvcmsgZm9yIGFkZGl0aW9uYWwgaW5mb3JtYXRpb24gcmVnYXJkaW5nIGNvcHlyaWdodCBvd25lcnNoaXAuCiAqIFRoZSBBU0YgbGljZW5zZXMgdGhpcyBmaWxlIHRvIFlvdSB1bmRlciB0aGUgQXBhY2hlIExpY2Vuc2UsIFZlcnNpb24gMi4wCiAqICh0aGUgIkxpY2Vuc2UiKTsgeW91IG1heSBub3QgdXNlIHRoaXMgZmlsZSBleGNlcHQgaW4gY29tcGxpYW5jZSB3aXRoCiAqIHRoZSBMaWNlbnNlLiAgWW91IG1heSBvYnRhaW4gYSBjb3B5IG9mIHRoZSBMaWNlbnNlIGF0CiAqIAogKiAgICAgIGh0dHA6Ly93d3cuYXBhY2hlLm9yZy9saWNlbnNlcy9MSUNFTlNFLTIuMAogKiAKICogVW5sZXNzIHJlcXVpcmVkIGJ5IGFwcGxpY2FibGUgbGF3IG9yIGFncmVlZCB0byBpbiB3cml0aW5nLCBzb2Z0d2FyZQogKiBkaXN0cmlidXRlZCB1bmRlciB0aGUgTGljZW5zZSBpcyBkaXN0cmlidXRlZCBvbiBhbiAiQVMgSVMiIEJBU0lTLAogKiBXSVRIT1VUIFdBUlJBTlRJRVMgT1IgQ09ORElUSU9OUyBPRiBBTlkgS0lORCwgZWl0aGVyIGV4cHJlc3Mgb3IgaW1wbGllZC4KICogU2VlIHRoZSBMaWNlbnNlIGZvciB0aGUgc3BlY2lmaWMgbGFuZ3VhZ2UgZ292ZXJuaW5nIHBlcm1pc3Npb25zIGFuZAogKiBsaW1pdGF0aW9ucyB1bmRlciB0aGUgTGljZW5zZS4KICovCgovKgogKiAkSWQ6IExpc3REYXRhdHlwZVZhbGlkYXRvci5jcHAgNTY4MDc4IDIwMDctMDgtMjEgMTE6NDM6MjVaIGFtYXNzYXJpICQKICovCgovLyAtLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0KLy8gIEluY2x1ZGVzCi8vIC0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLQojaW5jbHVkZSA8eGVyY2VzYy92YWxpZGF0b3JzL2RhdGF0eXBlL0xpc3REYXRhdHlwZVZhbGlkYXRvci5ocHA+CiNpbmNsdWRlIDx4ZXJjZXNjL3ZhbGlkYXRvcnMvZGF0YXR5cGUvSW52YWxpZERhdGF0eXBlRmFjZXRFeGNlcHRpb24uaHBwPgojaW5jbHVkZSA8eGVyY2VzYy92YWxpZGF0b3JzL2RhdGF0eXBlL0ludmFsaWREYXRhdHlwZVZhbHVlRXhjZXB0aW9uLmhwcD4KI2luY2x1ZGUgPHhlcmNlc2MvdXRpbC9PdXRPZk1lbW9yeUV4Y2VwdGlvbi5ocHA+CgpYRVJDRVNfQ1BQX05BTUVTUEFDRV9CRUdJTgoKc3RhdGljIGNvbnN0IGludCBCVUZfTEVOID0gNjQ7CgovLyAtLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0KLy8gIENvbnN0cnVjdG9ycyBhbmQgRGVzdHJ1Y3RvcgovLyAtLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0KTGlzdERhdGF0eXBlVmFsaWRhdG9yOjpMaXN0RGF0YXR5cGVWYWxpZGF0b3IoTWVtb3J5TWFuYWdlciogY29uc3QgbWFuYWdlcikKOkFic3RyYWN0U3RyaW5nVmFsaWRhdG9yKDAsIDAsIDAsIERhdGF0eXBlVmFsaWRhdG9yOjpMaXN0LCBtYW5hZ2VyKQosZkNvbnRlbnQoMCkKe30KCkxpc3REYXRhdHlwZVZhbGlkYXRvcjo6TGlzdERhdGF0eXBlVmFsaWRhdG9yKAogICAgICAgICAgICAgICAgICAgICAgICAgIERhdGF0eXBlVmFsaWRhdG9yKiAgICAgICAgICAgIGNvbnN0IGJhc2VWYWxpZGF0b3IKICAgICAgICAgICAgICAgICAgICAgICAgLCBSZWZIYXNoVGFibGVPZjxLVlN0cmluZ1BhaXI+KiBjb25zdCBmYWNldHMKICAgICAgICAgICAgICAgICAgICAgICAgLCBSZWZBcnJheVZlY3Rvck9mPFhNTENoPiogICAgICAgICAgIGNvbnN0IGVudW1zCiAgICAgICAgICAgICAgICAgICAgICAgICwgY29uc3QgaW50ICAgICAgICAgICAgICAgICAgICAgICAgICAgZmluYWxTZXQKICAgICAgICAgICAgICAgICAgICAgICAgLCBNZW1vcnlNYW5hZ2VyKiBjb25zdCBtYW5hZ2VyKQo6QWJzdHJhY3RTdHJpbmdWYWxpZGF0b3IoYmFzZVZhbGlkYXRvciwgZmFjZXRzLCBmaW5hbFNldCwgRGF0YXR5cGVWYWxpZGF0b3I6Okxpc3QsIG1hbmFnZXIpCixmQ29udGVudCgwKQp7CiAgICAvLwogICAgLy8gYmFzZVZhbGlkYXRvciBzaGFsbCBlaXRoZXIKICAgIC8vIGFuIGF0b21pYyBEVFYgd2hpY2ggc2VydmVycyBhcyBpdGVtVHlwZSwgb3IKICAgIC8vIGFub3RoZXIgTGlzdERUViBmcm9tIHdoaWNoLCB0aGlzIExpc3REVFYgaXMgZGVyaXZlZCBieSByZXN0cmljdGlvbi4KICAgIC8vCiAgICAvLyBJbiBlaXRoZXIgY2FzZSwgaXQgc2hhbGwgYmUgbm90IG51bGwKICAgIC8vCiAgICBpZiAoIWJhc2VWYWxpZGF0b3IpCiAgICAgICAgVGhyb3dYTUx3aXRoTWVtTWdyKEludmFsaWREYXRhdHlwZUZhY2V0RXhjZXB0aW9uLCBYTUxFeGNlcHRzOjpGQUNFVF9MaXN0X051bGxfYmFzZVZhbGlkYXRvciwgbWFuYWdlcik7CgogICAgaW5pdChlbnVtcywgbWFuYWdlcik7Cn0KCkxpc3REYXRhdHlwZVZhbGlkYXRvcjo6fkxpc3REYXRhdHlwZVZhbGlkYXRvcigpCnt9CgpEYXRhdHlwZVZhbGlkYXRvciogTGlzdERhdGF0eXBlVmFsaWRhdG9yOjpuZXdJbnN0YW5jZQooCiAgICAgIFJlZkhhc2hUYWJsZU9mPEtWU3RyaW5nUGFpcj4qIGNvbnN0IGZhY2V0cwogICAgLCBSZWZBcnJheVZlY3Rvck9mPFhNTENoPiogY29uc3QgICAgICBlbnVtcwogICAgLCBjb25zdCBpbnQgICAgICAgICAgICAgICAgICAgICAgICAgICBmaW5hbFNldAogICAgLCBNZW1vcnlNYW5hZ2VyKiBjb25zdCAgICAgICAgICAgICAgICBtYW5hZ2VyCikKewogICAgcmV0dXJuIChEYXRhdHlwZVZhbGlkYXRvciopIG5ldyAobWFuYWdlcikgTGlzdERhdGF0eXBlVmFsaWRhdG9yKHRoaXMsIGZhY2V0cywgZW51bXMsIGZpbmFsU2V0LCBtYW5hZ2VyKTsKfQoKCmludCBMaXN0RGF0YXR5cGVWYWxpZGF0b3I6OmNvbXBhcmUoY29uc3QgWE1MQ2gqICAgICBjb25zdCBsVmFsdWUKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgLCBjb25zdCBYTUxDaCogICAgIGNvbnN0IHJWYWx1ZQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAsIE1lbW9yeU1hbmFnZXIqICAgY29uc3QgbWFuYWdlcikKewogICAgRGF0YXR5cGVWYWxpZGF0b3IqIHRoZUl0ZW1UeXBlRFRWID0gZ2V0SXRlbVR5cGVEVFYoKTsKICAgIEJhc2VSZWZWZWN0b3JPZjxYTUxDaD4qIGxWZWN0b3IgPSBYTUxTdHJpbmc6OnRva2VuaXplU3RyaW5nKGxWYWx1ZSwgbWFuYWdlcik7CiAgICBKYW5pdG9yPEJhc2VSZWZWZWN0b3JPZjxYTUxDaD4gPiBqYW5sKGxWZWN0b3IpOwogICAgQmFzZVJlZlZlY3Rvck9mPFhNTENoPiogclZlY3RvciA9IFhNTFN0cmluZzo6dG9rZW5pemVTdHJpbmcoclZhbHVlLCBtYW5hZ2VyKTsKICAgIEphbml0b3I8QmFzZVJlZlZlY3Rvck9mPFhNTENoPiA+IGphbnIoclZlY3Rvcik7CgogICAgaW50IGxOdW1iZXJPZlRva2VucyA9IGxWZWN0b3ItPnNpemUoKTsKICAgIGludCByTnVtYmVyT2ZUb2tlbnMgPSByVmVjdG9yLT5zaXplKCk7CgogICAgaWYgKGxOdW1iZXJPZlRva2VucyA8IHJOdW1iZXJPZlRva2VucykKICAgICAgICByZXR1cm4gLTE7CiAgICBlbHNlIGlmIChsTnVtYmVyT2ZUb2tlbnMgPiByTnVtYmVyT2ZUb2tlbnMpCiAgICAgICAgcmV0dXJuIDE7CiAgICBlbHNlCiAgICB7IC8vY29tcGFyZSBlYWNoIHRva2VuCiAgICAgICAgZm9yICggaW50IGkgPSAwOyBpIDwgbE51bWJlck9mVG9rZW5zOyBpKyspCiAgICAgICAgewogICAgICAgICAgICBpbnQgcmV0dXJuVmFsdWUgPSB0aGVJdGVtVHlwZURUVi0+Y29tcGFyZShsVmVjdG9yLT5lbGVtZW50QXQoaSksIHJWZWN0b3ItPmVsZW1lbnRBdChpKSwgbWFuYWdlcik7CiAgICAgICAgICAgIGlmIChyZXR1cm5WYWx1ZSAhPSAwKQogICAgICAgICAgICAgICAgcmV0dXJuIHJldHVyblZhbHVlOyAvL1JFVklTSVQ6IGRvZXMgaXQgbWFrZSBzZW5zZSB0byByZXR1cm4gLTEgb3IgKzEuLj8KICAgICAgICB9CiAgICAgICAgcmV0dXJuIDA7CiAgICB9Cgp9Cgp2b2lkIExpc3REYXRhdHlwZVZhbGlkYXRvcjo6dmFsaWRhdGUoIGNvbnN0IFhNTENoKiAgICAgICAgICAgICBjb25zdCBjb250ZW50CiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICwgICAgICAgVmFsaWRhdGlvbkNvbnRleHQqIGNvbnN0IGNvbnRleHQKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgLCAgICAgICBNZW1vcnlNYW5hZ2VyKiAgICAgY29uc3QgbWFuYWdlcikKewogICAgc2V0Q29udGVudChjb250ZW50KTsKICAgIEJhc2VSZWZWZWN0b3JPZjxYTUxDaD4qIHRva2VuVmVjdG9yID0gWE1MU3RyaW5nOjp0b2tlbml6ZVN0cmluZyhjb250ZW50LCBtYW5hZ2VyKTsKICAgIEphbml0b3I8QmFzZVJlZlZlY3Rvck9mPFhNTENoPiA+IGphbk5hbWUodG9rZW5WZWN0b3IpOwogICAgY2hlY2tDb250ZW50KHRva2VuVmVjdG9yLCBjb250ZW50LCBjb250ZXh0LCBmYWxzZSwgbWFuYWdlcik7Cn0KCnZvaWQgTGlzdERhdGF0eXBlVmFsaWRhdG9yOjpjaGVja0NvbnRlbnQoIGNvbnN0IFhNTENoKiAgICAgICAgICAgICBjb25zdCBjb250ZW50CiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgLCAgICAgIFZhbGlkYXRpb25Db250ZXh0KiBjb25zdCBjb250ZXh0CiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgLCAgICAgIGJvb2wgICAgICAgICAgICAgICAgICAgICBhc0Jhc2UKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAsICAgICAgTWVtb3J5TWFuYWdlciogICAgIGNvbnN0IG1hbmFnZXIpCnsKICAgIHNldENvbnRlbnQoY29udGVudCk7CiAgICBCYXNlUmVmVmVjdG9yT2Y8WE1MQ2g+KiB0b2tlblZlY3RvciA9IFhNTFN0cmluZzo6dG9rZW5pemVTdHJpbmcoY29udGVudCwgbWFuYWdlcik7CiAgICBKYW5pdG9yPEJhc2VSZWZWZWN0b3JPZjxYTUxDaD4gPiBqYW5OYW1lKHRva2VuVmVjdG9yKTsKICAgIGNoZWNrQ29udGVudCh0b2tlblZlY3RvciwgY29udGVudCwgY29udGV4dCwgYXNCYXNlLCBtYW5hZ2VyKTsKfQoKLy8KLy8gaGVyZSBjb250ZW50IGlzIGEgbGlzdCBvZiBpdGVtcwovLwp2b2lkIExpc3REYXRhdHlwZVZhbGlkYXRvcjo6Y2hlY2tDb250ZW50KCAgICAgICBCYXNlUmVmVmVjdG9yT2Y8WE1MQ2g+KiAgICAgICB0b2tlblZlY3RvcgogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgLCBjb25zdCBYTUxDaCogICAgICAgICAgICAgICAgICBjb25zdCBjb250ZW50CiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAsICAgICAgIFZhbGlkYXRpb25Db250ZXh0KiAgICAgIGNvbnN0IGNvbnRleHQKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICwgICAgICAgYm9vbCAgICAgICAgICAgICAgICAgICAgICAgICAgYXNCYXNlCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAsICAgICAgIE1lbW9yeU1hbmFnZXIqICAgICAgICAgIGNvbnN0IG1hbmFnZXIpCnsKICAgIERhdGF0eXBlVmFsaWRhdG9yKiBidiA9IGdldEJhc2VWYWxpZGF0b3IoKTsKCiAgICBpZiAoYnYtPmdldFR5cGUoKSA9PSBEYXRhdHlwZVZhbGlkYXRvcjo6TGlzdCkKICAgICAgICAoKExpc3REYXRhdHlwZVZhbGlkYXRvciopYnYpLT5jaGVja0NvbnRlbnQodG9rZW5WZWN0b3IsIGNvbnRlbnQsIGNvbnRleHQsIHRydWUsIG1hbmFnZXIpOwogICAgZWxzZQogICAgeyAgIC8vIHRoZSB1bHRpbWF0ZSBpdGVtVHlwZSBEVFYKICAgICAgICBmb3IgKHVuc2lnbmVkIGludCBpID0gMDsgaSA8IHRva2VuVmVjdG9yLT5zaXplKCk7IGkrKykKICAgICAgICAgICAgYnYtPnZhbGlkYXRlKHRva2VuVmVjdG9yLT5lbGVtZW50QXQoaSksIGNvbnRleHQsIG1hbmFnZXIpOwogICAgfQoKICAgIGludCB0aGlzRmFjZXRzRGVmaW5lZCA9IGdldEZhY2V0c0RlZmluZWQoKTsKCiAgICAvLyB3ZSBjaGVjayBwYXR0ZXJuIGZpcnN0CiAgICBpZiAoICh0aGlzRmFjZXRzRGVmaW5lZCAmIERhdGF0eXBlVmFsaWRhdG9yOjpGQUNFVF9QQVRURVJOICkgIT0gMCApCiAgICB7CiAgICAgICAgLy9jaGVjayBldmVyeSBpdGVtIGluIHRoZSBsaXN0IGFzIGEgd2hvbGUKICAgICAgICBpZiAoZ2V0UmVnZXgoKS0+bWF0Y2hlcyhjb250ZW50LCBtYW5hZ2VyKSA9PSBmYWxzZSkKICAgICAgICB7CiAgICAgICAgICAgIFRocm93WE1Md2l0aE1lbU1ncjIoSW52YWxpZERhdGF0eXBlVmFsdWVFeGNlcHRpb24KICAgICAgICAgICAgICAgICAgICAsIFhNTEV4Y2VwdHM6OlZBTFVFX05vdE1hdGNoX1BhdHRlcm4KICAgICAgICAgICAgICAgICAgICAsIGNvbnRlbnQKICAgICAgICAgICAgICAgICAgICAsIGdldFBhdHRlcm4oKQogICAgICAgICAgICAgICAgICAgICwgbWFuYWdlcik7CiAgICAgICAgfQoKICAgIH0KCiAgICAvLyBpZiB0aGlzIGlzIGEgYmFzZSB2YWxpZGF0b3IsIHdlIG9ubHkgbmVlZCB0byBjaGVjayBwYXR0ZXJuIGZhY2V0CiAgICAvLyBhbGwgb3RoZXIgZmFjZXQgd2VyZSBpbmhlcml0ZWQgYnkgdGhlIGRlcml2ZWQgdHlwZQogICAgaWYgKGFzQmFzZSkKICAgICAgICByZXR1cm47CgogICAgdW5zaWduZWQgaW50IHRva2VuTnVtYmVyID0gdG9rZW5WZWN0b3ItPnNpemUoKTsKCiAgICBpZiAoKCh0aGlzRmFjZXRzRGVmaW5lZCAmIERhdGF0eXBlVmFsaWRhdG9yOjpGQUNFVF9NQVhMRU5HVEgpICE9IDApICYmCiAgICAgICAgKHRva2VuTnVtYmVyID4gZ2V0TWF4TGVuZ3RoKCkpKQogICAgewogICAgICAgIFhNTENoIHZhbHVlMVtCVUZfTEVOKzFdOwogICAgICAgIFhNTENoIHZhbHVlMltCVUZfTEVOKzFdOwogICAgICAgIFhNTFN0cmluZzo6YmluVG9UZXh0KHRva2VuTnVtYmVyLCB2YWx1ZTEsIEJVRl9MRU4sIDEwLCBtYW5hZ2VyKTsKICAgICAgICBYTUxTdHJpbmc6OmJpblRvVGV4dChnZXRNYXhMZW5ndGgoKSwgdmFsdWUyLCBCVUZfTEVOLCAxMCwgbWFuYWdlcik7CgogICAgICAgIFRocm93WE1Md2l0aE1lbU1ncjMoSW52YWxpZERhdGF0eXBlVmFsdWVFeGNlcHRpb24KICAgICAgICAgICAgICAgICwgWE1MRXhjZXB0czo6VkFMVUVfR1RfbWF4TGVuCiAgICAgICAgICAgICAgICAsIGdldENvbnRlbnQoKQogICAgICAgICAgICAgICAgLCB2YWx1ZTEKICAgICAgICAgICAgICAgICwgdmFsdWUyCiAgICAgICAgICAgICAgICAsIG1hbmFnZXIpOwogICAgfQoKICAgIGlmICgoKHRoaXNGYWNldHNEZWZpbmVkICYgRGF0YXR5cGVWYWxpZGF0b3I6OkZBQ0VUX01JTkxFTkdUSCkgIT0gMCkgJiYKICAgICAgICAodG9rZW5OdW1iZXIgPCBnZXRNaW5MZW5ndGgoKSkpCiAgICB7CiAgICAgICAgWE1MQ2ggdmFsdWUxW0JVRl9MRU4rMV07CiAgICAgICAgWE1MQ2ggdmFsdWUyW0JVRl9MRU4rMV07CiAgICAgICAgWE1MU3RyaW5nOjpiaW5Ub1RleHQodG9rZW5OdW1iZXIsIHZhbHVlMSwgQlVGX0xFTiwgMTAsIG1hbmFnZXIpOwogICAgICAgIFhNTFN0cmluZzo6YmluVG9UZXh0KGdldE1pbkxlbmd0aCgpLCB2YWx1ZTIsIEJVRl9MRU4sIDEwLCBtYW5hZ2VyKTsKCiAgICAgICAgVGhyb3dYTUx3aXRoTWVtTWdyMyhJbnZhbGlkRGF0YXR5cGVWYWx1ZUV4Y2VwdGlvbgogICAgICAgICAgICAgICAgLCBYTUxFeGNlcHRzOjpWQUxVRV9MVF9taW5MZW4KICAgICAgICAgICAgICAgICwgZ2V0Q29udGVudCgpCiAgICAgICAgICAgICAgICAsIHZhbHVlMQogICAgICAgICAgICAgICAgLCB2YWx1ZTIKICAgICAgICAgICAgICAgICwgbWFuYWdlcik7CiAgICB9CgogICAgaWYgKCgodGhpc0ZhY2V0c0RlZmluZWQgJiBEYXRhdHlwZVZhbGlkYXRvcjo6RkFDRVRfTEVOR1RIKSAhPSAwKSAmJgogICAgICAgICh0b2tlbk51bWJlciAhPSBBYnN0cmFjdFN0cmluZ1ZhbGlkYXRvcjo6Z2V0TGVuZ3RoKCkpKQogICAgewogICAgICAgIFhNTENoIHZhbHVlMVtCVUZfTEVOKzFdOwogICAgICAgIFhNTENoIHZhbHVlMltCVUZfTEVOKzFdOwogICAgICAgIFhNTFN0cmluZzo6YmluVG9UZXh0KHRva2VuTnVtYmVyLCB2YWx1ZTEsIEJVRl9MRU4sIDEwLCBtYW5hZ2VyKTsKICAgICAgICBYTUxTdHJpbmc6OmJpblRvVGV4dChBYnN0cmFjdFN0cmluZ1ZhbGlkYXRvcjo6Z2V0TGVuZ3RoKCksIHZhbHVlMiwgQlVGX0xFTiwgMTAsIG1hbmFnZXIpOwoKICAgICAgICBUaHJvd1hNTHdpdGhNZW1NZ3IzKEludmFsaWREYXRhdHlwZVZhbHVlRXhjZXB0aW9uCiAgICAgICAgICAgICAgICAsIFhNTEV4Y2VwdHM6OlZBTFVFX05FX0xlbgogICAgICAgICAgICAgICAgLCBnZXRDb250ZW50KCkKICAgICAgICAgICAgICAgICwgdmFsdWUxCiAgICAgICAgICAgICAgICAsIHZhbHVlMgogICAgICAgICAgICAgICAgLCBtYW5hZ2VyKTsKICAgIH0KCiAgICBpZiAoKHRoaXNGYWNldHNEZWZpbmVkICYgRGF0YXR5cGVWYWxpZGF0b3I6OkZBQ0VUX0VOVU1FUkFUSU9OKSAhPSAwICYmCiAgICAgICAgKGdldEVudW1lcmF0aW9uKCkgIT0gMCkpCiAgICB7CiAgICAgICAgaW50IGk7CiAgICAgICAgaW50IGVudW1MZW5ndGggPSBnZXRFbnVtZXJhdGlvbigpLT5zaXplKCk7CgogICAgICAgIGZvciAoIGkgPSAwOyBpIDwgZW51bUxlbmd0aDsgaSsrKQogICAgICAgIHsKICAgICAgICAgICAgLy9vcHRpbWl6YXRpb246IHdlIGRvIGEgbGV4aWNhbCBjb21wYXJpc2lvbiBmaXJzdAogICAgICAgICAgICAvLyB0aGlzIG1heSBiZSBmYXN0ZXIgZm9yIHN0cmluZyBhbmQgaXRzIGRlcml2ZWQKICAgICAgICAgICAgaWYgKFhNTFN0cmluZzo6ZXF1YWxzKGdldEVudW1lcmF0aW9uKCktPmVsZW1lbnRBdChpKSwgZ2V0Q29udGVudCgpKSkKICAgICAgICAgICAgICAgIGJyZWFrOyAvLyBhIG1hdGNoIGZvdW5kCgogICAgICAgICAgICAvLyBkbyBhIHZhbHVlIHNwYWNlIGNoZWNrCiAgICAgICAgICAgIC8vIHRoaXMgaXMgbmVlZGVkIGZvciBkZWNpbWFsIChhbmQgcHJvYmFibHkgb3RoZXIgdHlwZXMKICAgICAgICAgICAgLy8gc3VjaCBhcyBkYXRldGltZSByZWxhdGVkKQogICAgICAgICAgICAvLyBlZy4KICAgICAgICAgICAgLy8gdG9rZW5WZWN0b3IgPSAiMSAyIDMuMCA0IiB2cyBlbnVtZXJhdGlvbiA9ICIxIDIgMyA0LjAiCiAgICAgICAgICAgIC8vCiAgICAgICAgICAgIGlmICh2YWx1ZVNwYWNlQ2hlY2sodG9rZW5WZWN0b3IsIGdldEVudW1lcmF0aW9uKCktPmVsZW1lbnRBdChpKSwgbWFuYWdlcikpCiAgICAgICAgICAgICAgICBicmVhazsKICAgICAgICB9CgogICAgICAgIGlmIChpID09IGVudW1MZW5ndGgpCiAgICAgICAgICAgIFRocm93WE1Md2l0aE1lbU1ncjEoSW52YWxpZERhdGF0eXBlVmFsdWVFeGNlcHRpb24sIFhNTEV4Y2VwdHM6OlZBTFVFX05vdEluX0VudW1lcmF0aW9uLCBnZXRDb250ZW50KCksIG1hbmFnZXIpOwoKICAgIH0gLy8gZW51bWVyYXRpb24KCn0KCmJvb2wgTGlzdERhdGF0eXBlVmFsaWRhdG9yOjp2YWx1ZVNwYWNlQ2hlY2soQmFzZVJlZlZlY3Rvck9mPFhNTENoPiogdG9rZW5WZWN0b3IKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgLCBjb25zdCBYTUxDaCogICAgY29uc3QgIGVudW1TdHIKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgLCBNZW1vcnlNYW5hZ2VyKiAgY29uc3QgIG1hbmFnZXIpIGNvbnN0CnsKICAgIERhdGF0eXBlVmFsaWRhdG9yKiB0aGVJdGVtVHlwZURUViA9IGdldEl0ZW1UeXBlRFRWKCk7CiAgICBCYXNlUmVmVmVjdG9yT2Y8WE1MQ2g+KiBlbnVtVmVjdG9yID0gWE1MU3RyaW5nOjp0b2tlbml6ZVN0cmluZyhlbnVtU3RyLCBtYW5hZ2VyKTsKICAgIEphbml0b3I8QmFzZVJlZlZlY3Rvck9mPFhNTENoPiA+IGphbk5hbWUoZW51bVZlY3Rvcik7CgogICAgaWYgKHRva2VuVmVjdG9yLT5zaXplKCkgIT0gZW51bVZlY3Rvci0+c2l6ZSgpKQogICAgICAgIHJldHVybiBmYWxzZTsKCiAgICBmb3IgKCB1bnNpZ25lZCBpbnQgaiA9IDA7IGogPCB0b2tlblZlY3Rvci0+c2l6ZSgpOyBqKysgKQogICAgewogICAgICAgIGlmICh0aGVJdGVtVHlwZURUVi0+Y29tcGFyZSh0b2tlblZlY3Rvci0+ZWxlbWVudEF0KGopLCBlbnVtVmVjdG9yLT5lbGVtZW50QXQoaiksIG1hbmFnZXIpICE9IDApCiAgICAgICAgICAgIHJldHVybiBmYWxzZTsKICAgIH0KCiAgICByZXR1cm4gdHJ1ZTsKfQoKRGF0YXR5cGVWYWxpZGF0b3IqIExpc3REYXRhdHlwZVZhbGlkYXRvcjo6Z2V0SXRlbVR5cGVEVFYoKSBjb25zdAp7CiAgICBEYXRhdHlwZVZhbGlkYXRvciogYmR2ID0gdGhpcy0+Z2V0QmFzZVZhbGlkYXRvcigpOwoKICAgIHdoaWxlIChiZHYtPmdldFR5cGUoKSA9PSBEYXRhdHlwZVZhbGlkYXRvcjo6TGlzdCkKICAgICAgICBiZHYgPSBiZHYtPmdldEJhc2VWYWxpZGF0b3IoKTsKCiAgICByZXR1cm4gYmR2Owp9CgovLyAtLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0KLy8gIFV0aWxpdGllcwovLyAtLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0KCnZvaWQgTGlzdERhdGF0eXBlVmFsaWRhdG9yOjpjaGVja1ZhbHVlU3BhY2UoY29uc3QgWE1MQ2gqIGNvbnN0CiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgLCBNZW1vcnlNYW5hZ2VyKiBjb25zdCkKe30KCmludCBMaXN0RGF0YXR5cGVWYWxpZGF0b3I6OmdldExlbmd0aChjb25zdCBYTUxDaCogY29uc3QgY29udGVudAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgLCBNZW1vcnlNYW5hZ2VyKiBjb25zdCBtYW5hZ2VyKSBjb25zdAp7CiAgICBCYXNlUmVmVmVjdG9yT2Y8WE1MQ2g+KiB0b2tlblZlY3RvciA9IFhNTFN0cmluZzo6dG9rZW5pemVTdHJpbmcoY29udGVudCwgbWFuYWdlcik7CiAgICBKYW5pdG9yPEJhc2VSZWZWZWN0b3JPZjxYTUxDaD4gPiBqYW5OYW1lKHRva2VuVmVjdG9yKTsKCiAgICByZXR1cm4gdG9rZW5WZWN0b3ItPnNpemUoKTsKfQoKdm9pZCBMaXN0RGF0YXR5cGVWYWxpZGF0b3I6Omluc3BlY3RGYWNldEJhc2UoTWVtb3J5TWFuYWdlciogY29uc3QgbWFuYWdlcikKewoKICAgIC8vCiAgICAvLyB3ZSBhcmUgcHJldHR5IHN1cmUgYmFzZVZhbGlkYXRvciBpcyBub3QgbnVsbAogICAgLy8KCiAgICBpZiAoZ2V0QmFzZVZhbGlkYXRvcigpLT5nZXRUeXBlKCkgPT0gRGF0YXR5cGVWYWxpZGF0b3I6Okxpc3QpCiAgICB7CiAgICAgICAgQWJzdHJhY3RTdHJpbmdWYWxpZGF0b3I6Omluc3BlY3RGYWNldEJhc2UobWFuYWdlcik7CiAgICB9CiAgICBlbHNlCiAgICB7CiAgICAgICAgLy8gdGhlIGZpcnN0IGxldmVsIExpc3REVFYKICAgICAgICAvLyBjaGVjayA0LjMuNS5jMCBtdXN0OiBlbnVtZXJhdGlvbiB2YWx1ZXMgZnJvbSB0aGUgdmFsdWUgc3BhY2Ugb2YgYmFzZQogICAgICAgIGlmICggKChnZXRGYWNldHNEZWZpbmVkKCkgJiBEYXRhdHlwZVZhbGlkYXRvcjo6RkFDRVRfRU5VTUVSQVRJT04pICE9IDApICYmCiAgICAgICAgICAgICAoZ2V0RW51bWVyYXRpb24oKSAhPTApICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICkKICAgICAgICB7CiAgICAgICAgICAgIGludCBpOwogICAgICAgICAgICBpbnQgZW51bUxlbmd0aCA9IGdldEVudW1lcmF0aW9uKCktPnNpemUoKTsKICAgICAgICAgICAgdHJ5CiAgICAgICAgICAgIHsKICAgICAgICAgICAgICAgIGZvciAoIGkgPSAwOyBpIDwgZW51bUxlbmd0aDsgaSsrKQogICAgICAgICAgICAgICAgewogICAgICAgICAgICAgICAgICAgIC8vIGFzayB0aGUgaXRlbVR5cGUgZm9yIGEgY29tcGxldGUgY2hlY2sKICAgICAgICAgICAgICAgICAgICBCYXNlUmVmVmVjdG9yT2Y8WE1MQ2g+KiB0ZW1wTGlzdCA9IFhNTFN0cmluZzo6dG9rZW5pemVTdHJpbmcoZ2V0RW51bWVyYXRpb24oKS0+ZWxlbWVudEF0KGkpLCBtYW5hZ2VyKTsKICAgICAgICAgICAgICAgICAgICBKYW5pdG9yPEJhc2VSZWZWZWN0b3JPZjxYTUxDaD4gPiAgICBqYW4odGVtcExpc3QpOwogICAgICAgICAgICAgICAgICAgIGludCB0b2tlbk51bWJlciA9IHRlbXBMaXN0LT5zaXplKCk7CgogICAgICAgICAgICAgICAgICAgIHRyeQogICAgICAgICAgICAgICAgICAgIHsKICAgICAgICAgICAgICAgICAgICAgICAgZm9yICggaW50IGogPSAwOyBqIDwgdG9rZW5OdW1iZXI7IGorKykKICAgICAgICAgICAgICAgICAgICAgICAgICAgIGdldEJhc2VWYWxpZGF0b3IoKS0+dmFsaWRhdGUodGVtcExpc3QtPmVsZW1lbnRBdChqKSwgKFZhbGlkYXRpb25Db250ZXh0KikwLCBtYW5hZ2VyKTsKICAgICAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICAgICAgY2F0Y2goY29uc3QgT3V0T2ZNZW1vcnlFeGNlcHRpb24mKQogICAgICAgICAgICAgICAgICAgIHsKICAgICAgICAgICAgICAgICAgICAgICAgamFuLnJlbGVhc2UoKTsKCiAgICAgICAgICAgICAgICAgICAgICAgIHRocm93OwogICAgICAgICAgICAgICAgICAgIH0KI2lmIDAKLy8gc3BlYyBzYXlzIHRoYXQgb25seSBiYXNlIGhhcyB0byBjaGVja0NvbnRlbnQgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgIC8vIGVudW0gc2hhbGwgcGFzcyB0aGlzLT5jaGVja0NvbnRlbnQoKSBhcyB3ZWxsLgogICAgICAgICAgICAgICAgICAgIGNoZWNrQ29udGVudChnZXRFbnVtZXJhdGlvbigpLT5lbGVtZW50QXQoaSksIChWYWxpZGF0aW9uQ29udGV4dCopMCwgZmFsc2UsIG1hbmFnZXIpOwojZW5kaWYKICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgfQoKICAgICAgICAgICAgY2F0Y2ggKCBYTUxFeGNlcHRpb24mICkKICAgICAgICAgICAgewogICAgICAgICAgICAgICAgVGhyb3dYTUx3aXRoTWVtTWdyMShJbnZhbGlkRGF0YXR5cGVGYWNldEV4Y2VwdGlvbgogICAgICAgICAgICAgICAgICAgICAgICAsIFhNTEV4Y2VwdHM6OkZBQ0VUX2VudW1fYmFzZQogICAgICAgICAgICAgICAgICAgICAgICAsIGdldEVudW1lcmF0aW9uKCktPmVsZW1lbnRBdChpKQogICAgICAgICAgICAgICAgICAgICAgICAsIG1hbmFnZXIpOwogICAgICAgICAgICB9CgogICAgICAgIH0KCiAgICB9Cgp9Ly8gRW5kIG9mIGluc3BlY3RGYWNldEJhc2UoKQoKdm9pZCBMaXN0RGF0YXR5cGVWYWxpZGF0b3I6OmluaGVyaXRGYWNldCgpCnsKCiAgICAvL2lmZiB0aGUgYmFzZSB2YWxpZGF0b3IgaXMgTGlzdCwgdGhlbiB3ZSBpbmhlcml0CiAgICAvLwogICAgaWYgKGdldEJhc2VWYWxpZGF0b3IoKS0+Z2V0VHlwZSgpID09IERhdGF0eXBlVmFsaWRhdG9yOjpMaXN0KQogICAgewogICAgICAgIEFic3RyYWN0U3RyaW5nVmFsaWRhdG9yOjppbmhlcml0RmFjZXQoKTsKICAgIH0KCn0KCi8qKioKICogMi41LjEuMiBMaXN0IGRhdGF0eXBlcyAgIAogKiAgIAogKiBUaGUgY2Fub25pY2FsLWxleGljYWwtcmVwcmVzZW50YXRpb24gZm9yIHRoZSC3bGlzdLcgZGF0YXR5cGUgaXMgZGVmaW5lZCBhcyAKICogdGhlIGxleGljYWwgZm9ybSBpbiB3aGljaCBlYWNoIGl0ZW0gaW4gdGhlILdsaXN0tyBoYXMgdGhlIGNhbm9uaWNhbCAKICogbGV4aWNhbCByZXByZXNlbnRhdGlvbiBvZiBpdHMgt2l0ZW1UeXBlty4KICoqKi8KY29uc3QgWE1MQ2gqIExpc3REYXRhdHlwZVZhbGlkYXRvcjo6Z2V0Q2Fub25pY2FsUmVwcmVzZW50YXRpb24oY29uc3QgWE1MQ2gqICAgICAgICAgY29uc3QgcmF3RGF0YQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgLCAgICAgICBNZW1vcnlNYW5hZ2VyKiBjb25zdCBtZW1NZ3IKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICwgICAgICAgYm9vbCAgICAgICAgICAgICAgICAgdG9WYWxpZGF0ZSkgY29uc3QKewogICAgTWVtb3J5TWFuYWdlciogdG9Vc2UgPSBtZW1NZ3I/IG1lbU1nciA6IGdldE1lbW9yeU1hbmFnZXIoKTsKICAgIExpc3REYXRhdHlwZVZhbGlkYXRvciogdGVtcCA9IChMaXN0RGF0YXR5cGVWYWxpZGF0b3IqKSB0aGlzOwogICAgdGVtcC0+c2V0Q29udGVudChyYXdEYXRhKTsKICAgIEJhc2VSZWZWZWN0b3JPZjxYTUxDaD4qIHRva2VuVmVjdG9yID0gWE1MU3RyaW5nOjp0b2tlbml6ZVN0cmluZyhyYXdEYXRhLCB0b1VzZSk7CiAgICBKYW5pdG9yPEJhc2VSZWZWZWN0b3JPZjxYTUxDaD4gPiBqYW5OYW1lKHRva2VuVmVjdG9yKTsgICAgCgogICAgaWYgKHRvVmFsaWRhdGUpCiAgICB7CiAgICAgICAgdHJ5CiAgICAgICAgewogICAgICAgICAgICB0ZW1wLT5jaGVja0NvbnRlbnQodG9rZW5WZWN0b3IsIHJhd0RhdGEsIDAsIGZhbHNlLCB0b1VzZSk7CiAgICAgICAgfQogICAgICAgIGNhdGNoICguLi4pCiAgICAgICAgewogICAgICAgICAgICByZXR1cm4gMDsKICAgICAgICB9CiAgICB9CiAgIAogICAgdW5zaWduZWQgaW50ICByZXRCdWZTaXplID0gMiAqIFhNTFN0cmluZzo6c3RyaW5nTGVuKHJhd0RhdGEpOwogICAgWE1MQ2gqIHJldEJ1ZiA9IChYTUxDaCopIHRvVXNlLT5hbGxvY2F0ZShyZXRCdWZTaXplICogc2l6ZW9mKFhNTENoKSk7CiAgICByZXRCdWZbMF0gPSAwOwogICAgWE1MQ2gqIHJldEJ1ZlB0ciA9IHJldEJ1ZjsKICAgIERhdGF0eXBlVmFsaWRhdG9yKiBpdGVtRHYgPSB0aGlzLT5nZXRJdGVtVHlwZURUVigpOwoKICAgIHRyeSAKICAgIHsKICAgICAgICBmb3IgKHVuc2lnbmVkIGludCBpID0gMDsgaSA8IHRva2VuVmVjdG9yLT5zaXplKCk7IGkrKykKICAgICAgICB7CiAgICAgICAgICAgIFhNTENoKiBpdGVtQ2FuUmVwID0gKFhNTENoKikgaXRlbUR2LT5nZXRDYW5vbmljYWxSZXByZXNlbnRhdGlvbih0b2tlblZlY3Rvci0+ZWxlbWVudEF0KGkpLCB0b1VzZSwgZmFsc2UpOwogICAgICAgICAgICB1bnNpZ25lZCBpbnQgaXRlbUxlbiA9IFhNTFN0cmluZzo6c3RyaW5nTGVuKGl0ZW1DYW5SZXApOyAKCiAgICAgICAgICAgIGlmKHJldEJ1ZlB0citpdGVtTGVuKzIgPj0gcmV0QnVmK3JldEJ1ZlNpemUpCiAgICAgICAgICAgIHsKICAgICAgICAgICAgICAgIC8vIG5lZWQgdG8gcmVzaXplCiAgICAgICAgICAgICAgICBYTUxDaCAqIG9sZEJ1ZiA9IHJldEJ1ZjsKICAgICAgICAgICAgICAgIHJldEJ1ZiA9IChYTUxDaCopIHRvVXNlLT5hbGxvY2F0ZShyZXRCdWZTaXplICogc2l6ZW9mKFhNTENoKSAqIDQpOwogICAgICAgICAgICAgICAgbWVtY3B5KHJldEJ1Ziwgb2xkQnVmLCByZXRCdWZTaXplICogc2l6ZW9mKFhNTENoICkpOwogICAgICAgICAgICAgICAgcmV0QnVmUHRyID0gKHJldEJ1ZlB0ciAtIG9sZEJ1ZikgKyByZXRCdWY7CiAgICAgICAgICAgICAgICB0b1VzZS0+ZGVhbGxvY2F0ZShvbGRCdWYpOwogICAgICAgICAgICAgICAgcmV0QnVmU2l6ZSA8PD0gMjsKICAgICAgICAgICAgfQoKICAgICAgICAgICAgWE1MU3RyaW5nOjpjYXRTdHJpbmcocmV0QnVmUHRyLCBpdGVtQ2FuUmVwKTsKICAgICAgICAgICAgcmV0QnVmUHRyID0gcmV0QnVmUHRyICsgaXRlbUxlbjsKICAgICAgICAgICAgKihyZXRCdWZQdHIrKykgPSBjaFNwYWNlOwogICAgICAgICAgICAqKHJldEJ1ZlB0cikgPSBjaE51bGw7CiAgICAgICAgICAgIHRvVXNlLT5kZWFsbG9jYXRlKGl0ZW1DYW5SZXApOwogICAgICAgIH0KCiAgICAgICAgcmV0dXJuIHJldEJ1ZjsKCiAgICB9CiAgICBjYXRjaCAoLi4uKQogICAgewogICAgICAgIHJldHVybiAwOwogICAgfQp9CgovKioqCiAqIFN1cHBvcnQgZm9yIFNlcmlhbGl6YXRpb24vRGUtc2VyaWFsaXphdGlvbgogKioqLwoKSU1QTF9YU0VSSUFMSVpBQkxFX1RPQ1JFQVRFKExpc3REYXRhdHlwZVZhbGlkYXRvcikKCnZvaWQgTGlzdERhdGF0eXBlVmFsaWRhdG9yOjpzZXJpYWxpemUoWFNlcmlhbGl6ZUVuZ2luZSYgc2VyRW5nKQp7CiAgICBBYnN0cmFjdFN0cmluZ1ZhbGlkYXRvcjo6c2VyaWFsaXplKHNlckVuZyk7CgogICAgLy9kb24ndCBzZXJpYWxpemUgZkNvbnRlbnQsIHNpbmNlIGl0IGlzIE5PVCBvd25lZCBhbmQgCiAgICAvL3dpbGwgYmUgcmVzZXQgZWFjaCB0aW1lIHZhbGlkYXRlKCkvY2hlY2tDb250ZW50KCkgaW52b2tlZC4KfQoKWEVSQ0VTX0NQUF9OQU1FU1BBQ0VfRU5ECgovKioKICAqIEVuZCBvZiBmaWxlIExpc3REYXRhdHlwZVZhbGlkYXRvci5jcHAKICAqLwo=