Ly8gTW9yZ2VuR3JhdWVuIE1VRGxpYgovLwovLyBwbGF5ZXIvY29tYmF0LmMgLS0gY29tYmF0IHN0YXRpc3RpY3MKLy8KLy8gJElkOiBjb21iYXQuYyA5MDA4IDIwMTUtMDEtMDYgMTc6MjA6MTdaIFplc3N0cmEgJAojcHJhZ21hIHN0cm9uZ190eXBlcwojcHJhZ21hIHNhdmVfdHlwZXMKI3ByYWdtYSByYW5nZV9jaGVjawojcHJhZ21hIG5vX2Nsb25lCiNwcmFnbWEgcGVkYW50aWMKCmluaGVyaXQgIi9zdGQvbGl2aW5nL2NvbWJhdCI7CmluaGVyaXQgIi9zdGQvcGxheWVyL3BrbG9nIjsKCiNpbmNsdWRlIDx0aGluZy9wcm9wZXJ0aWVzLmg+CiNpbmNsdWRlIDxwcm9wZXJ0aWVzLmg+CiNpbmNsdWRlIDx3aXpsZXZlbHMuaD4KI2luY2x1ZGUgPGNvbWJhdC5oPgojaW5jbHVkZSA8bmV3X3NraWxscy5oPgoKI2RlZmluZSBNRSB0aGlzX29iamVjdCgpCiNkZWZpbmUgU1RBVE1BU1RFUiAiL3Avc2VydmljZS9yb2NodXMvZ3VpbGRzdGF0L21hc3RlciIKCnByaXZhdGUgbm9zYXZlIGNsb3N1cmUgbW9kX2RlZl9zdGF0Owpwcml2YXRlIG5vc2F2ZSBzdHJpbmcgKnBsQXR0YWNrZWQgPSAoe30pOwoKcHJvdGVjdGVkIHZvaWQgY3JlYXRlKCkgewogIGNvbWJhdDo6Y3JlYXRlKCk7CiAgLy8gUF9OT19BVFRBQ0sgaXN0IG5pY2h0IGZ1ZXIgU3BpZWxlciBnZWRhY2h0LiBBdXNuYWhtZTogU3BpZWxlciBpc3QKICAvLyBHZWlzdCwgZGFubiBzZXR6dCBkYXMgU3BpZWxlcm9iamVrdCBhYmVyIHNlbGJlci4KICBTZXQoUF9OT19BVFRBQ0ssIFNFQ1VSRUR8Tk9TRVRNRVRIT0QsIEZfTU9ERV9BUyk7CiAgCiAgU2V0KFBfSEVMUEVSX05QQywgUFJPVEVDVEVELCBGX01PREUpOwogIFNldFByb3AoUF9IRUxQRVJfTlBDLCAoW10pICk7Cn0KCi8vIE1hc2tlIGZ1ZXIgYWxsZSBtb2VnbGljaGVuIEtsYXNzZW4gdm9uIEhlbGZlci1OUEMKI2RlZmluZSBDTEFTU19NQVNLIDB4MWZmZmZmZmYKLyoqIHJlZ2lzdHJpZXJ0IGRlbiBOUEMgYWxzIEhlbGZlciB2b24gZGllc2VtIFNwaWVsZXIuCiAgQHBhcmFtW2luXSBucGMgb2JqZWN0IEhlbGZlci1OUEMKICBAcGFyYW1baW5dIGZsYWdzIGludCBCaXRmZWxkIHZvbiBGbGFncwogIEByZXR1cm4gaW50IDEsIGZhbGxzIGRlciBIZWxmZXItTlBDIHJlZ2lzdHJpZXJ0IHd1cmRlIHVuZCBub2NoIG5pY2h0CiAgcmVnaXN0cmllcnQgd2FyLgogIEBhdHRlbnRpb24gTnV0enQgYXVzLCBkYXNzIFF1ZXJ5UHJvcChQX0hFTFBFUl9OUEMpIF9rZWluZV8gS29waWUgZGVzCiAgTWFwcGluZ3MgaW4gZGVyIFByb3AgbGllZmVydC4KICAqLwpwdWJsaWMgaW50IFJlZ2lzdGVySGVscGVyTlBDKG9iamVjdCBucGMsIGludCBmbGFncykgewogIGlmICghb2JqZWN0cChucGMpKQogICAgcmFpc2VfZXJyb3Ioc3ByaW50ZiggIldyb25nIGFyZ3VtZW50IDEgaW4gUmVnaXN0ZXJIZWxwZXJOUEMoKS4gIgogICAgICAgICAgIkV4cGVjdGVkIDxvYmplY3Q+LCBnb3QgJS4xMDBPXG4iLCBucGMpKTsKICBpZiAoIWludHAoZmxhZ3MpIHx8IGZsYWdzIDwgMSkKICAgICByYWlzZV9lcnJvcihzcHJpbnRmKCAiV3JvbmcgYXJndW1lbnQgMiBpbiBSZWdpc3RlckhlbHBlck5QQygpLiAiCiAgICAgICAgICAiRXhwZWN0ZWQgcG9zaXRpdmUgPGludD4sIGdvdCAlT1xuIiwgZmxhZ3MpKTsKICAKICBtYXBwaW5nIGhlbHBlcnMgPSBRdWVyeVByb3AoUF9IRUxQRVJfTlBDKTsKICAKICAvLyBzY2hvbiByZWdpc3RyaWVydGUgc2luZCB3aXR6bG9zLgogIGlmIChtZW1iZXIoaGVscGVycywgbnBjKSkKICAgIHJldHVybiAwOwogIAogIC8vIGF1ZiBleGtsdXNpdmUgSGVsZmVyIHBydWVmZW4uCiAgZm9yZWFjaChvYmplY3QgaGVscGVyLCBpbnQgZmw6IGhlbHBlcnMpIHsKICAgIC8vIGZsYWdzIGlkZW50aXNjaD8gRGFubiBLbGFzc2UgdW5kIEV4a2x1c2l2aXRhZXQgaWRlbnRpc2NoCiAgICBpZiAoZmwgPT0gZmxhZ3MpCiAgICAgIHJldHVybiAwOwogICAgLy8gb2RlciBlaW5lciB2b24gYmVpZGVuIGV4a2x1c2l2IHVuZCBiZWlkZSBpbiBkZXIgZ2xlaWNoZW4gS2xhc3NlPwogICAgZWxzZSBpZiAoICgoZmwgJiBFWENMVVNJVkVfSEVMUEVSKSB8fCAoZmxhZ3MgJiBFWENMVVNJVkVfSEVMUEVSKSkKICAgICAgICAgICAgICAmJiAoKGZsICYgQ0xBU1NfTUFTSykgPT0gKGZsYWdzICYgQ0xBU1NfTUFTSykpICkKICAgICAgcmV0dXJuIDA7CiAgfQogIC8vIHNjaGVpbnQgd29obCBvayB6dSBzZWluLiBSZWdpc3RyaWVyZW4gdW5kIFByb3AgaW0gTlBDIHNldHplbi4KICBoZWxwZXJzICs9IChbIG5wYzogZmxhZ3MgXSk7CiAgbnBjLT5TZXRQcm9wKFBfSEVMUEVSX05QQywgKHsgdGhpc19vYmplY3QoKSwgZmxhZ3MgfSkgKTsKICAvLyBtb21lbnRhbiB1bm5vZXRpZywgZGEgaGVscGVycyBrZWluZSBLb3BpZSBpc3QuCiAgLy8gU2V0UHJvcChQX0hFTFBFUl9OUEMsIGhlbHBlcnMpOwoKICByZXR1cm4gMTsKfQojdW5kZWYgQ0xBU1NfTUFTSwoKLyoqIGRlLXJlZ2lzdHJpZXJ0IGRlbiBOUEMgYWxzIEhlbGZlciB2b24gZGllc2VtIFNwaWVsZXIuCiAgQHBhcmFtW2luXSBucGMgb2JqZWN0IEhlbGZlci1OUEMKICBAcmV0dXJuIGludCAxLCBmYWxscyBkZXIgSGVsZmVyLU5QQyByZWdpc3RyaWVydCB3YXIgdW5kIGVudGZlcm50IHd1cmRlLgogIEBhdHRlbnRpb24gTnV0enQgYXVzLCBkYXNzIFF1ZXJ5UHJvcChQX0hFTFBFUl9OUEMpIF9rZWluZV8gS29waWUgZGVzCiAgTWFwcGluZ3MgaW4gZGVyIFByb3AgbGllZmVydC4KICovCnB1YmxpYyBpbnQgVW5yZWdpc3RlckhlbHBlck5QQyhvYmplY3QgbnBjKSB7CiAgaWYgKCFvYmplY3RwKG5wYykpCiAgICByYWlzZV9lcnJvcihzcHJpbnRmKCJXcm9uZyBhcmd1bWVudCBpbiBVbnJlZ2lzdGVySGVscGVybk5QQygpLiAiCiAgICAgICAgICAiRXhwZWN0ZWQgPG9iamVjdD4sIGdvdCAlLjEwME9cbiIsIG5wYykpOwoKICBtYXBwaW5nIGhlbHBlcnMgPSBRdWVyeVByb3AoUF9IRUxQRVJfTlBDKTsKICBpZiAobWVtYmVyKGhlbHBlcnMsIG5wYykpIHsKICAgIG1fZGVsZXRlKGhlbHBlcnMsIG5wYyk7CiAgICAvLyBtb21lbnRhbiB1bm5vZXRpZywgZGEgaGVscGVycyBrZWluZSBLb3BpZSBpc3QuCiAgICAvLyBTZXRQcm9wKFBfSEVMUEVSX05QQywgaGVscGVycyk7CiAgICBucGMtPlNldFByb3AoUF9IRUxQRVJfTlBDLCAwKTsKICAgIHJldHVybiAxOwogIH0KICByZXR1cm4gMDsKfQoKLyoqIEZlaW5kIGVpbnRyYWdlbi4KICAqIFRyYWVndCBvYiBhbHMgRmVpbmQgZWluLiBEaWVzIGFsbGVyZGluZ3MgbnVyLCB3ZW5uIG9iIGtlaW4gU3BpZWxlciBpc3QKICAqIG9kZXIgYmVpZGUgU3BpZWxlciAoZGllc2VzIE9iamVrdCB1bmQgb2IpIGluIGRlciBTY2hhdHRlbndlbHQgc2luZCBvZGVyCiAgKiBiZWlkZSBTcGllbGVyIFRlc3RzcGllbGVyIHNpbmQuCiAgIEBwYXJhbVtpbl0gb2IgcG90ZW50aWVsbGVyIEZlaW5kLgogICBAcmV0dXJuIGludCAxLCBmYWxscyBvYiBhbHMgX25ldWVyXyBGZWluZCBlaW5nZXRyYWdlbiB3dXJkZS4KICAgKi8KcHVibGljIGludCBJbnNlcnRFbmVteShvYmplY3Qgb2IpIHsKICAvLyB3ZW5uIG9iIGVpbiBTcGllbGVyIGlzdCB1bmQgbmljaHQgc293b2hsIGljaCBhbHMgYXVjaCBvYiBpbiBkZXIKICAvLyBTY2hhdHRlbndlbHQgc2luZCwgd2lyZCBvYiBuaWNodCBhbHMgRmVpbmQgZWluZ2V0cmFnZW4uCiAgaWYgKHF1ZXJ5X29uY2VfaW50ZXJhY3RpdmUob2IpCiAgICAgICYmIChzdHJzdHIob2JqZWN0X25hbWUoZW52aXJvbm1lbnQob2IpKSwiL2Qvc2NoYXR0ZW53ZWx0LyIpIT0wCiAgICAgICAgICB8fCBzdHJzdHIob2JqZWN0X25hbWUoZW52aXJvbm1lbnQoTUUpKSwiL2Qvc2NoYXR0ZW53ZWx0LyIpIT0wKQogICAgICAmJiAoIVF1ZXJ5UHJvcChQX1RFU1RQTEFZRVIpIHx8ICFvYi0+UXVlcnlQcm9wKFBfVEVTVFBMQVlFUikpCiAgICAgKQogIHsKICAgIHJldHVybiAwOwogIH0KICByZXR1cm4gOjpJbnNlcnRFbmVteShvYik7Cn0KCi8qKiBIYXQgZGllc2VyIFNwaWVsZXIgZGVuIFNwaWVsZXIgcGwgYW5nZWdyaWZmZW4/LgogIEBwYXJhbVtpbl0gcGwgb2JqZWN0IHp1IHBydWVmZW5kZXIgU3BpZWxlcgogIEByZXR1cm4gaW50IDEsIGZhbGxzIGRpZXNlciBTcGllbGVyIHBsIGFuZ2VncmlmZmVuIGhhdC4KICBAYXR0ZW50aW9uIE5lYmVuZWZmZWt0OiBiZXJlaW5pZ3QgZGVuIGludGVybmVuIFNwZWljaGVyIHZvbiBVSURzIHZvbgogIHplcnN0b2VydGVuIFNwaWVsZXJuIHVuZCBzb2xjaGVuLCBkaWUga2VpbmUgRmVpbmRlIG1laHIgc2luZC4KICAqLwpwdWJsaWMgaW50IFF1ZXJ5UGxBdHRhY2tlZChvYmplY3QgcGwpIHsKICBvYmplY3Qgb2I7CgogIGlmICggIW9iamVjdHAocGwpICkKICAgIHJldHVybiAwOwoKICBmb3JlYWNoKHN0cmluZyBwbG5hbWU6IHBsQXR0YWNrZWQpIHsKICAgIGlmICggISggb2I9KGZpbmRfcGxheWVyKHBsbmFtZSl8fGZpbmRfbmV0ZGVhZChwbG5hbWUpKSApCiAgICAgICAgfHwgKCAhSXNFbmVteShvYikgJiYgIShvYi0+SXNFbmVteShNRSkpICkgKQogICAgICBwbEF0dGFja2VkIC09ICh7cGxuYW1lfSk7IC8vIGphLCBkYXMgZ2VodC4gOy0pCiAgfQogIHJldHVybiAobWVtYmVyKCBwbEF0dGFja2VkLCBnZXR1aWQocGwpICkgPj0gMCk7Cn0KCi8qKiBraWxsIC0gS2FtcGYgc3RhcnRlbi4KICogRnVlZ3Qgb2IgZGVyIEZlaW5kZXNsaXN0ZSBoaW56dS4KICovCnB1YmxpYyBpbnQgS2lsbChvYmplY3Qgb2IpIHsKCiAgaWYgKCFvYmplY3RwKG9iKSkgcmV0dXJuIDA7CgogIC8vIGRpZXMgZGllbnQgbnVyIGRhenUsIGRhcyBwbEF0dGFja2VkIG1hcHBpbmcgenUgYmVyZWluaWdlbi4KICAvLyBUT0RPOiBiZXNzZXIgbWFjaGVuLiA7LSkKICBpZiAoIHF1ZXJ5X29uY2VfaW50ZXJhY3RpdmUob2IpICYmICFJc0VuZW15KG9iKSkgewogICAgUXVlcnlQbEF0dGFja2VkKE1FKTsKICAgIG9iLT5RdWVyeVBsQXR0YWNrZWQob2IpOyAvLyBha3R1YWxpc2llcmVuIC4uLgogIH0KCiAgaW50IHJlcyA9IGNvbWJhdDo6S2lsbChvYik7CgogIC8vIGZhbGxzIG9iIG5lbiBTcGllbGVyIGlzdCwgcHJ1ZWZlbiwgb2IgZXMgZWluIFNwaWVsZXItU3BpZWxlci1BbmdyaWZmCiAgLy8gaXN0LgogIC8vIERhYmVpIGdnZi4gbG9nZ2VuIHVuZCBNYWdpZXIgdmVyc3RhZW5kaWdlbi4KICBpZiAocXVlcnlfb25jZV9pbnRlcmFjdGl2ZShvYikgJiYgQ2hlY2tQbGF5ZXJBdHRhY2soTUUsIG9iLCAwKSkKICB7CiAgICBpZiAocmVzID09IC00KSAvLyBmZWluZCB3dXJkZSBuaWNodCBlaW5nZXRyYWdlbgogICAgICB0ZWxsX29iamVjdChNRSwgIkVpbiBnb2V0dGxpY2hlciBCZWZlaGwgaGluZGVydCBEaWNoIGFtIEthbXBmLlxuIik7CiAgICBlbHNlCiAgICAgIHBsQXR0YWNrZWQgKz0gKHsgZ2V0dWlkKG9iKSB9KTsKICB9CgogIHJldHVybiByZXM7Cn0KCnB1YmxpYyBpbnQgRGVmZW5kKGludCBkYW0sIHN0cmluZ3xzdHJpbmcqIGRhbV90eXBlLCBpbnR8bWFwcGluZyBzcGVsbCwgb2JqZWN0IGVuZW15KSB7CiAgaW50IGRlbHRhX2hwLHJlczsKCiAgaWYgKHF1ZXJ5X29uY2VfaW50ZXJhY3RpdmUoTUUpCiAgICAgICYmICFJU19MRUFSTkVSKE1FKQogICAgICAmJiAhb2JqZWN0cChnZXRfdHlwZV9pbmZvKG1vZF9kZWZfc3RhdCwyKSkpIHsKICAgIG9iamVjdCBtYTsKICAgIGlmICghb2JqZWN0cChtYT1maW5kX29iamVjdChTVEFUTUFTVEVSKSkpCiAgICAgIHJldHVybiA6OkRlZmVuZChkYW0sZGFtX3R5cGUsc3BlbGwsZW5lbXkpOwogICAgLy8gU3RhdGlzdGlrIG51ciBhdWZydWZlbiBmYWxscyBNYXN0ZXIgZ2VsYWRlbgogICAgbW9kX2RlZl9zdGF0PXN5bWJvbF9mdW5jdGlvbigiTW9kaWZ5RGVmZW5kU3RhdCIsbWEpOwogIH0KCiAgaWYgKGNsb3N1cmVwKG1vZF9kZWZfc3RhdCkpCiAgICBkZWx0YV9ocD1RdWVyeVByb3AoUF9IUCk7CgogIHJlcz06OkRlZmVuZChkYW0sZGFtX3R5cGUsc3BlbGwsZW5lbXkpOwoKICBpZiAoY2xvc3VyZXAobW9kX2RlZl9zdGF0KSkgewogICAgZGVsdGFfaHAtPVF1ZXJ5UHJvcChQX0hQKTsKICAgIGlmIChkZWx0YV9ocDwwKQogICAgICBkZWx0YV9ocD0wOwogICAgZnVuY2FsbChtb2RfZGVmX3N0YXQsCiAgICAgICAgICAgIFF1ZXJ5UHJvcChQX0dVSUxEKSwKICAgICAgICAgICAgUXVlcnlQcm9wKFBfR1VJTERfTEVWRUwpLAogICAgICAgICAgICBkYW0tMTAqZGVsdGFfaHAsCiAgICAgICAgICAgIGRhbV90eXBlLAogICAgICAgICAgICBzcGVsbCk7CiAgfQoKICByZXR1cm4gcmVzOwp9CgovLyBTcGllbGVyIGtvZW5uZW4gYWxzIEdlaXN0IG5pY2h0IGvkbXBmZW4KLy8gVE9ETzogcHJ1ZWZlbiwgb2IgZGFzIFNldHplbiB1bmQgTG9lc2NoZW4gZGVyIFByb3AgaW4gc2V0X2dob3N0KCkgbmljaHQKLy8gYXVjaCBhdXNyZWljaGVuIHd1ZXJkZS4gSW4gZGVtIEZhbGwgbXVlc3N0ZSBtYW4gYWJlciBQX05PX0FUVEFDSyBhdWNoCi8vIHNwZWljaGVybiwgZGEgUF9HSE9TVCBnZXNwZWljaGVydCB3aXJkLi4uCnN0YXRpYyBtaXhlZCBfcXVlcnlfbm9fYXR0YWNrKCkKewogICAgaWYgKCBRdWVyeVByb3AoUF9HSE9TVCkgKQogICAgICAgIHJldHVybiAxOwoKICAgIHJldHVybiBRdWVyeShQX05PX0FUVEFDSyk7Cn0K