LyogQm9vc3QgaW50ZXJ2YWwvdHJhbnNjLmhwcCB0ZW1wbGF0ZSBpbXBsZW1lbnRhdGlvbiBmaWxlCiAqCiAqIENvcHlyaWdodCAyMDAwIEplbnMgTWF1cmVyCiAqIENvcHlyaWdodCAyMDAyIEhlcnbpIEJy9m5uaW1hbm4sIEd1aWxsYXVtZSBNZWxxdWlvbmQsIFN5bHZhaW4gUGlvbgogKgogKiBEaXN0cmlidXRlZCB1bmRlciB0aGUgQm9vc3QgU29mdHdhcmUgTGljZW5zZSwgVmVyc2lvbiAxLjAuCiAqIChTZWUgYWNjb21wYW55aW5nIGZpbGUgTElDRU5TRV8xXzAudHh0IG9yCiAqIGNvcHkgYXQgaHR0cDovL3d3dy5ib29zdC5vcmcvTElDRU5TRV8xXzAudHh0KQogKi8KCiNpZm5kZWYgQk9PU1RfTlVNRVJJQ19JTlRFUlZBTF9UUkFOU0NfSFBQCiNkZWZpbmUgQk9PU1RfTlVNRVJJQ19JTlRFUlZBTF9UUkFOU0NfSFBQCgojaW5jbHVkZSA8Ym9vc3QvY29uZmlnLmhwcD4KI2luY2x1ZGUgPGJvb3N0L251bWVyaWMvaW50ZXJ2YWwvZGV0YWlsL2ludGVydmFsX3Byb3RvdHlwZS5ocHA+CiNpbmNsdWRlIDxib29zdC9udW1lcmljL2ludGVydmFsL2RldGFpbC9idWdzLmhwcD4KI2luY2x1ZGUgPGJvb3N0L251bWVyaWMvaW50ZXJ2YWwvZGV0YWlsL3Rlc3RfaW5wdXQuaHBwPgojaW5jbHVkZSA8Ym9vc3QvbnVtZXJpYy9pbnRlcnZhbC9yb3VuZGluZy5ocHA+CiNpbmNsdWRlIDxib29zdC9udW1lcmljL2ludGVydmFsL2NvbnN0YW50cy5ocHA+CiNpbmNsdWRlIDxib29zdC9udW1lcmljL2ludGVydmFsL2FyaXRoLmhwcD4KI2luY2x1ZGUgPGJvb3N0L251bWVyaWMvaW50ZXJ2YWwvYXJpdGgyLmhwcD4KI2luY2x1ZGUgPGFsZ29yaXRobT4KCm5hbWVzcGFjZSBib29zdCB7Cm5hbWVzcGFjZSBudW1lcmljIHsKCnRlbXBsYXRlPGNsYXNzIFQsIGNsYXNzIFBvbGljaWVzPiBpbmxpbmUKaW50ZXJ2YWw8VCwgUG9saWNpZXM+IGV4cChjb25zdCBpbnRlcnZhbDxULCBQb2xpY2llcz4mIHgpCnsKICB0eXBlZGVmIGludGVydmFsPFQsIFBvbGljaWVzPiBJOwogIGlmIChpbnRlcnZhbF9saWI6OmRldGFpbDo6dGVzdF9pbnB1dCh4KSkKICAgIHJldHVybiBJOjplbXB0eSgpOwogIHR5cGVuYW1lIFBvbGljaWVzOjpyb3VuZGluZyBybmQ7CiAgcmV0dXJuIEkocm5kLmV4cF9kb3duKHgubG93ZXIoKSksIHJuZC5leHBfdXAoeC51cHBlcigpKSwgdHJ1ZSk7Cn0KCnRlbXBsYXRlPGNsYXNzIFQsIGNsYXNzIFBvbGljaWVzPiBpbmxpbmUKaW50ZXJ2YWw8VCwgUG9saWNpZXM+IGxvZyhjb25zdCBpbnRlcnZhbDxULCBQb2xpY2llcz4mIHgpCnsKICB0eXBlZGVmIGludGVydmFsPFQsIFBvbGljaWVzPiBJOwogIGlmIChpbnRlcnZhbF9saWI6OmRldGFpbDo6dGVzdF9pbnB1dCh4KSB8fAogICAgICAhaW50ZXJ2YWxfbGliOjp1c2VyOjppc19wb3MoeC51cHBlcigpKSkKICAgIHJldHVybiBJOjplbXB0eSgpOwogIHR5cGVuYW1lIFBvbGljaWVzOjpyb3VuZGluZyBybmQ7CiAgdHlwZWRlZiB0eXBlbmFtZSBQb2xpY2llczo6Y2hlY2tpbmcgY2hlY2tpbmc7CiAgVCBsID0gIWludGVydmFsX2xpYjo6dXNlcjo6aXNfcG9zKHgubG93ZXIoKSkKICAgICAgICAgICAgID8gY2hlY2tpbmc6Om5lZ19pbmYoKSA6IHJuZC5sb2dfZG93bih4Lmxvd2VyKCkpOwogIHJldHVybiBJKGwsIHJuZC5sb2dfdXAoeC51cHBlcigpKSwgdHJ1ZSk7Cn0KCnRlbXBsYXRlPGNsYXNzIFQsIGNsYXNzIFBvbGljaWVzPiBpbmxpbmUKaW50ZXJ2YWw8VCwgUG9saWNpZXM+IGNvcyhjb25zdCBpbnRlcnZhbDxULCBQb2xpY2llcz4mIHgpCnsKICBpZiAoaW50ZXJ2YWxfbGliOjpkZXRhaWw6OnRlc3RfaW5wdXQoeCkpCiAgICByZXR1cm4gaW50ZXJ2YWw8VCwgUG9saWNpZXM+OjplbXB0eSgpOwogIHR5cGVuYW1lIFBvbGljaWVzOjpyb3VuZGluZyBybmQ7CiAgdHlwZWRlZiBpbnRlcnZhbDxULCBQb2xpY2llcz4gSTsKICB0eXBlZGVmIHR5cGVuYW1lIGludGVydmFsX2xpYjo6dW5wcm90ZWN0PEk+Ojp0eXBlIFI7CgogIC8vIGdldCBsb3dlciBib3VuZCB3aXRoaW4gWzAsIHBpXQogIGNvbnN0IFIgcGkyID0gaW50ZXJ2YWxfbGliOjpwaV90d2ljZTxSPigpOwogIFIgdG1wID0gZm1vZCgoY29uc3QgUiYpeCwgcGkyKTsKICBpZiAod2lkdGgodG1wKSA+PSBwaTIubG93ZXIoKSkKICAgIHJldHVybiBJKHN0YXRpY19jYXN0PFQ+KC0xKSwgc3RhdGljX2Nhc3Q8VD4oMSksIHRydWUpOyAvLyB3ZSBhcmUgY292ZXJpbmcgYSBmdWxsIHBlcmlvZAogIGlmICh0bXAubG93ZXIoKSA+PSBpbnRlcnZhbF9saWI6OmNvbnN0YW50czo6cGlfdXBwZXI8VD4oKSkKICAgIHJldHVybiAtY29zKHRtcCAtIGludGVydmFsX2xpYjo6cGk8Uj4oKSk7CiAgVCBsID0gdG1wLmxvd2VyKCk7CiAgVCB1ID0gdG1wLnVwcGVyKCk7CgogIEJPT1NUX1VTSU5HX1NURF9NSU4oKTsKICAvLyBzZXBhcmF0ZSBpbnRvIG1vbm90b25lIHN1YmludGVydmFscwogIGlmICh1IDw9IGludGVydmFsX2xpYjo6Y29uc3RhbnRzOjpwaV9sb3dlcjxUPigpKQogICAgcmV0dXJuIEkocm5kLmNvc19kb3duKHUpLCBybmQuY29zX3VwKGwpLCB0cnVlKTsKICBlbHNlIGlmICh1IDw9IHBpMi5sb3dlcigpKQogICAgcmV0dXJuIEkoc3RhdGljX2Nhc3Q8VD4oLTEpLCBybmQuY29zX3VwKG1pbiBCT09TVF9QUkVWRU5UX01BQ1JPX1NVQlNUSVRVVElPTihybmQuc3ViX2Rvd24ocGkyLmxvd2VyKCksIHUpLCBsKSksIHRydWUpOwogIGVsc2UKICAgIHJldHVybiBJKHN0YXRpY19jYXN0PFQ+KC0xKSwgc3RhdGljX2Nhc3Q8VD4oMSksIHRydWUpOwp9Cgp0ZW1wbGF0ZTxjbGFzcyBULCBjbGFzcyBQb2xpY2llcz4gaW5saW5lCmludGVydmFsPFQsIFBvbGljaWVzPiBzaW4oY29uc3QgaW50ZXJ2YWw8VCwgUG9saWNpZXM+JiB4KQp7CiAgdHlwZWRlZiBpbnRlcnZhbDxULCBQb2xpY2llcz4gSTsKICBpZiAoaW50ZXJ2YWxfbGliOjpkZXRhaWw6OnRlc3RfaW5wdXQoeCkpCiAgICByZXR1cm4gSTo6ZW1wdHkoKTsKICB0eXBlbmFtZSBQb2xpY2llczo6cm91bmRpbmcgcm5kOwogIHR5cGVkZWYgdHlwZW5hbWUgaW50ZXJ2YWxfbGliOjp1bnByb3RlY3Q8ST46OnR5cGUgUjsKICBJIHIgPSBjb3MoKGNvbnN0IFImKXggLSBpbnRlcnZhbF9saWI6OnBpX2hhbGY8Uj4oKSk7CiAgKHZvaWQpJnJuZDsKICByZXR1cm4gcjsKfQoKdGVtcGxhdGU8Y2xhc3MgVCwgY2xhc3MgUG9saWNpZXM+IGlubGluZQppbnRlcnZhbDxULCBQb2xpY2llcz4gdGFuKGNvbnN0IGludGVydmFsPFQsIFBvbGljaWVzPiYgeCkKewogIHR5cGVkZWYgaW50ZXJ2YWw8VCwgUG9saWNpZXM+IEk7CiAgaWYgKGludGVydmFsX2xpYjo6ZGV0YWlsOjp0ZXN0X2lucHV0KHgpKQogICAgcmV0dXJuIEk6OmVtcHR5KCk7CiAgdHlwZW5hbWUgUG9saWNpZXM6OnJvdW5kaW5nIHJuZDsKICB0eXBlZGVmIHR5cGVuYW1lIGludGVydmFsX2xpYjo6dW5wcm90ZWN0PEk+Ojp0eXBlIFI7CgogIC8vIGdldCBsb3dlciBib3VuZCB3aXRoaW4gWy1waS8yLCBwaS8yXQogIGNvbnN0IFIgcGkgPSBpbnRlcnZhbF9saWI6OnBpPFI+KCk7CiAgUiB0bXAgPSBmbW9kKChjb25zdCBSJil4LCBwaSk7CiAgY29uc3QgVCBwaV9oYWxmX2QgPSBpbnRlcnZhbF9saWI6OmNvbnN0YW50czo6cGlfaGFsZl9sb3dlcjxUPigpOwogIGlmICh0bXAubG93ZXIoKSA+PSBwaV9oYWxmX2QpCiAgICB0bXAgLT0gcGk7CiAgaWYgKHRtcC5sb3dlcigpIDw9IC1waV9oYWxmX2QgfHwgdG1wLnVwcGVyKCkgPj0gcGlfaGFsZl9kKQogICAgcmV0dXJuIEk6Ondob2xlKCk7CiAgcmV0dXJuIEkocm5kLnRhbl9kb3duKHRtcC5sb3dlcigpKSwgcm5kLnRhbl91cCh0bXAudXBwZXIoKSksIHRydWUpOwp9Cgp0ZW1wbGF0ZTxjbGFzcyBULCBjbGFzcyBQb2xpY2llcz4gaW5saW5lCmludGVydmFsPFQsIFBvbGljaWVzPiBhc2luKGNvbnN0IGludGVydmFsPFQsIFBvbGljaWVzPiYgeCkKewogIHR5cGVkZWYgaW50ZXJ2YWw8VCwgUG9saWNpZXM+IEk7CiAgaWYgKGludGVydmFsX2xpYjo6ZGV0YWlsOjp0ZXN0X2lucHV0KHgpCiAgICAgfHwgeC51cHBlcigpIDwgc3RhdGljX2Nhc3Q8VD4oLTEpIHx8IHgubG93ZXIoKSA+IHN0YXRpY19jYXN0PFQ+KDEpKQogICAgcmV0dXJuIEk6OmVtcHR5KCk7CiAgdHlwZW5hbWUgUG9saWNpZXM6OnJvdW5kaW5nIHJuZDsKICBUIGwgPSAoeC5sb3dlcigpIDw9IHN0YXRpY19jYXN0PFQ+KC0xKSkKICAgICAgICAgICAgID8gLWludGVydmFsX2xpYjo6Y29uc3RhbnRzOjpwaV9oYWxmX3VwcGVyPFQ+KCkKICAgICAgICAgICAgIDogcm5kLmFzaW5fZG93bih4Lmxvd2VyKCkpOwogIFQgdSA9ICh4LnVwcGVyKCkgPj0gc3RhdGljX2Nhc3Q8VD4oMSkgKQogICAgICAgICAgICAgPyAgaW50ZXJ2YWxfbGliOjpjb25zdGFudHM6OnBpX2hhbGZfdXBwZXI8VD4oKQogICAgICAgICAgICAgOiBybmQuYXNpbl91cCAgKHgudXBwZXIoKSk7CiAgcmV0dXJuIEkobCwgdSwgdHJ1ZSk7Cn0KCnRlbXBsYXRlPGNsYXNzIFQsIGNsYXNzIFBvbGljaWVzPiBpbmxpbmUKaW50ZXJ2YWw8VCwgUG9saWNpZXM+IGFjb3MoY29uc3QgaW50ZXJ2YWw8VCwgUG9saWNpZXM+JiB4KQp7CiAgdHlwZWRlZiBpbnRlcnZhbDxULCBQb2xpY2llcz4gSTsKICBpZiAoaW50ZXJ2YWxfbGliOjpkZXRhaWw6OnRlc3RfaW5wdXQoeCkKICAgICB8fCB4LnVwcGVyKCkgPCBzdGF0aWNfY2FzdDxUPigtMSkgfHwgeC5sb3dlcigpID4gc3RhdGljX2Nhc3Q8VD4oMSkpCiAgICByZXR1cm4gSTo6ZW1wdHkoKTsKICB0eXBlbmFtZSBQb2xpY2llczo6cm91bmRpbmcgcm5kOwogIFQgbCA9ICh4LnVwcGVyKCkgPj0gc3RhdGljX2Nhc3Q8VD4oMSkgKQogICAgICAgICAgPyBzdGF0aWNfY2FzdDxUPigwKQogICAgICAgICAgOiBybmQuYWNvc19kb3duKHgudXBwZXIoKSk7CiAgVCB1ID0gKHgubG93ZXIoKSA8PSBzdGF0aWNfY2FzdDxUPigtMSkpCiAgICAgICAgICA/IGludGVydmFsX2xpYjo6Y29uc3RhbnRzOjpwaV91cHBlcjxUPigpCiAgICAgICAgICA6IHJuZC5hY29zX3VwICAoeC5sb3dlcigpKTsKICByZXR1cm4gSShsLCB1LCB0cnVlKTsKfQoKdGVtcGxhdGU8Y2xhc3MgVCwgY2xhc3MgUG9saWNpZXM+IGlubGluZQppbnRlcnZhbDxULCBQb2xpY2llcz4gYXRhbihjb25zdCBpbnRlcnZhbDxULCBQb2xpY2llcz4mIHgpCnsKICB0eXBlZGVmIGludGVydmFsPFQsIFBvbGljaWVzPiBJOwogIGlmIChpbnRlcnZhbF9saWI6OmRldGFpbDo6dGVzdF9pbnB1dCh4KSkKICAgIHJldHVybiBJOjplbXB0eSgpOwogIHR5cGVuYW1lIFBvbGljaWVzOjpyb3VuZGluZyBybmQ7CiAgcmV0dXJuIEkocm5kLmF0YW5fZG93bih4Lmxvd2VyKCkpLCBybmQuYXRhbl91cCh4LnVwcGVyKCkpLCB0cnVlKTsKfQoKdGVtcGxhdGU8Y2xhc3MgVCwgY2xhc3MgUG9saWNpZXM+IGlubGluZQppbnRlcnZhbDxULCBQb2xpY2llcz4gc2luaChjb25zdCBpbnRlcnZhbDxULCBQb2xpY2llcz4mIHgpCnsKICB0eXBlZGVmIGludGVydmFsPFQsIFBvbGljaWVzPiBJOwogIGlmIChpbnRlcnZhbF9saWI6OmRldGFpbDo6dGVzdF9pbnB1dCh4KSkKICAgIHJldHVybiBJOjplbXB0eSgpOwogIHR5cGVuYW1lIFBvbGljaWVzOjpyb3VuZGluZyBybmQ7CiAgcmV0dXJuIEkocm5kLnNpbmhfZG93bih4Lmxvd2VyKCkpLCBybmQuc2luaF91cCh4LnVwcGVyKCkpLCB0cnVlKTsKfQoKdGVtcGxhdGU8Y2xhc3MgVCwgY2xhc3MgUG9saWNpZXM+IGlubGluZQppbnRlcnZhbDxULCBQb2xpY2llcz4gY29zaChjb25zdCBpbnRlcnZhbDxULCBQb2xpY2llcz4mIHgpCnsKICB0eXBlZGVmIGludGVydmFsPFQsIFBvbGljaWVzPiBJOwogIGlmIChpbnRlcnZhbF9saWI6OmRldGFpbDo6dGVzdF9pbnB1dCh4KSkKICAgIHJldHVybiBJOjplbXB0eSgpOwogIHR5cGVuYW1lIFBvbGljaWVzOjpyb3VuZGluZyBybmQ7CiAgaWYgKGludGVydmFsX2xpYjo6dXNlcjo6aXNfbmVnKHgudXBwZXIoKSkpCiAgICByZXR1cm4gSShybmQuY29zaF9kb3duKHgudXBwZXIoKSksIHJuZC5jb3NoX3VwKHgubG93ZXIoKSksIHRydWUpOwogIGVsc2UgaWYgKCFpbnRlcnZhbF9saWI6OnVzZXI6OmlzX25lZyh4Lmxvd2VyKCkpKQogICAgcmV0dXJuIEkocm5kLmNvc2hfZG93bih4Lmxvd2VyKCkpLCBybmQuY29zaF91cCh4LnVwcGVyKCkpLCB0cnVlKTsKICBlbHNlCiAgICByZXR1cm4gSShzdGF0aWNfY2FzdDxUPigwKSwgcm5kLmNvc2hfdXAoLXgubG93ZXIoKSA+IHgudXBwZXIoKSA/IHgubG93ZXIoKSA6IHgudXBwZXIoKSksIHRydWUpOwp9Cgp0ZW1wbGF0ZTxjbGFzcyBULCBjbGFzcyBQb2xpY2llcz4gaW5saW5lCmludGVydmFsPFQsIFBvbGljaWVzPiB0YW5oKGNvbnN0IGludGVydmFsPFQsIFBvbGljaWVzPiYgeCkKewogIHR5cGVkZWYgaW50ZXJ2YWw8VCwgUG9saWNpZXM+IEk7CiAgaWYgKGludGVydmFsX2xpYjo6ZGV0YWlsOjp0ZXN0X2lucHV0KHgpKQogICAgcmV0dXJuIEk6OmVtcHR5KCk7CiAgdHlwZW5hbWUgUG9saWNpZXM6OnJvdW5kaW5nIHJuZDsKICByZXR1cm4gSShybmQudGFuaF9kb3duKHgubG93ZXIoKSksIHJuZC50YW5oX3VwKHgudXBwZXIoKSksIHRydWUpOwp9Cgp0ZW1wbGF0ZTxjbGFzcyBULCBjbGFzcyBQb2xpY2llcz4gaW5saW5lCmludGVydmFsPFQsIFBvbGljaWVzPiBhc2luaChjb25zdCBpbnRlcnZhbDxULCBQb2xpY2llcz4mIHgpCnsKICB0eXBlZGVmIGludGVydmFsPFQsIFBvbGljaWVzPiBJOwogIGlmIChpbnRlcnZhbF9saWI6OmRldGFpbDo6dGVzdF9pbnB1dCh4KSkKICAgIHJldHVybiBJOjplbXB0eSgpOwogIHR5cGVuYW1lIFBvbGljaWVzOjpyb3VuZGluZyBybmQ7CiAgcmV0dXJuIEkocm5kLmFzaW5oX2Rvd24oeC5sb3dlcigpKSwgcm5kLmFzaW5oX3VwKHgudXBwZXIoKSksIHRydWUpOwp9Cgp0ZW1wbGF0ZTxjbGFzcyBULCBjbGFzcyBQb2xpY2llcz4gaW5saW5lCmludGVydmFsPFQsIFBvbGljaWVzPiBhY29zaChjb25zdCBpbnRlcnZhbDxULCBQb2xpY2llcz4mIHgpCnsKICB0eXBlZGVmIGludGVydmFsPFQsIFBvbGljaWVzPiBJOwogIGlmIChpbnRlcnZhbF9saWI6OmRldGFpbDo6dGVzdF9pbnB1dCh4KSB8fCB4LnVwcGVyKCkgPCBzdGF0aWNfY2FzdDxUPigxKSkKICAgIHJldHVybiBJOjplbXB0eSgpOwogIHR5cGVuYW1lIFBvbGljaWVzOjpyb3VuZGluZyBybmQ7CiAgVCBsID0geC5sb3dlcigpIDw9IHN0YXRpY19jYXN0PFQ+KDEpID8gc3RhdGljX2Nhc3Q8VD4oMCkgOiBybmQuYWNvc2hfZG93bih4Lmxvd2VyKCkpOwogIHJldHVybiBJKGwsIHJuZC5hY29zaF91cCh4LnVwcGVyKCkpLCB0cnVlKTsKfQoKdGVtcGxhdGU8Y2xhc3MgVCwgY2xhc3MgUG9saWNpZXM+IGlubGluZQppbnRlcnZhbDxULCBQb2xpY2llcz4gYXRhbmgoY29uc3QgaW50ZXJ2YWw8VCwgUG9saWNpZXM+JiB4KQp7CiAgdHlwZWRlZiBpbnRlcnZhbDxULCBQb2xpY2llcz4gSTsKICBpZiAoaW50ZXJ2YWxfbGliOjpkZXRhaWw6OnRlc3RfaW5wdXQoeCkKICAgICAgfHwgeC51cHBlcigpIDwgc3RhdGljX2Nhc3Q8VD4oLTEpIHx8IHgubG93ZXIoKSA+IHN0YXRpY19jYXN0PFQ+KDEpKQogICAgcmV0dXJuIEk6OmVtcHR5KCk7CiAgdHlwZW5hbWUgUG9saWNpZXM6OnJvdW5kaW5nIHJuZDsKICB0eXBlZGVmIHR5cGVuYW1lIFBvbGljaWVzOjpjaGVja2luZyBjaGVja2luZzsKICBUIGwgPSAoeC5sb3dlcigpIDw9IHN0YXRpY19jYXN0PFQ+KC0xKSkKICAgICAgICAgICAgID8gY2hlY2tpbmc6Om5lZ19pbmYoKSA6IHJuZC5hdGFuaF9kb3duKHgubG93ZXIoKSk7CiAgVCB1ID0gKHgudXBwZXIoKSA+PSBzdGF0aWNfY2FzdDxUPigxKSApCiAgICAgICAgICAgICA/IGNoZWNraW5nOjpwb3NfaW5mKCkgOiBybmQuYXRhbmhfdXAgICh4LnVwcGVyKCkpOwogIHJldHVybiBJKGwsIHUsIHRydWUpOwp9Cgp9IC8vIG5hbWVzcGFjZSBudW1lcmljCn0gLy8gbmFtZXNwYWNlIGJvb3N0CgojZW5kaWYgLy8gQk9PU1RfTlVNRVJJQ19JTlRFUlZBTF9UUkFOU0NfSFBQCg==