LyoKT3BlbiBBc3NldCBJbXBvcnQgTGlicmFyeSAoYXNzaW1wKQotLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tCgpDb3B5cmlnaHQgKGMpIDIwMDYtMjAxMCwgYXNzaW1wIHRlYW0KQWxsIHJpZ2h0cyByZXNlcnZlZC4KClJlZGlzdHJpYnV0aW9uIGFuZCB1c2Ugb2YgdGhpcyBzb2Z0d2FyZSBpbiBzb3VyY2UgYW5kIGJpbmFyeSBmb3JtcywKd2l0aCBvciB3aXRob3V0IG1vZGlmaWNhdGlvbiwgYXJlIHBlcm1pdHRlZCBwcm92aWRlZCB0aGF0IHRoZQpmb2xsb3dpbmcgY29uZGl0aW9ucyBhcmUgbWV0OgoKKiBSZWRpc3RyaWJ1dGlvbnMgb2Ygc291cmNlIGNvZGUgbXVzdCByZXRhaW4gdGhlIGFib3ZlCiAgY29weXJpZ2h0IG5vdGljZSwgdGhpcyBsaXN0IG9mIGNvbmRpdGlvbnMgYW5kIHRoZQogIGZvbGxvd2luZyBkaXNjbGFpbWVyLgoKKiBSZWRpc3RyaWJ1dGlvbnMgaW4gYmluYXJ5IGZvcm0gbXVzdCByZXByb2R1Y2UgdGhlIGFib3ZlCiAgY29weXJpZ2h0IG5vdGljZSwgdGhpcyBsaXN0IG9mIGNvbmRpdGlvbnMgYW5kIHRoZQogIGZvbGxvd2luZyBkaXNjbGFpbWVyIGluIHRoZSBkb2N1bWVudGF0aW9uIGFuZC9vciBvdGhlcgogIG1hdGVyaWFscyBwcm92aWRlZCB3aXRoIHRoZSBkaXN0cmlidXRpb24uCgoqIE5laXRoZXIgdGhlIG5hbWUgb2YgdGhlIGFzc2ltcCB0ZWFtLCBub3IgdGhlIG5hbWVzIG9mIGl0cwogIGNvbnRyaWJ1dG9ycyBtYXkgYmUgdXNlZCB0byBlbmRvcnNlIG9yIHByb21vdGUgcHJvZHVjdHMKICBkZXJpdmVkIGZyb20gdGhpcyBzb2Z0d2FyZSB3aXRob3V0IHNwZWNpZmljIHByaW9yCiAgd3JpdHRlbiBwZXJtaXNzaW9uIG9mIHRoZSBhc3NpbXAgdGVhbS4KClRISVMgU09GVFdBUkUgSVMgUFJPVklERUQgQlkgVEhFIENPUFlSSUdIVCBIT0xERVJTIEFORCBDT05UUklCVVRPUlMKIkFTIElTIiBBTkQgQU5ZIEVYUFJFU1MgT1IgSU1QTElFRCBXQVJSQU5USUVTLCBJTkNMVURJTkcsIEJVVCBOT1QKTElNSVRFRCBUTywgVEhFIElNUExJRUQgV0FSUkFOVElFUyBPRiBNRVJDSEFOVEFCSUxJVFkgQU5EIEZJVE5FU1MgRk9SCkEgUEFSVElDVUxBUiBQVVJQT1NFIEFSRSBESVNDTEFJTUVELiBJTiBOTyBFVkVOVCBTSEFMTCBUSEUgQ09QWVJJR0hUCk9XTkVSIE9SIENPTlRSSUJVVE9SUyBCRSBMSUFCTEUgRk9SIEFOWSBESVJFQ1QsIElORElSRUNULCBJTkNJREVOVEFMLApTUEVDSUFMLCBFWEVNUExBUlksIE9SIENPTlNFUVVFTlRJQUwgREFNQUdFUyAoSU5DTFVESU5HLCBCVVQgTk9UCkxJTUlURUQgVE8sIFBST0NVUkVNRU5UIE9GIFNVQlNUSVRVVEUgR09PRFMgT1IgU0VSVklDRVM7IExPU1MgT0YgVVNFLApEQVRBLCBPUiBQUk9GSVRTOyBPUiBCVVNJTkVTUyBJTlRFUlJVUFRJT04pIEhPV0VWRVIgQ0FVU0VEIEFORCBPTiBBTlkKVEhFT1JZIE9GIExJQUJJTElUWSwgV0hFVEhFUiBJTiBDT05UUkFDVCwgU1RSSUNUIExJQUJJTElUWSwgT1IgVE9SVAooSU5DTFVESU5HIE5FR0xJR0VOQ0UgT1IgT1RIRVJXSVNFKSBBUklTSU5HIElOIEFOWSBXQVkgT1VUIE9GIFRIRSBVU0UKT0YgVEhJUyBTT0ZUV0FSRSwgRVZFTiBJRiBBRFZJU0VEIE9GIFRIRSBQT1NTSUJJTElUWSBPRiBTVUNIIERBTUFHRS4KCi0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0KKi8KCi8qKiBAZmlsZSAgSUZDQm9vbGVhbi5jcHAKICogIEBicmllZiBJbXBsZW1lbnRzIGEgc3Vic2V0IG9mIElmYyBib29sZWFuIG9wZXJhdGlvbnMKICovCgoKI2lmbmRlZiBBU1NJTVBfQlVJTERfTk9fSUZDX0lNUE9SVEVSCiNpbmNsdWRlICJJRkNVdGlsLmgiCiNpbmNsdWRlICJQb2x5VG9vbHMuaCIKI2luY2x1ZGUgIlByb2Nlc3NIZWxwZXIuaCIKI2luY2x1ZGUgPGFzc2ltcC9EZWZpbmVzLmg+CgojaW5jbHVkZSA8aXRlcmF0b3I+CiNpbmNsdWRlIDx0dXBsZT4KCgpuYW1lc3BhY2UgQXNzaW1wIHsKICAgIG5hbWVzcGFjZSBJRkMgewoKLy8gLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tCi8vIENhbGN1bGF0ZXMgaW50ZXJzZWN0aW9uIGJldHdlZW4gbGluZSBzZWdtZW50IGFuZCBwbGFuZS4gVG8gY2F0Y2ggY29ybmVyIGNhc2VzLCBzcGVjaWZ5IHdoaWNoIHNpZGUgeW91IHByZWZlci4KLy8gVGhlIGZ1bmN0aW9uIHRoZW4gZ2VuZXJhdGVzIGEgaGl0IG9ubHkgaWYgdGhlIGVuZCBpcyBiZXlvbmQgYSBjZXJ0YWluIG1hcmdpbiBpbiB0aGF0IGRpcmVjdGlvbiwgZmlsdGVyaW5nIG91dAovLyAidmVyeSBjbG9zZSB0byBwbGFuZSIgZ2hvc3QgaGl0cyBhcyBsb25nIGFzIHN0YXJ0IGFuZCBlbmQgc3RheSBkaXJlY3RseSBvbiBvciB3aXRoaW4gdGhlIGdpdmVuIHBsYW5lIHNpZGUuCmJvb2wgSW50ZXJzZWN0U2VnbWVudFBsYW5lKGNvbnN0IElmY1ZlY3RvcjMmIHAsY29uc3QgSWZjVmVjdG9yMyYgbiwgY29uc3QgSWZjVmVjdG9yMyYgZTAsCiAgICBjb25zdCBJZmNWZWN0b3IzJiBlMSwgYm9vbCBhc3N1bWVTdGFydE9uV2hpdGVTaWRlLCBJZmNWZWN0b3IzJiBvdXQpCnsKICAgIGNvbnN0IElmY1ZlY3RvcjMgcGRlbHRhID0gZTAgLSBwLCBzZWcgPSBlMSAtIGUwOwogICAgY29uc3QgSWZjRmxvYXQgZG90T25lID0gbipzZWcsIGRvdFR3byA9IC0obipwZGVsdGEpOwoKICAgIC8vIGlmIHNlZ21lbnQgZW5kcyBvbiBwbGFuZSwgZG8gbm90IHJlcG9ydCBhIGhpdC4gV2Ugc3RheSBvbiB0aGF0IHNpZGUgdW50aWwgYSBmb2xsb3dpbmcgc2VnbWVudCBzdGFydGluZyBhdCB0aGlzCiAgICAvLyBwb2ludCBsZWF2ZXMgdGhlIHBsYW5lIHRocm91Z2ggdGhlIG90aGVyIHNpZGUKICAgIGlmKCBzdGQ6OmFicyhkb3RPbmUgKyBkb3RUd28pIDwgMWUtNiApCiAgICAgICAgcmV0dXJuIGZhbHNlOwoKICAgIC8vIGlmIHNlZ21lbnQgc3RhcnRzIG9uIHRoZSBwbGFuZSwgcmVwb3J0IGEgaGl0IG9ubHkgaWYgdGhlIGVuZCBsaWVzIG9uIHRoZSAqb3RoZXIqIHNpZGUKICAgIGlmKCBzdGQ6OmFicyhkb3RUd28pIDwgMWUtNiApCiAgICB7CiAgICAgICAgaWYoIChhc3N1bWVTdGFydE9uV2hpdGVTaWRlICYmIGRvdE9uZSArIGRvdFR3byA8IDFlLTYpIHx8ICghYXNzdW1lU3RhcnRPbldoaXRlU2lkZSAmJiBkb3RPbmUgKyBkb3RUd28gPiAtMWUtNikgKQogICAgICAgIHsKICAgICAgICAgICAgb3V0ID0gZTA7CiAgICAgICAgICAgIHJldHVybiB0cnVlOwogICAgICAgIH0KICAgICAgICBlbHNlCiAgICAgICAgewogICAgICAgICAgICByZXR1cm4gZmFsc2U7CiAgICAgICAgfQogICAgfQoKICAgIC8vIGlnbm9yZSBpZiBzZWdtZW50IGlzIHBhcmFsbGVsIHRvIHBsYW5lIGFuZCBmYXIgYXdheSBmcm9tIGl0IG9uIGVpdGhlciBzaWRlCiAgICAvLyBXYXJuaW5nOiBpZiB0aGVyZSdzIGEgZmV3IHRob3VzYW5kIG9mIHN1Y2ggc2VnbWVudHMgd2hpY2ggc2xvd2x5IGFjY3VtdWxhdGUgYmV5b25kIHRoZSBlcHNpbG9uLCBubyBoaXQgd291bGQgYmUgcmVnaXN0ZXJlZAogICAgaWYoIHN0ZDo6YWJzKGRvdE9uZSkgPCAxZS02ICkKICAgICAgICByZXR1cm4gZmFsc2U7CgogICAgLy8gdCBtdXN0IGJlIGluIFswLi4xXSBpZiB0aGUgaW50ZXJzZWN0aW9uIHBvaW50IGlzIHdpdGhpbiB0aGUgZ2l2ZW4gc2VnbWVudAogICAgY29uc3QgSWZjRmxvYXQgdCA9IGRvdFR3byAvIGRvdE9uZTsKICAgIGlmKCB0ID4gMS4wIHx8IHQgPCAwLjAgKQogICAgICAgIHJldHVybiBmYWxzZTsKCiAgICBvdXQgPSBlMCArIHQqc2VnOwogICAgcmV0dXJuIHRydWU7Cn0KCi8vIC0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLQp2b2lkIEZpbHRlclBvbHlnb24oc3RkOjp2ZWN0b3I8SWZjVmVjdG9yMz4mIHJlc3VsdHBvbHkpCnsKICAgIGlmKCByZXN1bHRwb2x5LnNpemUoKSA8IDMgKQogICAgewogICAgICAgIHJlc3VsdHBvbHkuY2xlYXIoKTsKICAgICAgICByZXR1cm47CiAgICB9CgogICAgSWZjVmVjdG9yMyB2bWluLCB2bWF4OwogICAgQXJyYXlCb3VuZHMocmVzdWx0cG9seS5kYXRhKCksIHN0YXRpY19jYXN0PHVuc2lnbmVkIGludD4ocmVzdWx0cG9seS5zaXplKCkpLCB2bWluLCB2bWF4KTsKCiAgICAvLyBmaWx0ZXIgb3VyIElmY0Zsb2F0IHBvaW50cyAtIHRob3NlIG1heSBoYXBwZW4gaWYgYSBwb2ludCBsaWVzCiAgICAvLyBkaXJlY3RseSBvbiB0aGUgaW50ZXJzZWN0aW9uIGxpbmUgb3IgZGlyZWN0bHkgb24gdGhlIGNsaXBwaW5nIHBsYW5lCiAgICBjb25zdCBJZmNGbG9hdCBlcHNpbG9uID0gKHZtYXggLSB2bWluKS5TcXVhcmVMZW5ndGgoKSAvIDFlNmY7CiAgICBGdXp6eVZlY3RvckNvbXBhcmUgZnooZXBzaWxvbik7CiAgICBzdGQ6OnZlY3RvcjxJZmNWZWN0b3IzPjo6aXRlcmF0b3IgZSA9IHN0ZDo6dW5pcXVlKHJlc3VsdHBvbHkuYmVnaW4oKSwgcmVzdWx0cG9seS5lbmQoKSwgZnopOwoKICAgIGlmKCBlICE9IHJlc3VsdHBvbHkuZW5kKCkgKQogICAgICAgIHJlc3VsdHBvbHkuZXJhc2UoZSwgcmVzdWx0cG9seS5lbmQoKSk7CgogICAgaWYoICFyZXN1bHRwb2x5LmVtcHR5KCkgJiYgZnoocmVzdWx0cG9seS5mcm9udCgpLCByZXN1bHRwb2x5LmJhY2soKSkgKQogICAgICAgIHJlc3VsdHBvbHkucG9wX2JhY2soKTsKfQoKLy8gLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tCnZvaWQgV3JpdGVQb2x5Z29uKHN0ZDo6dmVjdG9yPElmY1ZlY3RvcjM+JiByZXN1bHRwb2x5LCBUZW1wTWVzaCYgcmVzdWx0KQp7CiAgICBGaWx0ZXJQb2x5Z29uKHJlc3VsdHBvbHkpOwoKICAgIGlmKCByZXN1bHRwb2x5LnNpemUoKSA+IDIgKQogICAgewogICAgICAgIHJlc3VsdC52ZXJ0cy5pbnNlcnQocmVzdWx0LnZlcnRzLmVuZCgpLCByZXN1bHRwb2x5LmJlZ2luKCksIHJlc3VsdHBvbHkuZW5kKCkpOwogICAgICAgIHJlc3VsdC52ZXJ0Y250LnB1c2hfYmFjayhzdGF0aWNfY2FzdDx1bnNpZ25lZCBpbnQ+KHJlc3VsdHBvbHkuc2l6ZSgpKSk7CiAgICB9Cn0KCgovLyAtLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0Kdm9pZCBQcm9jZXNzQm9vbGVhbkhhbGZTcGFjZURpZmZlcmVuY2UoY29uc3QgSWZjSGFsZlNwYWNlU29saWQqIGhzLCBUZW1wTWVzaCYgcmVzdWx0LAogICAgY29uc3QgVGVtcE1lc2gmIGZpcnN0X29wZXJhbmQsCiAgICBDb252ZXJzaW9uRGF0YSYgLypjb252Ki8pCnsKICAgIGFpX2Fzc2VydChocyAhPSBOVUxMKTsKCiAgICBjb25zdCBJZmNQbGFuZSogY29uc3QgcGxhbmUgPSBocy0+QmFzZVN1cmZhY2UtPlRvUHRyPElmY1BsYW5lPigpOwogICAgaWYoIXBsYW5lKSB7CiAgICAgICAgSUZDSW1wb3J0ZXI6OkxvZ0Vycm9yKCJleHBlY3RlZCBJZmNQbGFuZSBhcyBiYXNlIHN1cmZhY2UgZm9yIHRoZSBJZmNIYWxmU3BhY2VTb2xpZCIpOwogICAgICAgIHJldHVybjsKICAgIH0KCiAgICAvLyBleHRyYWN0IHBsYW5lIGJhc2UgcG9zaXRpb24gdmVjdG9yIGFuZCBub3JtYWwgdmVjdG9yCiAgICBJZmNWZWN0b3IzIHAsbigwLmYsMC5mLDEuZik7CiAgICBpZiAocGxhbmUtPlBvc2l0aW9uLT5BeGlzKSB7CiAgICAgICAgQ29udmVydERpcmVjdGlvbihuLHBsYW5lLT5Qb3NpdGlvbi0+QXhpcy5HZXQoKSk7CiAgICB9CiAgICBDb252ZXJ0Q2FydGVzaWFuUG9pbnQocCxwbGFuZS0+UG9zaXRpb24tPkxvY2F0aW9uKTsKCiAgICBpZighSXNUcnVlKGhzLT5BZ3JlZW1lbnRGbGFnKSkgewogICAgICAgIG4gKj0gLTEuZjsKICAgIH0KCiAgICAvLyBjbGlwIHRoZSBjdXJyZW50IGNvbnRlbnRzIG9mIGBtZXNob3V0YCBhZ2FpbnN0IHRoZSBwbGFuZSB3ZSBvYnRhaW5lZCBmcm9tIHRoZSBzZWNvbmQgb3BlcmFuZAogICAgY29uc3Qgc3RkOjp2ZWN0b3I8SWZjVmVjdG9yMz4mIGluID0gZmlyc3Rfb3BlcmFuZC52ZXJ0czsKICAgIHN0ZDo6dmVjdG9yPElmY1ZlY3RvcjM+JiBvdXR2ZXJ0ID0gcmVzdWx0LnZlcnRzOwoKICAgIHN0ZDo6dmVjdG9yPHVuc2lnbmVkIGludD46OmNvbnN0X2l0ZXJhdG9yIGJlZ2luID0gZmlyc3Rfb3BlcmFuZC52ZXJ0Y250LmJlZ2luKCksCiAgICAgICAgZW5kID0gZmlyc3Rfb3BlcmFuZC52ZXJ0Y250LmVuZCgpLCBpaXQ7CgogICAgb3V0dmVydC5yZXNlcnZlKGluLnNpemUoKSk7CiAgICByZXN1bHQudmVydGNudC5yZXNlcnZlKGZpcnN0X29wZXJhbmQudmVydGNudC5zaXplKCkpOwoKICAgIHVuc2lnbmVkIGludCB2aWR4ID0gMDsKICAgIGZvcihpaXQgPSBiZWdpbjsgaWl0ICE9IGVuZDsgdmlkeCArPSAqaWl0KyspIHsKCiAgICAgICAgdW5zaWduZWQgaW50IG5ld2NvdW50ID0gMDsKICAgICAgICBib29sIGlzQXRXaGl0ZVNpZGUgPSAoaW5bdmlkeF0gLSBwKSAqIG4gPiAtMWUtNjsKICAgICAgICBmb3IoIHVuc2lnbmVkIGludCBpID0gMDsgaSA8ICppaXQ7ICsraSApIHsKICAgICAgICAgICAgY29uc3QgSWZjVmVjdG9yMyYgZTAgPSBpblt2aWR4ICsgaV0sIGUxID0gaW5bdmlkeCArIChpICsgMSkgJSAqaWl0XTsKCiAgICAgICAgICAgIC8vIGRvZXMgdGhlIG5leHQgc2VnbWVudCBpbnRlcnNlY3QgdGhlIHBsYW5lPwogICAgICAgICAgICBJZmNWZWN0b3IzIGlzZWN0cG9zOwogICAgICAgICAgICBpZiggSW50ZXJzZWN0U2VnbWVudFBsYW5lKHAsIG4sIGUwLCBlMSwgaXNBdFdoaXRlU2lkZSwgaXNlY3Rwb3MpICkgewogICAgICAgICAgICAgICAgaWYoIGlzQXRXaGl0ZVNpZGUgKSB7CiAgICAgICAgICAgICAgICAgICAgLy8gZTAgaXMgb24gdGhlIHJpZ2h0IHNpZGUsIHNvIGtlZXAgaXQKICAgICAgICAgICAgICAgICAgICBvdXR2ZXJ0LnB1c2hfYmFjayhlMCk7CiAgICAgICAgICAgICAgICAgICAgb3V0dmVydC5wdXNoX2JhY2soaXNlY3Rwb3MpOwogICAgICAgICAgICAgICAgICAgIG5ld2NvdW50ICs9IDI7CiAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICBlbHNlIHsKICAgICAgICAgICAgICAgICAgICAvLyBlMCBpcyBvbiB0aGUgd3Jvbmcgc2lkZSwgc28gZHJvcCBpdCBhbmQga2VlcCBlMSBpbnN0ZWFkCiAgICAgICAgICAgICAgICAgICAgb3V0dmVydC5wdXNoX2JhY2soaXNlY3Rwb3MpOwogICAgICAgICAgICAgICAgICAgICsrbmV3Y291bnQ7CiAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICBpc0F0V2hpdGVTaWRlID0gIWlzQXRXaGl0ZVNpZGU7CiAgICAgICAgICAgIH0KICAgICAgICAgICAgZWxzZQogICAgICAgICAgICB7CiAgICAgICAgICAgICAgICBpZiggaXNBdFdoaXRlU2lkZSApIHsKICAgICAgICAgICAgICAgICAgICBvdXR2ZXJ0LnB1c2hfYmFjayhlMCk7CiAgICAgICAgICAgICAgICAgICAgKytuZXdjb3VudDsKICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgfQogICAgICAgIH0KCiAgICAgICAgaWYgKCFuZXdjb3VudCkgewogICAgICAgICAgICBjb250aW51ZTsKICAgICAgICB9CgogICAgICAgIElmY1ZlY3RvcjMgdm1pbix2bWF4OwogICAgICAgIEFycmF5Qm91bmRzKCYqKG91dHZlcnQuZW5kKCktbmV3Y291bnQpLG5ld2NvdW50LHZtaW4sdm1heCk7CgogICAgICAgIC8vIGZpbHRlciBvdXIgSWZjRmxvYXQgcG9pbnRzIC0gdGhvc2UgbWF5IGhhcHBlbiBpZiBhIHBvaW50IGxpZXMKICAgICAgICAvLyBkaXJlY3RseSBvbiB0aGUgaW50ZXJzZWN0aW9uIGxpbmUuIEhvd2V2ZXIsIGR1ZSB0byBJZmNGbG9hdAogICAgICAgIC8vIHByZWNpc2lvbiBhIGJpdHdpc2UgY29tcGFyaXNvbiBpcyBub3QgZmVhc2libGUgdG8gZGV0ZWN0CiAgICAgICAgLy8gdGhpcyBjYXNlLgogICAgICAgIGNvbnN0IElmY0Zsb2F0IGVwc2lsb24gPSAodm1heC12bWluKS5TcXVhcmVMZW5ndGgoKSAvIDFlNmY7CiAgICAgICAgRnV6enlWZWN0b3JDb21wYXJlIGZ6KGVwc2lsb24pOwoKICAgICAgICBzdGQ6OnZlY3RvcjxJZmNWZWN0b3IzPjo6aXRlcmF0b3IgZSA9IHN0ZDo6dW5pcXVlKCBvdXR2ZXJ0LmVuZCgpLW5ld2NvdW50LCBvdXR2ZXJ0LmVuZCgpLCBmeiApOwoKICAgICAgICBpZiAoZSAhPSBvdXR2ZXJ0LmVuZCgpKSB7CiAgICAgICAgICAgIG5ld2NvdW50IC09IHN0YXRpY19jYXN0PHVuc2lnbmVkIGludD4oc3RkOjpkaXN0YW5jZShlLG91dHZlcnQuZW5kKCkpKTsKICAgICAgICAgICAgb3V0dmVydC5lcmFzZShlLG91dHZlcnQuZW5kKCkpOwogICAgICAgIH0KICAgICAgICBpZiAoZnooKiggb3V0dmVydC5lbmQoKS1uZXdjb3VudCksb3V0dmVydC5iYWNrKCkpKSB7CiAgICAgICAgICAgIG91dHZlcnQucG9wX2JhY2soKTsKICAgICAgICAgICAgLS1uZXdjb3VudDsKICAgICAgICB9CiAgICAgICAgaWYobmV3Y291bnQgPiAyKSB7CiAgICAgICAgICAgIHJlc3VsdC52ZXJ0Y250LnB1c2hfYmFjayhuZXdjb3VudCk7CiAgICAgICAgfQogICAgICAgIGVsc2Ugd2hpbGUobmV3Y291bnQtLT4wKSB7CiAgICAgICAgICAgIHJlc3VsdC52ZXJ0cy5wb3BfYmFjaygpOwogICAgICAgIH0KCiAgICB9CiAgICBJRkNJbXBvcnRlcjo6TG9nRGVidWcoImdlbmVyYXRpbmcgQ1NHIGdlb21ldHJ5IGJ5IHBsYW5lIGNsaXBwaW5nIChJZmNCb29sZWFuQ2xpcHBpbmdSZXN1bHQpIik7Cn0KCi8vIC0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLQovLyBDaGVjayBpZiBlMC1lMSBpbnRlcnNlY3RzIGEgc3ViLXNlZ21lbnQgb2YgdGhlIGdpdmVuIGJvdW5kYXJ5IGxpbmUuCi8vIG5vdGU6IHRoaXMgZnVuY3Rpb25zIHdvcmtzIG9uIDNEIHZlY3RvcnMsIGJ1dCBwZXJmb3JtcyBpdHMgaW50ZXJzZWN0aW9uIGNoZWNrcyBzb2xlbHkgaW4geHkuCi8vIE5ldyB2ZXJzaW9uIHRha2VzIHRoZSBzdXBwb3NlZCBpbnNpZGUvb3V0c2lkZSBzdGF0ZSBhcyBhIHBhcmFtZXRlciBhbmQgdHJlYXRzIGNvcm5lciBjYXNlcyBhcyBpZgovLyB0aGUgbGluZSBzdGF5cyBvbiB0aGF0IHNpZGUuIFRoaXMgc2hvdWxkIG1ha2UgY29ybmVyIGNhc2VzIG1vcmUgc3RhYmxlLgovLyBUd28gbWlsbGlvbiBhc3N1bXB0aW9ucyEgQm91bmRhcnkgc2hvdWxkIGhhdmUgYWxsIHogYXQgMC4wLCB3aWxsIGJlIHRyZWF0ZWQgYXMgY2xvc2VkLCBzaG91bGQgbm90IGhhdmUKLy8gc2VnbWVudHMgd2l0aCBsZW5ndGggPDFlLTYsIHNlbGYtaW50ZXJzZWN0aW5nIG1pZ2h0IGJyZWFrIHRoZSBjb3JuZXIgY2FzZSBoYW5kbGluZy4uLiBqdXN0IGRvbid0IGdvIHRoZXJlLCBvaz8KYm9vbCBJbnRlcnNlY3RzQm91bmRhcnlQcm9maWxlKGNvbnN0IElmY1ZlY3RvcjMmIGUwLCBjb25zdCBJZmNWZWN0b3IzJiBlMSwgY29uc3Qgc3RkOjp2ZWN0b3I8SWZjVmVjdG9yMz4mIGJvdW5kYXJ5LAogICAgY29uc3QgYm9vbCBpc1N0YXJ0QXNzdW1lZEluc2lkZSwgc3RkOjp2ZWN0b3I8c3RkOjpwYWlyPHNpemVfdCwgSWZjVmVjdG9yMz4gPiYgaW50ZXJzZWN0X3Jlc3VsdHMsCiAgICBjb25zdCBib29sIGhhbGZPcGVuID0gZmFsc2UpCnsKICAgIGFpX2Fzc2VydChpbnRlcnNlY3RfcmVzdWx0cy5lbXB0eSgpKTsKCiAgICAvLyBkZXRlcm1pbmUgd2luZGluZyBvcmRlciAtIG5lY2Vzc2FyeSB0byBkZXRlY3Qgc2VnbWVudHMgZ29pbmcgImlud2FyZHMiIG9yICJvdXR3YXJkcyIgZnJvbSBhIHBvaW50IGRpcmVjdGx5IG9uIHRoZSBib3JkZXIKICAgIC8vIHBvc2l0aXZlIHN1bSBvZiBhbmdsZXMgbWVhbnMgY2xvY2t3aXNlIG9yZGVyIHdoZW4gbG9va2luZyBkb3duIHRoZSAtWiBheGlzCiAgICBJZmNGbG9hdCB3aW5kaW5nT3JkZXIgPSAwLjA7CiAgICBmb3IoIHNpemVfdCBpID0gMCwgYmNvdW50ID0gYm91bmRhcnkuc2l6ZSgpOyBpIDwgYmNvdW50OyArK2kgKSB7CiAgICAgICAgSWZjVmVjdG9yMyBiMDEgPSBib3VuZGFyeVsoaSArIDEpICUgYmNvdW50XSAtIGJvdW5kYXJ5W2ldOwogICAgICAgIElmY1ZlY3RvcjMgYjEyID0gYm91bmRhcnlbKGkgKyAyKSAlIGJjb3VudF0gLSBib3VuZGFyeVsoaSArIDEpICUgYmNvdW50XTsKICAgICAgICBJZmNWZWN0b3IzIGIxX3NpZGUgPSBJZmNWZWN0b3IzKGIwMS55LCAtYjAxLngsIDAuMCk7IC8vIHJvdGF0ZWQgOTCwIGNsb2Nrd2lzZSBpbiBaIHBsYW5lCiAgICAgICAgLy8gV2FybmluZzogcm91Z2ggZXN0aW1hdGUgb25seS4gQSBjb25jYXZlIHBvbHkgd2l0aCBsb3RzIG9mIHNtYWxsIHNlZ21lbnRzIGVhY2ggZmVhdHVyaW5nIGEgc21hbGwgY291bnRlciByb3RhdGlvbgogICAgICAgIC8vIGNvdWxkIGZvb2wgdGhlIGFjY3VtdWxhdGlvbi4gQ29ycmVjdCBpbXBsZW1lbnRhdGlvbiB3b3VsZCBiZSBzdW0oIGFjb3MoIGIwMSAqIGIyKSAqIHNpZ24oIGIxMiAqIGIxX3NpZGUpKQogICAgICAgIHdpbmRpbmdPcmRlciArPSAoYjFfc2lkZS54KmIxMi54ICsgYjFfc2lkZS55KmIxMi55KTsKICAgIH0KICAgIHdpbmRpbmdPcmRlciA9IHdpbmRpbmdPcmRlciA+IDAuMCA/IDEuMCA6IC0xLjA7CgogICAgY29uc3QgSWZjVmVjdG9yMyBlID0gZTEgLSBlMDsKCiAgICBmb3IoIHNpemVfdCBpID0gMCwgYmNvdW50ID0gYm91bmRhcnkuc2l6ZSgpOyBpIDwgYmNvdW50OyArK2kgKSB7CiAgICAgICAgLy8gYm91bmRhcnkgc2VnbWVudCBpOiBiMC1iMQogICAgICAgIGNvbnN0IElmY1ZlY3RvcjMmIGIwID0gYm91bmRhcnlbaV07CiAgICAgICAgY29uc3QgSWZjVmVjdG9yMyYgYjEgPSBib3VuZGFyeVsoaSArIDEpICUgYmNvdW50XTsKICAgICAgICBJZmNWZWN0b3IzIGIgPSBiMSAtIGIwOwoKICAgICAgICAvLyBzZWdtZW50LXNlZ21lbnQgaW50ZXJzZWN0aW9uCiAgICAgICAgLy8gc29sdmUgYjAgKyBiKnMgPSBlMCArIGUqdCBmb3IgKHMsdCkKICAgICAgICBjb25zdCBJZmNGbG9hdCBkZXQgPSAoLWIueCAqIGUueSArIGUueCAqIGIueSk7CiAgICAgICAgaWYoIHN0ZDo6YWJzKGRldCkgPCAxZS02ICkgewogICAgICAgICAgICAvLyBubyBzb2x1dGlvbnMgKHBhcmFsbGVsIGxpbmVzKQogICAgICAgICAgICBjb250aW51ZTsKICAgICAgICB9CiAgICAgICAgSWZjRmxvYXQgYl9zcWxlbl9pbnYgPSAxLjAgLyBiLlNxdWFyZUxlbmd0aCgpOwoKICAgICAgICBjb25zdCBJZmNGbG9hdCB4ID0gYjAueCAtIGUwLng7CiAgICAgICAgY29uc3QgSWZjRmxvYXQgeSA9IGIwLnkgLSBlMC55OwogICAgICAgIGNvbnN0IElmY0Zsb2F0IHMgPSAoeCplLnkgLSBlLngqeSkgLyBkZXQ7IC8vIHNjYWxlIGFsb25nIGJvdW5kYXJ5IGVkZ2UKICAgICAgICBjb25zdCBJZmNGbG9hdCB0ID0gKHgqYi55IC0gYi54KnkpIC8gZGV0OyAvLyBzY2FsZSBhbG9uZyBnaXZlbiBzZWdtZW50CiAgICAgICAgY29uc3QgSWZjVmVjdG9yMyBwID0gZTAgKyBlKnQ7CiNpZmRlZiBBU1NJTVBfQlVJTERfREVCVUcKICAgICAgICBjb25zdCBJZmNWZWN0b3IzIGNoZWNrID0gYjAgKyBiKnMgLSBwOwogICAgICAgIGFpX2Fzc2VydCgoSWZjVmVjdG9yMihjaGVjay54LCBjaGVjay55KSkuU3F1YXJlTGVuZ3RoKCkgPCAxZS01KTsKI2VuZGlmCgogICAgICAgIC8vIGFsc28gY2FsY3VsYXRlIHRoZSBkaXN0YW5jZSBvZiBlMCBhbmQgZTEgdG8gdGhlIHNlZ21lbnQuIFdlIG5lZWQgdG8gZGV0ZWN0IHRoZSAic3RhcnRzIGRpcmVjdGx5IG9uIHNlZ21lbnQiCiAgICAgICAgLy8gYW5kICJlbmRzIGRpcmVjdGx5IGF0IHNlZ21lbnQiIGNhc2VzCiAgICAgICAgYm9vbCBzdGFydHNBdFNlZ21lbnQsIGVuZHNBdFNlZ21lbnQ7CiAgICAgICAgewogICAgICAgICAgICAvLyBjYWxjdWxhdGUgY2xvc2VzdCBwb2ludCB0byBlYWNoIGVuZCBvbiB0aGUgc2VnbWVudCwgY2xhbXAgdGhhdCBwb2ludCB0byB0aGUgc2VnbWVudCdzIGxlbmd0aCwgdGhlbiBjaGVjawogICAgICAgICAgICAvLyBkaXN0YW5jZSB0byB0aGF0IHBvaW50LiBUaGlzIGFwcHJvYWNoIGlzIGxpa2UgdGVzdGluZyBpZiBlMCBpcyBpbnNpZGUgYSBjYXBwZWQgY3lsaW5kZXIuCiAgICAgICAgICAgIElmY0Zsb2F0IGV0MCA9IChiLngqKGUwLnggLSBiMC54KSArIGIueSooZTAueSAtIGIwLnkpKSAqIGJfc3FsZW5faW52OwogICAgICAgICAgICBJZmNWZWN0b3IzIGNsb3Nlc3RQb3NUb0UwT25Cb3VuZGFyeSA9IGIwICsgc3RkOjptYXgoSWZjRmxvYXQoMC4wKSwgc3RkOjptaW4oSWZjRmxvYXQoMS4wKSwgZXQwKSkgKiBiOwogICAgICAgICAgICBzdGFydHNBdFNlZ21lbnQgPSAoY2xvc2VzdFBvc1RvRTBPbkJvdW5kYXJ5IC0gSWZjVmVjdG9yMyhlMC54LCBlMC55LCAwLjApKS5TcXVhcmVMZW5ndGgoKSA8IDFlLTEyOwogICAgICAgICAgICBJZmNGbG9hdCBldDEgPSAoYi54KihlMS54IC0gYjAueCkgKyBiLnkqKGUxLnkgLSBiMC55KSkgKiBiX3NxbGVuX2ludjsKICAgICAgICAgICAgSWZjVmVjdG9yMyBjbG9zZXN0UG9zVG9FMU9uQm91bmRhcnkgPSBiMCArIHN0ZDo6bWF4KElmY0Zsb2F0KDAuMCksIHN0ZDo6bWluKElmY0Zsb2F0KDEuMCksIGV0MSkpICogYjsKICAgICAgICAgICAgZW5kc0F0U2VnbWVudCA9IChjbG9zZXN0UG9zVG9FMU9uQm91bmRhcnkgLSBJZmNWZWN0b3IzKGUxLngsIGUxLnksIDAuMCkpLlNxdWFyZUxlbmd0aCgpIDwgMWUtMTI7CiAgICAgICAgfQoKICAgICAgICAvLyBMaW5lIHNlZ21lbnQgZW5kcyBhdCBib3VuZGFyeSAtPiBpZ25vcmUgYW55IGhpdCwgaXQgd2lsbCBiZSBoYW5kbGVkIGJ5IHBvc3NpYmx5IGZvbGxvd2luZyBzZWdtZW50cwogICAgICAgIGlmKCBlbmRzQXRTZWdtZW50ICYmICFoYWxmT3BlbiApCiAgICAgICAgICAgIGNvbnRpbnVlOwoKICAgICAgICAvLyBMaW5lIHNlZ21lbnQgc3RhcnRzIGF0IGJvdW5kYXJ5IC0+IGdlbmVyYXRlIGEgaGl0IG9ubHkgaWYgZm9sbG93aW5nIHRoYXQgbGluZSB3b3VsZCBjaGFuZ2UgdGhlIElOU0lERS9PVVRTSURFCiAgICAgICAgLy8gc3RhdGUuIFRoaXMgc2hvdWxkIGNhdGNoIHRoZSBjYXNlIHdoZXJlIGEgY29ubmVjdGVkIHNldCBvZiBzZWdtZW50cyBoYXMgYSBwb2ludCBkaXJlY3RseSBvbiB0aGUgYm91bmRhcnksCiAgICAgICAgLy8gb25lIHNlZ21lbnQgbm90IGhpdHRpbmcgaXQgYmVjYXVzZSBpdCBlbmRzIHRoZXJlIGFuZCB0aGUgbmV4dCBzZWdtZW50IG5vdCBoaXR0aW5nIGl0IGJlY2F1c2UgaXQgc3RhcnRzIHRoZXJlCiAgICAgICAgLy8gU2hvdWxkIE5PVCBnZW5lcmF0ZSBhIGhpdCBpZiB0aGUgc2VnbWVudCBvbmx5IHRvdWNoZXMgdGhlIGJvdW5kYXJ5IGJ1dCB0dXJucyBhcm91bmQgYW5kIHN0YXlzIGluc2lkZS4KICAgICAgICBpZiggc3RhcnRzQXRTZWdtZW50ICkKICAgICAgICB7CiAgICAgICAgICAgIElmY1ZlY3RvcjMgaW5zaWRlX2RpciA9IElmY1ZlY3RvcjMoYi55LCAtYi54LCAwLjApICogd2luZGluZ09yZGVyOwogICAgICAgICAgICBib29sIGlzR29pbmdJbnNpZGUgPSAoaW5zaWRlX2RpciAqIGUpID4gMC4wOwogICAgICAgICAgICBpZiggaXNHb2luZ0luc2lkZSA9PSBpc1N0YXJ0QXNzdW1lZEluc2lkZSApCiAgICAgICAgICAgICAgICBjb250aW51ZTsKCiAgICAgICAgICAgIC8vIG9ubHkgaW5zZXJ0IHRoZSBwb2ludCBpbnRvIHRoZSBsaXN0IGlmIGl0IGlzIHN1ZmZpY2llbnRseSBmYXIgYXdheSBmcm9tIHRoZSBwcmV2aW91cyBpbnRlcnNlY3Rpb24gcG9pbnQuCiAgICAgICAgICAgIC8vIFRoaXMgd2F5LCB3ZSBhdm9pZCBkdXBsaWNhdGUgZGV0ZWN0aW9uIGlmIHRoZSBpbnRlcnNlY3Rpb24gaXMgZGlyZWN0bHkgb24gdGhlIHZlcnRleCBiZXR3ZWVuIHR3byBzZWdtZW50cy4KICAgICAgICAgICAgaWYoICFpbnRlcnNlY3RfcmVzdWx0cy5lbXB0eSgpICYmIGludGVyc2VjdF9yZXN1bHRzLmJhY2soKS5maXJzdCA9PSBpIC0gMSApCiAgICAgICAgICAgIHsKICAgICAgICAgICAgICAgIGNvbnN0IElmY1ZlY3RvcjMgZGlmZiA9IGludGVyc2VjdF9yZXN1bHRzLmJhY2soKS5zZWNvbmQgLSBlMDsKICAgICAgICAgICAgICAgIGlmKCBJZmNWZWN0b3IyKGRpZmYueCwgZGlmZi55KS5TcXVhcmVMZW5ndGgoKSA8IDFlLTEwICkKICAgICAgICAgICAgICAgICAgICBjb250aW51ZTsKICAgICAgICAgICAgfQogICAgICAgICAgICBpbnRlcnNlY3RfcmVzdWx0cy5wdXNoX2JhY2soc3RkOjptYWtlX3BhaXIoaSwgZTApKTsKICAgICAgICAgICAgY29udGludWU7CiAgICAgICAgfQoKICAgICAgICAvLyBmb3IgYSB2YWxpZCBpbnRlcnNlY3Rpb24sIHMgYW5kIHQgc2hvdWxkIGJlIGluIHJhbmdlIFswLDFdLiBJbmNsdWRpbmcgYSBiaXQgb2YgZXBzaWxvbiBvbiBzLCBwb3RlbnRpYWwgZG91YmxlCiAgICAgICAgLy8gaGl0cyBvbiB0d28gY29uc2VjdXRpdmUgYm91bmRhcnkgc2VnbWVudHMgYXJlIGZpbHRlcmVkCiAgICAgICAgaWYoIHMgPj0gLTFlLTYgKiBiX3NxbGVuX2ludiAmJiBzIDw9IDEuMCArIDFlLTYqYl9zcWxlbl9pbnYgJiYgdCA+PSAwLjAgJiYgKHQgPD0gMS4wIHx8IGhhbGZPcGVuKSApCiAgICAgICAgewogICAgICAgICAgICAvLyBvbmx5IGluc2VydCB0aGUgcG9pbnQgaW50byB0aGUgbGlzdCBpZiBpdCBpcyBzdWZmaWNpZW50bHkgZmFyIGF3YXkgZnJvbSB0aGUgcHJldmlvdXMgaW50ZXJzZWN0aW9uIHBvaW50LgogICAgICAgICAgICAvLyBUaGlzIHdheSwgd2UgYXZvaWQgZHVwbGljYXRlIGRldGVjdGlvbiBpZiB0aGUgaW50ZXJzZWN0aW9uIGlzIGRpcmVjdGx5IG9uIHRoZSB2ZXJ0ZXggYmV0d2VlbiB0d28gc2VnbWVudHMuCiAgICAgICAgICAgIGlmKCAhaW50ZXJzZWN0X3Jlc3VsdHMuZW1wdHkoKSAmJiBpbnRlcnNlY3RfcmVzdWx0cy5iYWNrKCkuZmlyc3QgPT0gaSAtIDEgKQogICAgICAgICAgICB7CiAgICAgICAgICAgICAgICBjb25zdCBJZmNWZWN0b3IzIGRpZmYgPSBpbnRlcnNlY3RfcmVzdWx0cy5iYWNrKCkuc2Vjb25kIC0gcDsKICAgICAgICAgICAgICAgIGlmKCBJZmNWZWN0b3IyKGRpZmYueCwgZGlmZi55KS5TcXVhcmVMZW5ndGgoKSA8IDFlLTEwICkKICAgICAgICAgICAgICAgICAgICBjb250aW51ZTsKICAgICAgICAgICAgfQogICAgICAgICAgICBpbnRlcnNlY3RfcmVzdWx0cy5wdXNoX2JhY2soc3RkOjptYWtlX3BhaXIoaSwgcCkpOwogICAgICAgIH0KICAgIH0KCiAgICByZXR1cm4gIWludGVyc2VjdF9yZXN1bHRzLmVtcHR5KCk7Cn0KCgovLyAtLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0KLy8gbm90ZTogdGhpcyBmdW5jdGlvbnMgd29ya3Mgb24gM0QgdmVjdG9ycywgYnV0IHBlcmZvcm1zIGl0cyBpbnRlcnNlY3Rpb24gY2hlY2tzIHNvbGVseSBpbiB4eS4KYm9vbCBQb2ludEluUG9seShjb25zdCBJZmNWZWN0b3IzJiBwLCBjb25zdCBzdGQ6OnZlY3RvcjxJZmNWZWN0b3IzPiYgYm91bmRhcnkpCnsKICAgIC8vIGV2ZW4tb2RkIGFsZ29yaXRobTogdGFrZSBhIHJhbmRvbSB2ZWN0b3IgdGhhdCBleHRlbmRzIGZyb20gcCB0byBpbmZpbml0ZQogICAgLy8gYW5kIGNvdW50cyBob3cgbWFueSB0aW1lcyBpdCBpbnRlcnNlY3RzIGVkZ2VzIG9mIHRoZSBib3VuZGFyeS4KICAgIC8vIGJlY2F1c2UgY2hlY2tpbmcgZm9yIHNlZ21lbnQgaW50ZXJzZWN0aW9ucyBpcyBwcm9uZSB0byBudW1lcmljIGluYWNjdXJhY2llcwogICAgLy8gb3IgZG91YmxlIGRldGVjdGlvbnMgKGkuZS4gd2hlbiBoaXR0aW5nIG11bHRpcGxlIGFkamFjZW50IHNlZ21lbnRzIGF0IHRoZWlyCiAgICAvLyBzaGFyZWQgdmVydGljZXMpIHdlIGRvIGl0IHRocmljZSB3aXRoIGRpZmZlcmVudCByYXlzIGFuZCB2b3RlIG9uIGl0LgoKICAgIC8vIHRoZSBldmVuLW9kZCBhbGdvcml0aG0gZG9lc24ndCB3b3JrIGZvciBwb2ludHMgd2hpY2ggbGllIGRpcmVjdGx5IG9uCiAgICAvLyB0aGUgYm9yZGVyIG9mIHRoZSBwb2x5Z29uLiBJZiBhbnkgb2Ygb3VyIGF0dGVtcHRzIHByb2R1Y2VzIHRoaXMgcmVzdWx0LAogICAgLy8gd2UgcmV0dXJuIGZhbHNlIGltbWVkaWF0ZWx5LgoKICAgIHN0ZDo6dmVjdG9yPHN0ZDo6cGFpcjxzaXplX3QsIElmY1ZlY3RvcjM+ID4gaW50ZXJzZWN0ZWRfYm91bmRhcnk7CiAgICBzaXplX3Qgdm90ZXMgPSAwOwoKICAgIEludGVyc2VjdHNCb3VuZGFyeVByb2ZpbGUocCwgcCArIElmY1ZlY3RvcjMoMS4wLCAwLCAwKSwgYm91bmRhcnksIHRydWUsIGludGVyc2VjdGVkX2JvdW5kYXJ5LCB0cnVlKTsKICAgIHZvdGVzICs9IGludGVyc2VjdGVkX2JvdW5kYXJ5LnNpemUoKSAlIDI7CgogICAgaW50ZXJzZWN0ZWRfYm91bmRhcnkuY2xlYXIoKTsKICAgIEludGVyc2VjdHNCb3VuZGFyeVByb2ZpbGUocCwgcCArIElmY1ZlY3RvcjMoMCwgMS4wLCAwKSwgYm91bmRhcnksIHRydWUsIGludGVyc2VjdGVkX2JvdW5kYXJ5LCB0cnVlKTsKICAgIHZvdGVzICs9IGludGVyc2VjdGVkX2JvdW5kYXJ5LnNpemUoKSAlIDI7CgogICAgaW50ZXJzZWN0ZWRfYm91bmRhcnkuY2xlYXIoKTsKICAgIEludGVyc2VjdHNCb3VuZGFyeVByb2ZpbGUocCwgcCArIElmY1ZlY3RvcjMoMC42LCAtMC42LCAwLjApLCBib3VuZGFyeSwgdHJ1ZSwgaW50ZXJzZWN0ZWRfYm91bmRhcnksIHRydWUpOwogICAgdm90ZXMgKz0gaW50ZXJzZWN0ZWRfYm91bmRhcnkuc2l6ZSgpICUgMjsKCiAgICByZXR1cm4gdm90ZXMgPiAxOwp9CgoKLy8gLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tCnZvaWQgUHJvY2Vzc1BvbHlnb25hbEJvdW5kZWRCb29sZWFuSGFsZlNwYWNlRGlmZmVyZW5jZShjb25zdCBJZmNQb2x5Z29uYWxCb3VuZGVkSGFsZlNwYWNlKiBocywgVGVtcE1lc2gmIHJlc3VsdCwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNvbnN0IFRlbXBNZXNoJiBmaXJzdF9vcGVyYW5kLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgQ29udmVyc2lvbkRhdGEmIGNvbnYpCnsKICAgIGFpX2Fzc2VydChocyAhPSBOVUxMKTsKCiAgICBjb25zdCBJZmNQbGFuZSogY29uc3QgcGxhbmUgPSBocy0+QmFzZVN1cmZhY2UtPlRvUHRyPElmY1BsYW5lPigpOwogICAgaWYoIXBsYW5lKSB7CiAgICAgICAgSUZDSW1wb3J0ZXI6OkxvZ0Vycm9yKCJleHBlY3RlZCBJZmNQbGFuZSBhcyBiYXNlIHN1cmZhY2UgZm9yIHRoZSBJZmNIYWxmU3BhY2VTb2xpZCIpOwogICAgICAgIHJldHVybjsKICAgIH0KCiAgICAvLyBleHRyYWN0IHBsYW5lIGJhc2UgcG9zaXRpb24gdmVjdG9yIGFuZCBub3JtYWwgdmVjdG9yCiAgICBJZmNWZWN0b3IzIHAsbigwLmYsMC5mLDEuZik7CiAgICBpZiAocGxhbmUtPlBvc2l0aW9uLT5BeGlzKSB7CiAgICAgICAgQ29udmVydERpcmVjdGlvbihuLHBsYW5lLT5Qb3NpdGlvbi0+QXhpcy5HZXQoKSk7CiAgICB9CiAgICBDb252ZXJ0Q2FydGVzaWFuUG9pbnQocCxwbGFuZS0+UG9zaXRpb24tPkxvY2F0aW9uKTsKCiAgICBpZighSXNUcnVlKGhzLT5BZ3JlZW1lbnRGbGFnKSkgewogICAgICAgIG4gKj0gLTEuZjsKICAgIH0KCiAgICBuLk5vcm1hbGl6ZSgpOwoKICAgIC8vIG9idGFpbiB0aGUgcG9seWdvbmFsIGJvdW5kaW5nIHZvbHVtZQogICAgc3RkOjpzaGFyZWRfcHRyPFRlbXBNZXNoPiBwcm9maWxlID0gc3RkOjpzaGFyZWRfcHRyPFRlbXBNZXNoPihuZXcgVGVtcE1lc2goKSk7CiAgICBpZighUHJvY2Vzc0N1cnZlKGhzLT5Qb2x5Z29uYWxCb3VuZGFyeSwgKnByb2ZpbGUuZ2V0KCksIGNvbnYpKSB7CiAgICAgICAgSUZDSW1wb3J0ZXI6OkxvZ0Vycm9yKCJleHBlY3RlZCB2YWxpZCBwb2x5bGluZSBmb3IgYm91bmRhcnkgb2YgYm9vbGVhbiBoYWxmc3BhY2UiKTsKICAgICAgICByZXR1cm47CiAgICB9CgogICAgLy8gZGV0ZXJtaW5lIHdpbmRpbmcgb3JkZXIgYnkgY2FsY3VsYXRpbmcgdGhlIG5vcm1hbC4KICAgIElmY1ZlY3RvcjMgcHJvZmlsZU5vcm1hbCA9IFRlbXBNZXNoOjpDb21wdXRlUG9seWdvbk5vcm1hbChwcm9maWxlLT52ZXJ0cy5kYXRhKCksIHByb2ZpbGUtPnZlcnRzLnNpemUoKSk7CgogICAgSWZjTWF0cml4NCBwcm9qX2ludjsKICAgIENvbnZlcnRBeGlzUGxhY2VtZW50KHByb2pfaW52LGhzLT5Qb3NpdGlvbik7CgogICAgLy8gYW5kIG1hcCBldmVyeXRoaW5nIGludG8gYSBwbGFuZSBjb29yZGluYXRlIHNwYWNlIHNvIGFsbCBpbnRlcnNlY3Rpb24KICAgIC8vIHRlc3RzIGNhbiBiZSBkb25lIGluIDJEIHNwYWNlLgogICAgSWZjTWF0cml4NCBwcm9qID0gcHJval9pbnY7CiAgICBwcm9qLkludmVyc2UoKTsKCiAgICAvLyBjbGlwIHRoZSBjdXJyZW50IGNvbnRlbnRzIG9mIGBtZXNob3V0YCBhZ2FpbnN0IHRoZSBwbGFuZSB3ZSBvYnRhaW5lZCBmcm9tIHRoZSBzZWNvbmQgb3BlcmFuZAogICAgY29uc3Qgc3RkOjp2ZWN0b3I8SWZjVmVjdG9yMz4mIGluID0gZmlyc3Rfb3BlcmFuZC52ZXJ0czsKICAgIHN0ZDo6dmVjdG9yPElmY1ZlY3RvcjM+JiBvdXR2ZXJ0ID0gcmVzdWx0LnZlcnRzOwogICAgc3RkOjp2ZWN0b3I8dW5zaWduZWQgaW50PiYgb3V0dmVydGNudCA9IHJlc3VsdC52ZXJ0Y250OwoKICAgIG91dHZlcnQucmVzZXJ2ZShpbi5zaXplKCkpOwogICAgb3V0dmVydGNudC5yZXNlcnZlKGZpcnN0X29wZXJhbmQudmVydGNudC5zaXplKCkpOwoKICAgIHVuc2lnbmVkIGludCB2aWR4ID0gMDsKICAgIHN0ZDo6dmVjdG9yPHVuc2lnbmVkIGludD46OmNvbnN0X2l0ZXJhdG9yIGJlZ2luID0gZmlyc3Rfb3BlcmFuZC52ZXJ0Y250LmJlZ2luKCk7CiAgICBzdGQ6OnZlY3Rvcjx1bnNpZ25lZCBpbnQ+Ojpjb25zdF9pdGVyYXRvciBlbmQgPSBmaXJzdF9vcGVyYW5kLnZlcnRjbnQuZW5kKCk7CiAgICBzdGQ6OnZlY3Rvcjx1bnNpZ25lZCBpbnQ+Ojpjb25zdF9pdGVyYXRvciBpaXQ7CiAgICBmb3IoIGlpdCA9IGJlZ2luOyBpaXQgIT0gZW5kOyB2aWR4ICs9ICppaXQrKyApCiAgICB7CiAgICAgICAgLy8gT3VyIG5ldyBhcHByb2FjaDogd2UgY3V0IHRoZSBwb2x5IGFsb25nIHRoZSBwbGFuZSwgdGhlbiB3ZSBpbnRlcnNlY3QgdGhlIHBhcnQgb24gdGhlIGJsYWNrIHNpZGUgb2YgdGhlIHBsYW5lCiAgICAgICAgLy8gYWdhaW5zdCB0aGUgYm91bmRpbmcgcG9seWdvbi4gQWxsIHRoZSB3aGl0ZSBwYXJ0cywgYW5kIHRoZSBibGFjayBwYXJ0IG91dHNpZGUgdGhlIGJvdW5kYXJ5IHBvbHlnb24sIGFyZSBrZXB0LgogICAgICAgIHN0ZDo6dmVjdG9yPElmY1ZlY3RvcjM+IHdoaXRlc2lkZSwgYmxhY2tzaWRlOwoKICAgICAgICB7CiAgICAgICAgICAgIGNvbnN0IElmY1ZlY3RvcjMqIHNyY1ZlcnRpY2VzID0gJmluW3ZpZHhdOwogICAgICAgICAgICBjb25zdCBzaXplX3Qgc3JjVnR4Q291bnQgPSAqaWl0OwogICAgICAgICAgICBpZiggc3JjVnR4Q291bnQgPT0gMCApCiAgICAgICAgICAgICAgICBjb250aW51ZTsKCiAgICAgICAgICAgIElmY1ZlY3RvcjMgcG9seU5vcm1hbCA9IFRlbXBNZXNoOjpDb21wdXRlUG9seWdvbk5vcm1hbChzcmNWZXJ0aWNlcywgc3JjVnR4Q291bnQsIHRydWUpOwoKICAgICAgICAgICAgLy8gaWYgdGhlIHBvbHkgaXMgcGFyYWxsZWwgdG8gdGhlIHBsYW5lLCBwdXQgaXQgY29tcGxldGVseSBvbiB0aGUgYmxhY2sgb3Igd2hpdGUgc2lkZQogICAgICAgICAgICBpZiggc3RkOjphYnMocG9seU5vcm1hbCAqIG4pID4gMC45OTk5ICkKICAgICAgICAgICAgewogICAgICAgICAgICAgICAgYm9vbCBpc09uV2hpdGVTaWRlID0gKHNyY1ZlcnRpY2VzWzBdIC0gcCkgKiBuID4gLTFlLTY7CiAgICAgICAgICAgICAgICBzdGQ6OnZlY3RvcjxJZmNWZWN0b3IzPiYgdGFyZ2V0U2lkZSA9IGlzT25XaGl0ZVNpZGUgPyB3aGl0ZXNpZGUgOiBibGFja3NpZGU7CiAgICAgICAgICAgICAgICB0YXJnZXRTaWRlLmluc2VydCh0YXJnZXRTaWRlLmVuZCgpLCBzcmNWZXJ0aWNlcywgc3JjVmVydGljZXMgKyBzcmNWdHhDb3VudCk7CiAgICAgICAgICAgIH0KICAgICAgICAgICAgZWxzZQogICAgICAgICAgICB7CiAgICAgICAgICAgICAgICAvLyBvdGhlcndpc2Ugc3RhcnQgYnVpbGRpbmcgb25lIHBvbHlnb24gZm9yIGVhY2ggc2lkZS4gV2hlbmV2ZXIgdGhlIGN1cnJlbnQgbGluZSBzZWdtZW50IGludGVyc2VjdHMgdGhlIHBsYW5lCiAgICAgICAgICAgICAgICAvLyB3ZSBwdXQgYSBwb2ludCB0aGVyZSBhcyBhbiBlbmQgb2YgdGhlIGN1cnJlbnQgc2VnbWVudC4gVGhlbiB3ZSBzd2l0Y2ggdG8gdGhlIG90aGVyIHNpZGUsIHB1dCBhIHBvaW50IHRoZXJlLCB0b28sCiAgICAgICAgICAgICAgICAvLyBhcyBhIGJlZ2lubmluZyBvZiB0aGUgY3VycmVudCBzZWdtZW50LCBhbmQgc2ltcGx5IGNvbnRpbnVlIGFjY3VtdWxhdGluZyB2ZXJ0aWNlcy4KICAgICAgICAgICAgICAgIGJvb2wgaXNDdXJyZW50bHlPbldoaXRlU2lkZSA9ICgoc3JjVmVydGljZXNbMF0pIC0gcCkgKiBuID4gLTFlLTY7CiAgICAgICAgICAgICAgICBmb3IoIHNpemVfdCBhID0gMDsgYSA8IHNyY1Z0eENvdW50OyArK2EgKQogICAgICAgICAgICAgICAgewogICAgICAgICAgICAgICAgICAgIElmY1ZlY3RvcjMgZTAgPSBzcmNWZXJ0aWNlc1thXTsKICAgICAgICAgICAgICAgICAgICBJZmNWZWN0b3IzIGUxID0gc3JjVmVydGljZXNbKGEgKyAxKSAlIHNyY1Z0eENvdW50XTsKICAgICAgICAgICAgICAgICAgICBJZmNWZWN0b3IzIGVpOwoKICAgICAgICAgICAgICAgICAgICAvLyBwdXQgc3RhcnRpbmcgcG9pbnQgdG8gdGhlIGN1cnJlbnQgbWVzaAogICAgICAgICAgICAgICAgICAgIHN0ZDo6dmVjdG9yPElmY1ZlY3RvcjM+JiB0cmd0ID0gaXNDdXJyZW50bHlPbldoaXRlU2lkZSA/IHdoaXRlc2lkZSA6IGJsYWNrc2lkZTsKICAgICAgICAgICAgICAgICAgICB0cmd0LnB1c2hfYmFjayhzcmNWZXJ0aWNlc1thXSk7CgogICAgICAgICAgICAgICAgICAgIC8vIGlmIHRoZXJlJ3MgYW4gaW50ZXJzZWN0aW9uLCBwdXQgYW4gZW5kIHZlcnRleCB0aGVyZSwgc3dpdGNoIHRvIHRoZSBvdGhlciBzaWRlJ3MgbWVzaCwKICAgICAgICAgICAgICAgICAgICAvLyBhbmQgYWRkIGEgc3RhcnRpbmcgdmVydGV4IHRoZXJlLCB0b28KICAgICAgICAgICAgICAgICAgICBib29sIGlzUGxhbmVIaXQgPSBJbnRlcnNlY3RTZWdtZW50UGxhbmUocCwgbiwgZTAsIGUxLCBpc0N1cnJlbnRseU9uV2hpdGVTaWRlLCBlaSk7CiAgICAgICAgICAgICAgICAgICAgaWYoIGlzUGxhbmVIaXQgKQogICAgICAgICAgICAgICAgICAgIHsKICAgICAgICAgICAgICAgICAgICAgICAgaWYoIHRyZ3QuZW1wdHkoKSB8fCAodHJndC5iYWNrKCkgLSBlaSkuU3F1YXJlTGVuZ3RoKCkgPiAxZS0xMiApCiAgICAgICAgICAgICAgICAgICAgICAgICAgICB0cmd0LnB1c2hfYmFjayhlaSk7CiAgICAgICAgICAgICAgICAgICAgICAgIGlzQ3VycmVudGx5T25XaGl0ZVNpZGUgPSAhaXNDdXJyZW50bHlPbldoaXRlU2lkZTsKICAgICAgICAgICAgICAgICAgICAgICAgc3RkOjp2ZWN0b3I8SWZjVmVjdG9yMz4mIG5ld3RyZ3QgPSBpc0N1cnJlbnRseU9uV2hpdGVTaWRlID8gd2hpdGVzaWRlIDogYmxhY2tzaWRlOwogICAgICAgICAgICAgICAgICAgICAgICBuZXd0cmd0LnB1c2hfYmFjayhlaSk7CiAgICAgICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICAgfQogICAgICAgICAgICB9CiAgICAgICAgfQoKICAgICAgICAvLyB0aGUgcGFydCBvbiB0aGUgd2hpdGUgc2lkZSBjYW4gYmUgd3JpdHRlbiBpbnRvIHRoZSB0YXJnZXQgbWVzaCByaWdodCBhd2F5CiAgICAgICAgV3JpdGVQb2x5Z29uKHdoaXRlc2lkZSwgcmVzdWx0KTsKCiAgICAgICAgLy8gVGhlIGJsYWNrIHBhcnQgaXMgdGhlIHBpZWNlIHdlIG5lZWQgdG8gZ2V0IHJpZCBvZiwgYnV0IG9ubHkgdGhlIHBhcnQgb2YgaXQgd2l0aGluIHRoZSBib3VuZGFyeSBwb2x5Z29uLgogICAgICAgIC8vIFNvIHdlIG5vdyBuZWVkIHRvIGNvbnN0cnVjdCBhbGwgdGhlIHBvbHlnb25zIHRoYXQgcmVzdWx0IGZyb20gQmxhY2tTaWRlUG9seSBtaW51cyBCb3VuZGFyeVBvbHkuCiAgICAgICAgRmlsdGVyUG9seWdvbihibGFja3NpZGUpOwoKICAgICAgICAvLyBDb21wbGljYXRlZCwgSUkuIFdlIHJ1biBhbG9uZyB0aGUgcG9seWdvbi4gYSkgV2hlbiB3ZSdyZSBpbnNpZGUgdGhlIGJvdW5kYXJ5LCB3ZSBydW4gb24gdW50aWwgd2UgaGl0IGFuCiAgICAgICAgLy8gaW50ZXJzZWN0aW9uLCB3aGljaCBtZWFucyB3ZSdyZSBsZWF2aW5nIGl0LiBXZSB0aGVuIHN0YXJ0IGEgbmV3IG91dCBwb2x5IHRoZXJlLiBiKSBXaGVuIHdlJ3JlIG91dHNpZGUgdGhlCiAgICAgICAgLy8gYm91bmRhcnksIHdlIHN0YXJ0IGNvbGxlY3RpbmcgdmVydGljZXMgdW50aWwgd2UgaGl0IGFuIGludGVyc2VjdGlvbiwgdGhlbiB3ZSBydW4gYWxvbmcgdGhlIGJvdW5kYXJ5IHVudGlsIHdlIGhpdAogICAgICAgIC8vIGFuIGludGVyc2VjdGlvbiwgdGhlbiB3ZSBzd2l0Y2ggYmFjayB0byB0aGUgcG9seSBhbmQgcnVuIG9uIG9uIHRoaXMgb25lIGFnYWluLCBhbmQgc28gb24gdW50aWwgd2UgZ290IGEgY2xvc2VkCiAgICAgICAgLy8gbG9vcC4gVGhlbiB3ZSBjb250aW51ZSB3aXRoIHRoZSBwYXRoIHdlIGxlZnQgdG8gY2F0Y2ggcG90ZW50aWFsIGFkZGl0aW9uYWwgcG9seXMgb24gdGhlIG90aGVyIHNpZGUgb2YgdGhlCiAgICAgICAgLy8gYm91bmRhcnkgYXMgZGVzY3JpYmVkIGluIGEpCiAgICAgICAgaWYoICFibGFja3NpZGUuZW1wdHkoKSApCiAgICAgICAgewogICAgICAgICAgICAvLyBwb2x5IGVkZ2UgaW5kZXgsIGludGVyc2VjdGlvbiBwb2ludCwgZWRnZSBpbmRleCBpbiBib3VuZGFyeSBwb2x5CiAgICAgICAgICAgIHN0ZDo6dmVjdG9yPHN0ZDo6dHVwbGU8c2l6ZV90LCBJZmNWZWN0b3IzLCBzaXplX3Q+ID4gaW50ZXJzZWN0aW9uczsKICAgICAgICAgICAgYm9vbCBzdGFydGVkSW5zaWRlID0gUG9pbnRJblBvbHkocHJvaiAqIGJsYWNrc2lkZS5mcm9udCgpLCBwcm9maWxlLT52ZXJ0cyk7CiAgICAgICAgICAgIGJvb2wgaXNDdXJyZW50bHlJbnNpZGUgPSBzdGFydGVkSW5zaWRlOwoKICAgICAgICAgICAgc3RkOjp2ZWN0b3I8c3RkOjpwYWlyPHNpemVfdCwgSWZjVmVjdG9yMz4gPiBpbnRlcnNlY3RlZF9ib3VuZGFyeTsKCiAgICAgICAgICAgIGZvciggc2l6ZV90IGEgPSAwOyBhIDwgYmxhY2tzaWRlLnNpemUoKTsgKythICkKICAgICAgICAgICAgewogICAgICAgICAgICAgICAgY29uc3QgSWZjVmVjdG9yMyBlMCA9IHByb2ogKiBibGFja3NpZGVbYV07CiAgICAgICAgICAgICAgICBjb25zdCBJZmNWZWN0b3IzIGUxID0gcHJvaiAqIGJsYWNrc2lkZVsoYSArIDEpICUgYmxhY2tzaWRlLnNpemUoKV07CgogICAgICAgICAgICAgICAgaW50ZXJzZWN0ZWRfYm91bmRhcnkuY2xlYXIoKTsKICAgICAgICAgICAgICAgIEludGVyc2VjdHNCb3VuZGFyeVByb2ZpbGUoZTAsIGUxLCBwcm9maWxlLT52ZXJ0cywgaXNDdXJyZW50bHlJbnNpZGUsIGludGVyc2VjdGVkX2JvdW5kYXJ5KTsKICAgICAgICAgICAgICAgIC8vIHNvcnQgdGhlIGhpdHMgYnkgZGlzdGFuY2UgZnJvbSBlMCB0byBnZXQgdGhlIGNvcnJlY3QgaW4vb3V0L2luIHNlcXVlbmNlLiBNYW51YWxseSA6LSggSSBtaXNzIHlvdSwgQysrMTEuCiAgICAgICAgICAgICAgICBpZiggaW50ZXJzZWN0ZWRfYm91bmRhcnkuc2l6ZSgpID4gMSApCiAgICAgICAgICAgICAgICB7CiAgICAgICAgICAgICAgICAgICAgYm9vbCBrZWVwU29ydGluZyA9IHRydWU7CiAgICAgICAgICAgICAgICAgICAgd2hpbGUoIGtlZXBTb3J0aW5nICkKICAgICAgICAgICAgICAgICAgICB7CiAgICAgICAgICAgICAgICAgICAgICAgIGtlZXBTb3J0aW5nID0gZmFsc2U7CiAgICAgICAgICAgICAgICAgICAgICAgIGZvciggc2l6ZV90IGIgPSAwOyBiIDwgaW50ZXJzZWN0ZWRfYm91bmRhcnkuc2l6ZSgpIC0gMTsgKytiICkKICAgICAgICAgICAgICAgICAgICAgICAgewogICAgICAgICAgICAgICAgICAgICAgICAgICAgaWYoIChpbnRlcnNlY3RlZF9ib3VuZGFyeVtiICsgMV0uc2Vjb25kIC0gZTApLlNxdWFyZUxlbmd0aCgpIDwgKGludGVyc2VjdGVkX2JvdW5kYXJ5W2JdLnNlY29uZCAtIGUwKS5TcXVhcmVMZW5ndGgoKSApCiAgICAgICAgICAgICAgICAgICAgICAgICAgICB7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAga2VlcFNvcnRpbmcgPSB0cnVlOwogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHN0ZDo6c3dhcChpbnRlcnNlY3RlZF9ib3VuZGFyeVtiICsgMV0sIGludGVyc2VjdGVkX2JvdW5kYXJ5W2JdKTsKICAgICAgICAgICAgICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgIC8vIG5vdyBhZGQgdGhlbSB0byB0aGUgbGlzdCBvZiBpbnRlcnNlY3Rpb25zCiAgICAgICAgICAgICAgICBmb3IoIHNpemVfdCBiID0gMDsgYiA8IGludGVyc2VjdGVkX2JvdW5kYXJ5LnNpemUoKTsgKytiICkKICAgICAgICAgICAgICAgICAgICBpbnRlcnNlY3Rpb25zLnB1c2hfYmFjayhzdGQ6Om1ha2VfdHVwbGUoYSwgcHJval9pbnYgKiBpbnRlcnNlY3RlZF9ib3VuZGFyeVtiXS5zZWNvbmQsIGludGVyc2VjdGVkX2JvdW5kYXJ5W2JdLmZpcnN0KSk7CgogICAgICAgICAgICAgICAgLy8gYW5kIGNhbGN1bGF0ZSBvdXIgbmV3IGluc2lkZS9vdXRzaWRlIHN0YXRlCiAgICAgICAgICAgICAgICBpZiggaW50ZXJzZWN0ZWRfYm91bmRhcnkuc2l6ZSgpICYgMSApCiAgICAgICAgICAgICAgICAgICAgaXNDdXJyZW50bHlJbnNpZGUgPSAhaXNDdXJyZW50bHlJbnNpZGU7CiAgICAgICAgICAgIH0KCiAgICAgICAgICAgIC8vIHdlIGdvdCBhIGxpc3Qgb2YgaW4tb3V0LWNvbWJpbmF0aW9ucyBvZiBpbnRlcnNlY3Rpb25zLiBUaGF0IHNob3VsZCBiZSBhbiBldmVuIG51bWJlciBvZiBpbnRlcnNlY3Rpb25zLCBvcgogICAgICAgICAgICAvLyB3ZSdyZSBmdWNrZWQuCiAgICAgICAgICAgIGlmKCAoaW50ZXJzZWN0aW9ucy5zaXplKCkgJiAxKSAhPSAwICkKICAgICAgICAgICAgewogICAgICAgICAgICAgICAgSUZDSW1wb3J0ZXI6OkxvZ1dhcm4oIk9kZCBudW1iZXIgb2YgaW50ZXJzZWN0aW9ucywgY2FuJ3Qgd29yayB3aXRoIHRoYXQuIE9taXR0aW5nIGhhbGYgc3BhY2UgYm91bmRhcnkgY2hlY2suIik7CiAgICAgICAgICAgICAgICBjb250aW51ZTsKICAgICAgICAgICAgfQoKICAgICAgICAgICAgaWYoIGludGVyc2VjdGlvbnMuc2l6ZSgpID4gMSApCiAgICAgICAgICAgIHsKICAgICAgICAgICAgICAgIC8vIElmIHdlIHN0YXJ0ZWQgb3V0c2lkZSwgdGhlIGZpcnN0IGludGVyc2VjdGlvbiBpcyBhIG91dC0+aW4gaW50ZXJzZWN0aW9uLiBDeWNsZSB0aGVtIHNvIHRoYXQgaXQKICAgICAgICAgICAgICAgIC8vIHN0YXJ0cyB3aXRoIGFuIGludGVyc2VjdGlvbiBsZWF2aW5nIHRoZSBib3VuZGFyeQogICAgICAgICAgICAgICAgaWYoICFzdGFydGVkSW5zaWRlICkKICAgICAgICAgICAgICAgIGZvciggc2l6ZV90IGIgPSAwOyBiIDwgaW50ZXJzZWN0aW9ucy5zaXplKCkgLSAxOyArK2IgKQogICAgICAgICAgICAgICAgICAgIHN0ZDo6c3dhcChpbnRlcnNlY3Rpb25zW2JdLCBpbnRlcnNlY3Rpb25zWyhiICsgaW50ZXJzZWN0aW9ucy5zaXplKCkgLSAxKSAlIGludGVyc2VjdGlvbnMuc2l6ZSgpXSk7CgogICAgICAgICAgICAgICAgLy8gRmlsdGVyIHBhaXJzIG9mIG91dC0+aW4tPm91dCB0aGF0IGxpZSB0b28gY2xvc2UgdG8gZWFjaCBvdGhlci4KICAgICAgICAgICAgICAgIGZvciggc2l6ZV90IGEgPSAwOyBpbnRlcnNlY3Rpb25zLnNpemUoKSA+IDAgJiYgYSA8IGludGVyc2VjdGlvbnMuc2l6ZSgpIC0gMTsgLyoqLyApCiAgICAgICAgICAgICAgICB7CiAgICAgICAgICAgICAgICAgICAgaWYoIChzdGQ6OmdldDwxPihpbnRlcnNlY3Rpb25zW2FdKSAtIHN0ZDo6Z2V0PDE+KGludGVyc2VjdGlvbnNbKGEgKyAxKSAlIGludGVyc2VjdGlvbnMuc2l6ZSgpXSkpLlNxdWFyZUxlbmd0aCgpIDwgMWUtMTAgKQogICAgICAgICAgICAgICAgICAgICAgICBpbnRlcnNlY3Rpb25zLmVyYXNlKGludGVyc2VjdGlvbnMuYmVnaW4oKSArIGEsIGludGVyc2VjdGlvbnMuYmVnaW4oKSArIGEgKyAyKTsKICAgICAgICAgICAgICAgICAgICBlbHNlCiAgICAgICAgICAgICAgICAgICAgICAgIGErKzsKICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgIGlmKCBpbnRlcnNlY3Rpb25zLnNpemUoKSA+IDEgJiYgKHN0ZDo6Z2V0PDE+KGludGVyc2VjdGlvbnMuYmFjaygpKSAtIHN0ZDo6Z2V0PDE+KGludGVyc2VjdGlvbnMuZnJvbnQoKSkpLlNxdWFyZUxlbmd0aCgpIDwgMWUtMTAgKQogICAgICAgICAgICAgICAgewogICAgICAgICAgICAgICAgICAgIGludGVyc2VjdGlvbnMucG9wX2JhY2soKTsgaW50ZXJzZWN0aW9ucy5lcmFzZShpbnRlcnNlY3Rpb25zLmJlZ2luKCkpOwogICAgICAgICAgICAgICAgfQogICAgICAgICAgICB9CgoKICAgICAgICAgICAgLy8gbm8gaW50ZXJzZWN0aW9ucyBhdCBhbGw6IGVpdGhlciBjb21wbGV0ZWx5IGluc2lkZSB0aGUgYm91bmRhcnksIHNvIGV2ZXJ5dGhpbmcgZ2V0cyBkaXNjYXJkZWQsIG9yIGNvbXBsZXRlbHkgb3V0c2lkZS4KICAgICAgICAgICAgLy8gaW4gdGhlIGxhdHRlciBjYXNlIHdlJ3JlIGltcGxlbWVudGlvbmFsIGxvc3QuIEknbSBzaW1wbHkgZ29pbmcgdG8gaWdub3JlIHRoaXMsIHNvIGEgbGFyZ2UgcG9seSB3aWxsIG5vdCBnZXQgYW55CiAgICAgICAgICAgIC8vIGhvbGVzIGlmIHRoZSBib3VuZGFyeSBpcyBzbWFsbGVyIGFuZCBkb2VzIG5vdCB0b3VjaCBpdCBhbnl3aGVyZS4KICAgICAgICAgICAgaWYoIGludGVyc2VjdGlvbnMuZW1wdHkoKSApCiAgICAgICAgICAgIHsKICAgICAgICAgICAgICAgIC8vIHN0YXJ0aW5nIHBvaW50IHdhcyBvdXRzaWRlIC0+IGV2ZXJ5dGhpbmcgaXMgb3V0c2lkZSB0aGUgYm91bmRhcnkgLT4gbm90aGluZyBpcyBjbGlwcGVkIC0+IGFkZCBibGFjayBzaWRlCiAgICAgICAgICAgICAgICAvLyB0byByZXN1bHQgbWVzaCB1bmNoYW5nZWQKICAgICAgICAgICAgICAgIGlmKCAhc3RhcnRlZEluc2lkZSApCiAgICAgICAgICAgICAgICB7CiAgICAgICAgICAgICAgICAgICAgb3V0dmVydGNudC5wdXNoX2JhY2soc3RhdGljX2Nhc3Q8dW5zaWduZWQgaW50PihibGFja3NpZGUuc2l6ZSgpKSk7CiAgICAgICAgICAgICAgICAgICAgb3V0dmVydC5pbnNlcnQob3V0dmVydC5lbmQoKSwgYmxhY2tzaWRlLmJlZ2luKCksIGJsYWNrc2lkZS5lbmQoKSk7CiAgICAgICAgICAgICAgICAgICAgY29udGludWU7CiAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICBlbHNlCiAgICAgICAgICAgICAgICB7CiAgICAgICAgICAgICAgICAgICAgLy8gc3RhcnRpbmcgcG9pbnQgd2FzIGluc2lkZSB0aGUgYm91bmRhcnkgLT4gZXZlcnl0aGluZyBpcyBpbnNpZGUgdGhlIGJvdW5kYXJ5IC0+IG5vdGhpbmcgaXMgc3BhcmVkIGZyb20gdGhlCiAgICAgICAgICAgICAgICAgICAgLy8gY2xpcHBpbmcgLT4gbm90aGluZyBsZWZ0IHRvIGFkZCB0byB0aGUgcmVzdWx0IG1lc2gKICAgICAgICAgICAgICAgICAgICBjb250aW51ZTsKICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgfQoKICAgICAgICAgICAgLy8gZGV0ZXJtaW5lIHRoZSBkaXJlY3Rpb24gaW4gd2hpY2ggd2UncmUgbWFyY2hpbmcgYWxvbmcgdGhlIGJvdW5kYXJ5IHBvbHlnb24uIElmIHRoZSBzcmMgcG9seSBpcyBmYWNlZCB1cHdhcmRzCiAgICAgICAgICAgIC8vIGFuZCB0aGUgYm91bmRhcnkgaXMgYWxzbyB3aW5kZWQgdGhpcyB3YXksIHdlIG5lZWQgdG8gbWFyY2ggKmJhY2t3YXJkcyogb24gdGhlIGJvdW5kYXJ5LgogICAgICAgICAgICBjb25zdCBJZmNWZWN0b3IzIHBvbHlOb3JtYWwgPSBJZmNNYXRyaXgzKHByb2opICogVGVtcE1lc2g6OkNvbXB1dGVQb2x5Z29uTm9ybWFsKGJsYWNrc2lkZS5kYXRhKCksIGJsYWNrc2lkZS5zaXplKCkpOwogICAgICAgICAgICBib29sIG1hcmNoQmFja3dhcmRzT25Cb3VuZGFyeSA9IChwcm9maWxlTm9ybWFsICogcG9seU5vcm1hbCkgPj0gMC4wOwoKICAgICAgICAgICAgLy8gQnVpbGQgY2xvc2VkIGxvb3BzIGZyb20gdGhlc2UgaW50ZXJzZWN0aW9ucy4gU3RhcnRpbmcgZnJvbSBhbiBpbnRlcnNlY3Rpb24gbGVhdmluZyB0aGUgYm91bmRhcnkgd2UKICAgICAgICAgICAgLy8gd2FsayBhbG9uZyB0aGUgcG9seWdvbiB0byB0aGUgbmV4dCBpbnRlcnNlY3Rpb24gKHdoaWNoIHNob3VsZCBiZSBhbiBJUyBlbnRlcmluZyB0aGUgYm91bmRhcnkgcG9seSkuCiAgICAgICAgICAgIC8vIEZyb20gdGhlcmUgd2Ugd2FsayBhbG9uZyB0aGUgYm91bmRhcnkgdW50aWwgd2UgaGl0IGFub3RoZXIgaW50ZXJzZWN0aW9uIGxlYXZpbmcgdGhlIGJvdW5kYXJ5LAogICAgICAgICAgICAvLyB3YWxrIGFsb25nIHRoZSBwb2x5IHRvIHRoZSBuZXh0IElTIGFuZCBzbyBvbiB1bnRpbCB3ZSdyZSBiYWNrIGF0IHRoZSBzdGFydGluZyBwb2ludC4KICAgICAgICAgICAgLy8gV2UgcmVtb3ZlIGV2ZXJ5IGludGVyc2VjdGlvbiB3ZSAidXNlZCB1cCIsIHNvIGFueSByZW1haW5pbmcgaW50ZXJzZWN0aW9uIGlzIHRoZSBzdGFydCBvZiBhIG5ldyBsb29wLgogICAgICAgICAgICB3aGlsZSggIWludGVyc2VjdGlvbnMuZW1wdHkoKSApCiAgICAgICAgICAgIHsKICAgICAgICAgICAgICAgIHN0ZDo6dmVjdG9yPElmY1ZlY3RvcjM+IHJlc3VsdHBvbHk7CiAgICAgICAgICAgICAgICBzaXplX3QgY3VycmVudEludGVyc2VjSWR4ID0gMDsKCiAgICAgICAgICAgICAgICB3aGlsZSggdHJ1ZSApCiAgICAgICAgICAgICAgICB7CiAgICAgICAgICAgICAgICAgICAgYWlfYXNzZXJ0KGludGVyc2VjdGlvbnMuc2l6ZSgpID4gY3VycmVudEludGVyc2VjSWR4ICsgMSk7CiAgICAgICAgICAgICAgICAgICAgc3RkOjp0dXBsZTxzaXplX3QsIElmY1ZlY3RvcjMsIHNpemVfdD4gY3VycmludHNlYyA9IGludGVyc2VjdGlvbnNbY3VycmVudEludGVyc2VjSWR4ICsgMF07CiAgICAgICAgICAgICAgICAgICAgc3RkOjp0dXBsZTxzaXplX3QsIElmY1ZlY3RvcjMsIHNpemVfdD4gbmV4dGludHNlYyA9IGludGVyc2VjdGlvbnNbY3VycmVudEludGVyc2VjSWR4ICsgMV07CiAgICAgICAgICAgICAgICAgICAgaW50ZXJzZWN0aW9ucy5lcmFzZShpbnRlcnNlY3Rpb25zLmJlZ2luKCkgKyBjdXJyZW50SW50ZXJzZWNJZHgsIGludGVyc2VjdGlvbnMuYmVnaW4oKSArIGN1cnJlbnRJbnRlcnNlY0lkeCArIDIpOwoKICAgICAgICAgICAgICAgICAgICAvLyB3ZSBzdGFydCB3aXRoIGFuIGluLT5vdXQgaW50ZXJzZWN0aW9uCiAgICAgICAgICAgICAgICAgICAgcmVzdWx0cG9seS5wdXNoX2JhY2soc3RkOjpnZXQ8MT4oY3VycmludHNlYykpOwogICAgICAgICAgICAgICAgICAgIC8vIGNsaW1iIGFsb25nIHRoZSBwb2x5Z29uIHRvIHRoZSBuZXh0IGludGVyc2VjdGlvbiwgd2hpY2ggc2hvdWxkIGJlIGFuIG91dC0+aW4KICAgICAgICAgICAgICAgICAgICBzaXplX3QgbnVtUG9seVBvaW50cyA9IChzdGQ6OmdldDwwPihjdXJyaW50c2VjKSA+IHN0ZDo6Z2V0PDA+KG5leHRpbnRzZWMpID8gYmxhY2tzaWRlLnNpemUoKSA6IDApCiAgICAgICAgICAgICAgICAgICAgICAgICsgc3RkOjpnZXQ8MD4obmV4dGludHNlYykgLSBzdGQ6OmdldDwwPihjdXJyaW50c2VjKTsKICAgICAgICAgICAgICAgICAgICBmb3IoIHNpemVfdCBhID0gMTsgYSA8PSBudW1Qb2x5UG9pbnRzOyArK2EgKQogICAgICAgICAgICAgICAgICAgICAgICByZXN1bHRwb2x5LnB1c2hfYmFjayhibGFja3NpZGVbKHN0ZDo6Z2V0PDA+KGN1cnJpbnRzZWMpICsgYSkgJSBibGFja3NpZGUuc2l6ZSgpXSk7CiAgICAgICAgICAgICAgICAgICAgLy8gcHV0IHRoZSBvdXQtPmluIGludGVyc2VjdGlvbgogICAgICAgICAgICAgICAgICAgIHJlc3VsdHBvbHkucHVzaF9iYWNrKHN0ZDo6Z2V0PDE+KG5leHRpbnRzZWMpKTsKCiAgICAgICAgICAgICAgICAgICAgLy8gZ2VuZXJhdGUgc2VnbWVudHMgYWxvbmcgdGhlIGJvdW5kYXJ5IHBvbHlnb24gdGhhdCBsaWUgaW4gdGhlIHBvbHkncyBwbGFuZSB1bnRpbCB3ZSBoaXQgYW5vdGhlciBpbnRlcnNlY3Rpb24KICAgICAgICAgICAgICAgICAgICBJZmNWZWN0b3IzIHN0YXJ0aW5nUG9pbnQgPSBwcm9qICogc3RkOjpnZXQ8MT4obmV4dGludHNlYyk7CiAgICAgICAgICAgICAgICAgICAgc2l6ZV90IGN1cnJlbnRCb3VuZGFyeUVkZ2VJZHggPSAoc3RkOjpnZXQ8Mj4obmV4dGludHNlYykgKyAobWFyY2hCYWNrd2FyZHNPbkJvdW5kYXJ5ID8gMSA6IDApKSAlIHByb2ZpbGUtPnZlcnRzLnNpemUoKTsKICAgICAgICAgICAgICAgICAgICBzaXplX3QgbmV4dEludHNlY0lkeCA9IFNJWkVfTUFYOwogICAgICAgICAgICAgICAgICAgIHdoaWxlKCBuZXh0SW50c2VjSWR4ID09IFNJWkVfTUFYICkKICAgICAgICAgICAgICAgICAgICB7CiAgICAgICAgICAgICAgICAgICAgICAgIElmY0Zsb2F0IHQgPSAxZTEwOwoKICAgICAgICAgICAgICAgICAgICAgICAgc2l6ZV90IG5leHRCb3VuZGFyeUVkZ2VJZHggPSBtYXJjaEJhY2t3YXJkc09uQm91bmRhcnkgPyAoY3VycmVudEJvdW5kYXJ5RWRnZUlkeCArIHByb2ZpbGUtPnZlcnRzLnNpemUoKSAtIDEpIDogY3VycmVudEJvdW5kYXJ5RWRnZUlkeCArIDE7CiAgICAgICAgICAgICAgICAgICAgICAgIG5leHRCb3VuZGFyeUVkZ2VJZHggJT0gcHJvZmlsZS0+dmVydHMuc2l6ZSgpOwogICAgICAgICAgICAgICAgICAgICAgICAvLyB2ZXJ0aWNlcyBvZiB0aGUgY3VycmVudCBib3VuZGFyeSBzZWdtZW50cwogICAgICAgICAgICAgICAgICAgICAgICBJZmNWZWN0b3IzIGN1cnJCb3VuZGFyeVBvaW50ID0gcHJvZmlsZS0+dmVydHNbY3VycmVudEJvdW5kYXJ5RWRnZUlkeF07CiAgICAgICAgICAgICAgICAgICAgICAgIElmY1ZlY3RvcjMgbmV4dEJvdW5kYXJ5UG9pbnQgPSBwcm9maWxlLT52ZXJ0c1tuZXh0Qm91bmRhcnlFZGdlSWR4XTsKICAgICAgICAgICAgICAgICAgICAgICAgLy8gcHJvamVjdCB0aGUgdHdvIG9udG8gdGhlIHBvbHlnb24KICAgICAgICAgICAgICAgICAgICAgICAgaWYoIHN0ZDo6YWJzKHBvbHlOb3JtYWwueikgPiAxZS01ICkKICAgICAgICAgICAgICAgICAgICAgICAgewogICAgICAgICAgICAgICAgICAgICAgICAgICAgY3VyckJvdW5kYXJ5UG9pbnQueiA9IHN0YXJ0aW5nUG9pbnQueiArIChjdXJyQm91bmRhcnlQb2ludC54IC0gc3RhcnRpbmdQb2ludC54KSAqIHBvbHlOb3JtYWwueC9wb2x5Tm9ybWFsLnogKyAoY3VyckJvdW5kYXJ5UG9pbnQueSAtIHN0YXJ0aW5nUG9pbnQueSkgKiBwb2x5Tm9ybWFsLnkvcG9seU5vcm1hbC56OwogICAgICAgICAgICAgICAgICAgICAgICAgICAgbmV4dEJvdW5kYXJ5UG9pbnQueiA9IHN0YXJ0aW5nUG9pbnQueiArIChuZXh0Qm91bmRhcnlQb2ludC54IC0gc3RhcnRpbmdQb2ludC54KSAqIHBvbHlOb3JtYWwueC9wb2x5Tm9ybWFsLnogKyAobmV4dEJvdW5kYXJ5UG9pbnQueSAtIHN0YXJ0aW5nUG9pbnQueSkgKiBwb2x5Tm9ybWFsLnkvcG9seU5vcm1hbC56OwogICAgICAgICAgICAgICAgICAgICAgICB9CgogICAgICAgICAgICAgICAgICAgICAgICAvLyBidWlsZCBhIGRpcmVjdGlvbiB0aGF0IGdvZXMgYWxvbmcgdGhlIGJvdW5kYXJ5IGJvcmRlciBidXQgbGllcyBpbiB0aGUgcG9seSBwbGFuZQogICAgICAgICAgICAgICAgICAgICAgICBJZmNWZWN0b3IzIGJvdW5kYXJ5UGxhbmVOb3JtYWwgPSAoKG5leHRCb3VuZGFyeVBvaW50IC0gY3VyckJvdW5kYXJ5UG9pbnQpIF4gcHJvZmlsZU5vcm1hbCkuTm9ybWFsaXplKCk7CiAgICAgICAgICAgICAgICAgICAgICAgIElmY1ZlY3RvcjMgZGlyQXRQb2x5UGxhbmUgPSAoYm91bmRhcnlQbGFuZU5vcm1hbCBeIHBvbHlOb3JtYWwpLk5vcm1hbGl6ZSgpICogKG1hcmNoQmFja3dhcmRzT25Cb3VuZGFyeSA/IC0xLjAgOiAxLjApOwogICAgICAgICAgICAgICAgICAgICAgICAvLyBpZiB3ZSBjYW4gcHJvamVjdCB0aGUgZGlyZWN0aW9uIHRvIHRoZSBwbGFuZSwgd2UgY2FuIGNhbGN1bGF0ZSBhIG1heGltdW0gbWFyY2hpbmcgZGlzdGFuY2UgYWxvbmcgdGhhdCBkaXIKICAgICAgICAgICAgICAgICAgICAgICAgLy8gdW50aWwgd2UgZmluaXNoIHRoYXQgYm91bmRhcnkgc2VnbWVudCBhbmQgY29udGludWUgb24gdGhlIG5leHQKICAgICAgICAgICAgICAgICAgICAgICAgaWYoIHN0ZDo6YWJzKHBvbHlOb3JtYWwueikgPiAxZS01ICkKICAgICAgICAgICAgICAgICAgICAgICAgewogICAgICAgICAgICAgICAgICAgICAgICAgICAgdCA9IHN0ZDo6bWluKHQsIChuZXh0Qm91bmRhcnlQb2ludCAtIHN0YXJ0aW5nUG9pbnQpLkxlbmd0aCgpKTsKICAgICAgICAgICAgICAgICAgICAgICAgfQoKICAgICAgICAgICAgICAgICAgICAgICAgLy8gY2hlY2sgaWYgdGhlIGRpcmVjdGlvbiBoaXRzIHRoZSBsb29wIHN0YXJ0IC0gaWYgeWVzLCB3ZSBnb3QgYSBwb2x5IHRvIG91dHB1dAogICAgICAgICAgICAgICAgICAgICAgICBJZmNWZWN0b3IzIGRpclRvVGhhdFBvaW50ID0gcHJvaiAqIHJlc3VsdHBvbHkuZnJvbnQoKSAtIHN0YXJ0aW5nUG9pbnQ7CiAgICAgICAgICAgICAgICAgICAgICAgIElmY0Zsb2F0IHRwdCA9IGRpclRvVGhhdFBvaW50ICogZGlyQXRQb2x5UGxhbmU7CiAgICAgICAgICAgICAgICAgICAgICAgIGlmKCB0cHQgPiAtMWUtNiAmJiB0cHQgPD0gdCAmJiAoZGlyVG9UaGF0UG9pbnQgLSB0cHQgKiBkaXJBdFBvbHlQbGFuZSkuU3F1YXJlTGVuZ3RoKCkgPCAxZS0xMCApCiAgICAgICAgICAgICAgICAgICAgICAgIHsKICAgICAgICAgICAgICAgICAgICAgICAgICAgIG5leHRJbnRzZWNJZHggPSBpbnRlcnNlY3Rpb25zLnNpemUoKTsgLy8gZGlydHkgaGFjayB0byBlbmQgbWFyY2hpbmcgYWxvbmcgdGhlIGJvdW5kYXJ5IGFuZCBzaWduYWwgdGhlIGVuZCBvZiB0aGUgbG9vcAogICAgICAgICAgICAgICAgICAgICAgICAgICAgdCA9IHRwdDsKICAgICAgICAgICAgICAgICAgICAgICAgfQoKICAgICAgICAgICAgICAgICAgICAgICAgLy8gYWxzbyBjaGVjayBpZiB0aGUgZGlyZWN0aW9uIGhpdHMgYW55IGluLT5vdXQgaW50ZXJzZWN0aW9ucyBlYXJsaWVyLiBJZiB3ZSBoaXQgb25lLCB3ZSBjYW4gc3dpdGNoIGJhY2sKICAgICAgICAgICAgICAgICAgICAgICAgLy8gdG8gbWFyY2hpbmcgYWxvbmcgdGhlIHBvbHkgYm9yZGVyIGZyb20gdGhhdCBpbnRlcnNlY3Rpb24gcG9pbnQKICAgICAgICAgICAgICAgICAgICAgICAgZm9yKCBzaXplX3QgYSA9IDA7IGEgPCBpbnRlcnNlY3Rpb25zLnNpemUoKTsgYSArPSAyICkKICAgICAgICAgICAgICAgICAgICAgICAgewogICAgICAgICAgICAgICAgICAgICAgICAgICAgZGlyVG9UaGF0UG9pbnQgPSBwcm9qICogc3RkOjpnZXQ8MT4oaW50ZXJzZWN0aW9uc1thXSkgLSBzdGFydGluZ1BvaW50OwogICAgICAgICAgICAgICAgICAgICAgICAgICAgdHB0ID0gZGlyVG9UaGF0UG9pbnQgKiBkaXJBdFBvbHlQbGFuZTsKICAgICAgICAgICAgICAgICAgICAgICAgICAgIGlmKCB0cHQgPiAtMWUtNiAmJiB0cHQgPD0gdCAmJiAoZGlyVG9UaGF0UG9pbnQgLSB0cHQgKiBkaXJBdFBvbHlQbGFuZSkuU3F1YXJlTGVuZ3RoKCkgPCAxZS0xMCApCiAgICAgICAgICAgICAgICAgICAgICAgICAgICB7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgbmV4dEludHNlY0lkeCA9IGE7IC8vIHN3aXRjaCBiYWNrIHRvIHBvbHkgYW5kIG1hcmNoIG9uIGZyb20gdGhpcyBpbi0+b3V0IGludGVyc2VjdGlvbgogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHQgPSB0cHQ7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICAgICAgICAgIH0KCiAgICAgICAgICAgICAgICAgICAgICAgIC8vIGlmIHdlIGtlZXAgbWFyY2hpbmcgb24gdGhlIGJvdW5kYXJ5LCBwdXQgdGhlIHNlZ21lbnQgZW5kIHBvaW50IHRvIHRoZSByZXN1bHQgcG9seSBhbmQgd2VsbC4uLiBrZWVwIG1hcmNoaW5nCiAgICAgICAgICAgICAgICAgICAgICAgIGlmKCBuZXh0SW50c2VjSWR4ID09IFNJWkVfTUFYICkKICAgICAgICAgICAgICAgICAgICAgICAgewogICAgICAgICAgICAgICAgICAgICAgICAgICAgcmVzdWx0cG9seS5wdXNoX2JhY2socHJval9pbnYgKiBuZXh0Qm91bmRhcnlQb2ludCk7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICBjdXJyZW50Qm91bmRhcnlFZGdlSWR4ID0gbmV4dEJvdW5kYXJ5RWRnZUlkeDsKICAgICAgICAgICAgICAgICAgICAgICAgICAgIHN0YXJ0aW5nUG9pbnQgPSBuZXh0Qm91bmRhcnlQb2ludDsKICAgICAgICAgICAgICAgICAgICAgICAgfQoKICAgICAgICAgICAgICAgICAgICAgICAgLy8gcXVpY2sgZW5kbGVzcyBsb29wIGNoZWNrCiAgICAgICAgICAgICAgICAgICAgICAgIGlmKCByZXN1bHRwb2x5LnNpemUoKSA+IGJsYWNrc2lkZS5zaXplKCkgKyBwcm9maWxlLT52ZXJ0cy5zaXplKCkgKQogICAgICAgICAgICAgICAgICAgICAgICB7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICBJRkNJbXBvcnRlcjo6TG9nRXJyb3IoIkVuY291bnRlcmVkIGVuZGxlc3MgbG9vcCB3aGlsZSBjbGlwcGluZyBwb2x5Z29uIGFnYWluc3QgcG9seS1ib3VuZGVkIGhhbGYgc3BhY2UuIik7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICBicmVhazsKICAgICAgICAgICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICAgICAgIH0KCiAgICAgICAgICAgICAgICAgICAgLy8gd2UncmUgYmFjayBvbiB0aGUgcG9seSAtIGlmIHRoaXMgaXMgdGhlIGludGVyc2VjdGlvbiB3ZSBzdGFydGVkIGZyb20sIHdlIGdvdCBhIGNsb3NlZCBsb29wLgogICAgICAgICAgICAgICAgICAgIGlmKCBuZXh0SW50c2VjSWR4ID49IGludGVyc2VjdGlvbnMuc2l6ZSgpICkKICAgICAgICAgICAgICAgICAgICB7CiAgICAgICAgICAgICAgICAgICAgICAgIGJyZWFrOwogICAgICAgICAgICAgICAgICAgIH0KCiAgICAgICAgICAgICAgICAgICAgLy8gb3RoZXJ3aXNlIGl0J3MgYW5vdGhlciBpbnRlcnNlY3Rpb24uIENvbnRpbnVlIG1hcmNoaW5nIGZyb20gdGhlcmUuCiAgICAgICAgICAgICAgICAgICAgY3VycmVudEludGVyc2VjSWR4ID0gbmV4dEludHNlY0lkeDsKICAgICAgICAgICAgICAgIH0KCiAgICAgICAgICAgICAgICBXcml0ZVBvbHlnb24ocmVzdWx0cG9seSwgcmVzdWx0KTsKICAgICAgICAgICAgfQogICAgICAgIH0KICAgIH0KICAgIElGQ0ltcG9ydGVyOjpMb2dEZWJ1ZygiZ2VuZXJhdGluZyBDU0cgZ2VvbWV0cnkgYnkgcGxhbmUgY2xpcHBpbmcgd2l0aCBwb2x5Z29uYWwgYm91bmRpbmcgKElmY0Jvb2xlYW5DbGlwcGluZ1Jlc3VsdCkiKTsKfQoKLy8gLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tCnZvaWQgUHJvY2Vzc0Jvb2xlYW5FeHRydWRlZEFyZWFTb2xpZERpZmZlcmVuY2UoY29uc3QgSWZjRXh0cnVkZWRBcmVhU29saWQqIGFzLCBUZW1wTWVzaCYgcmVzdWx0LAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNvbnN0IFRlbXBNZXNoJiBmaXJzdF9vcGVyYW5kLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIENvbnZlcnNpb25EYXRhJiBjb252KQp7CiAgICBhaV9hc3NlcnQoYXMgIT0gTlVMTCk7CgogICAgLy8gVGhpcyBjYXNlIGlzIGhhbmRsZWQgYnkgcmVkdWN0aW9uIHRvIGFuIGluc3RhbmNlIG9mIHRoZSBxdWFkcmlmeSgpIGFsZ29yaXRobS4KICAgIC8vIE9idmlvdXNseSwgdGhpcyB3b24ndCB3b3JrIGZvciBhcmJpdHJhcmlseSBjb21wbGV4IGNhc2VzLiBJbiBmYWN0LCB0aGUgZmlyc3QKICAgIC8vIG9wZXJhbmQgc2hvdWxkIGJlIG5lYXItcGxhbmFyLiBMdWNraWx5LCB0aGlzIGlzIHVzdWFsbHkgdGhlIGNhc2UgaW4gSWZjCiAgICAvLyBidWlsZGluZ3MuCgogICAgc3RkOjpzaGFyZWRfcHRyPFRlbXBNZXNoPiBtZXNodG1wID0gc3RkOjpzaGFyZWRfcHRyPFRlbXBNZXNoPihuZXcgVGVtcE1lc2goKSk7CiAgICBQcm9jZXNzRXh0cnVkZWRBcmVhU29saWQoKmFzLCptZXNodG1wLGNvbnYsZmFsc2UpOwoKICAgIHN0ZDo6dmVjdG9yPFRlbXBPcGVuaW5nPiBvcGVuaW5ncygxLCBUZW1wT3BlbmluZyhhcyxJZmNWZWN0b3IzKDAsMCwwKSxtZXNodG1wLHN0ZDo6c2hhcmVkX3B0cjxUZW1wTWVzaD4oKSkpOwoKICAgIHJlc3VsdCA9IGZpcnN0X29wZXJhbmQ7CgogICAgVGVtcE1lc2ggdGVtcDsKCiAgICBzdGQ6OnZlY3RvcjxJZmNWZWN0b3IzPjo6Y29uc3RfaXRlcmF0b3Igdml0ID0gZmlyc3Rfb3BlcmFuZC52ZXJ0cy5iZWdpbigpOwogICAgZm9yKHVuc2lnbmVkIGludCBwY291bnQgOiBmaXJzdF9vcGVyYW5kLnZlcnRjbnQpIHsKICAgICAgICB0ZW1wLkNsZWFyKCk7CgogICAgICAgIHRlbXAudmVydHMuaW5zZXJ0KHRlbXAudmVydHMuZW5kKCksIHZpdCwgdml0ICsgcGNvdW50KTsKICAgICAgICB0ZW1wLnZlcnRjbnQucHVzaF9iYWNrKHBjb3VudCk7CgogICAgICAgIC8vIFRoZSBhbGdvcml0aG1zIHVzZWQgdG8gZ2VuZXJhdGUgbWVzaCBnZW9tZXRyeSBzb21ldGltZXMKICAgICAgICAvLyBzcGl0IG91dCBsaW5lcyBvciBvdGhlciBkZWdlbmVyYXRlcyB3aGljaCBtdXN0IGJlCiAgICAgICAgLy8gZmlsdGVyZWQgdG8gYXZvaWQgcnVubmluZyBpbnRvIGFzc2VydGlvbnMgbGF0ZXIgb24uCgogICAgICAgIC8vIENvbXB1dGVQb2x5Z29uTm9ybWFsIHJldHVybnMgdGhlIE5ld2VsbCBub3JtYWwsIHNvIHRoZQogICAgICAgIC8vIGxlbmd0aCBvZiB0aGUgbm9ybWFsIGlzIHRoZSBhcmVhIG9mIHRoZSBwb2x5Z29uLgogICAgICAgIGNvbnN0IElmY1ZlY3RvcjMmIG5vcm1hbCA9IHRlbXAuQ29tcHV0ZUxhc3RQb2x5Z29uTm9ybWFsKGZhbHNlKTsKICAgICAgICBpZiAobm9ybWFsLlNxdWFyZUxlbmd0aCgpIDwgc3RhdGljX2Nhc3Q8SWZjRmxvYXQ+KDFlLTUpKSB7CiAgICAgICAgICAgIElGQ0ltcG9ydGVyOjpMb2dXYXJuKCJza2lwcGluZyBkZWdlbmVyYXRlIHBvbHlnb24gKFByb2Nlc3NCb29sZWFuRXh0cnVkZWRBcmVhU29saWREaWZmZXJlbmNlKSIpOwogICAgICAgICAgICBjb250aW51ZTsKICAgICAgICB9CgogICAgICAgIEdlbmVyYXRlT3BlbmluZ3Mob3BlbmluZ3MsIHN0ZDo6dmVjdG9yPElmY1ZlY3RvcjM+KDEsSWZjVmVjdG9yMygxLDAsMCkpLCB0ZW1wLCBmYWxzZSwgdHJ1ZSk7CiAgICAgICAgcmVzdWx0LkFwcGVuZCh0ZW1wKTsKCiAgICAgICAgdml0ICs9IHBjb3VudDsKICAgIH0KCiAgICBJRkNJbXBvcnRlcjo6TG9nRGVidWcoImdlbmVyYXRpbmcgQ1NHIGdlb21ldHJ5IGJ5IGdlb21ldHJpYyBkaWZmZXJlbmNlIHRvIGEgc29saWQgKElmY0V4dHJ1ZGVkQXJlYVNvbGlkKSIpOwp9CgovLyAtLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0Kdm9pZCBQcm9jZXNzQm9vbGVhbihjb25zdCBJZmNCb29sZWFuUmVzdWx0JiBib29sZWFuLCBUZW1wTWVzaCYgcmVzdWx0LCBDb252ZXJzaW9uRGF0YSYgY29udikKewogICAgLy8gc3VwcG9ydGVkIENTRyBvcGVyYXRpb25zOgogICAgLy8gICBESUZGRVJFTkNFCiAgICBpZihjb25zdCBJZmNCb29sZWFuUmVzdWx0KiBjb25zdCBjbGlwID0gYm9vbGVhbi5Ub1B0cjxJZmNCb29sZWFuUmVzdWx0PigpKSB7CiAgICAgICAgaWYoY2xpcC0+T3BlcmF0b3IgIT0gIkRJRkZFUkVOQ0UiKSB7CiAgICAgICAgICAgIElGQ0ltcG9ydGVyOjpMb2dXYXJuKCJlbmNvdW50ZXJlZCB1bnN1cHBvcnRlZCBib29sZWFuIG9wZXJhdG9yOiAiICsgKHN0ZDo6c3RyaW5nKWNsaXAtPk9wZXJhdG9yKTsKICAgICAgICAgICAgcmV0dXJuOwogICAgICAgIH0KCiAgICAgICAgLy8gc3VwcG9ydGVkIGNhc2VzICgxc3Qgb3BlcmFuZCk6CiAgICAgICAgLy8gIElmY0Jvb2xlYW5SZXN1bHQgLS0gY2FsbCBQcm9jZXNzQm9vbGVhbiByZWN1cnNpdmVseQogICAgICAgIC8vICBJZmNTd2VwdEFyZWFTb2xpZCAtLSBvYnRhaW4gcG9seWdvbmFsIGdlb21ldHJ5IGZpcnN0CgogICAgICAgIC8vIHN1cHBvcnRlZCBjYXNlcyAoMm5kIG9wZXJhbmQpOgogICAgICAgIC8vICBJZmNIYWxmU3BhY2VTb2xpZCAtLSBlYXN5LCBjbGlwIGFnYWluc3QgcGxhbmUKICAgICAgICAvLyAgSWZjRXh0cnVkZWRBcmVhU29saWQgLS0gcmVkdWNlIHRvIGFuIGluc3RhbmNlIG9mIHRoZSBxdWFkcmlmeSgpIGFsZ29yaXRobQoKCiAgICAgICAgY29uc3QgSWZjSGFsZlNwYWNlU29saWQqIGNvbnN0IGhzID0gY2xpcC0+U2Vjb25kT3BlcmFuZC0+UmVzb2x2ZVNlbGVjdFB0cjxJZmNIYWxmU3BhY2VTb2xpZD4oY29udi5kYik7CiAgICAgICAgY29uc3QgSWZjRXh0cnVkZWRBcmVhU29saWQqIGNvbnN0IGFzID0gY2xpcC0+U2Vjb25kT3BlcmFuZC0+UmVzb2x2ZVNlbGVjdFB0cjxJZmNFeHRydWRlZEFyZWFTb2xpZD4oY29udi5kYik7CiAgICAgICAgaWYoIWhzICYmICFhcykgewogICAgICAgICAgICBJRkNJbXBvcnRlcjo6TG9nRXJyb3IoImV4cGVjdGVkIElmY0hhbGZTcGFjZVNvbGlkIG9yIElmY0V4dHJ1ZGVkQXJlYVNvbGlkIGFzIHNlY29uZCBjbGlwcGluZyBvcGVyYW5kIik7CiAgICAgICAgICAgIHJldHVybjsKICAgICAgICB9CgogICAgICAgIFRlbXBNZXNoIGZpcnN0X29wZXJhbmQ7CiAgICAgICAgaWYoY29uc3QgSWZjQm9vbGVhblJlc3VsdCogY29uc3Qgb3AwID0gY2xpcC0+Rmlyc3RPcGVyYW5kLT5SZXNvbHZlU2VsZWN0UHRyPElmY0Jvb2xlYW5SZXN1bHQ+KGNvbnYuZGIpKSB7CiAgICAgICAgICAgIFByb2Nlc3NCb29sZWFuKCpvcDAsZmlyc3Rfb3BlcmFuZCxjb252KTsKICAgICAgICB9CiAgICAgICAgZWxzZSBpZiAoY29uc3QgSWZjU3dlcHRBcmVhU29saWQqIGNvbnN0IHN3ZXB0ID0gY2xpcC0+Rmlyc3RPcGVyYW5kLT5SZXNvbHZlU2VsZWN0UHRyPElmY1N3ZXB0QXJlYVNvbGlkPihjb252LmRiKSkgewogICAgICAgICAgICBQcm9jZXNzU3dlcHRBcmVhU29saWQoKnN3ZXB0LGZpcnN0X29wZXJhbmQsY29udik7CiAgICAgICAgfQogICAgICAgIGVsc2UgewogICAgICAgICAgICBJRkNJbXBvcnRlcjo6TG9nRXJyb3IoImV4cGVjdGVkIElmY1N3ZXB0QXJlYVNvbGlkIG9yIElmY0Jvb2xlYW5SZXN1bHQgYXMgZmlyc3QgY2xpcHBpbmcgb3BlcmFuZCIpOwogICAgICAgICAgICByZXR1cm47CiAgICAgICAgfQoKICAgICAgICBpZihocykgewoKICAgICAgICAgICAgY29uc3QgSWZjUG9seWdvbmFsQm91bmRlZEhhbGZTcGFjZSogY29uc3QgaHNfYm91bmRlZCA9IGNsaXAtPlNlY29uZE9wZXJhbmQtPlJlc29sdmVTZWxlY3RQdHI8SWZjUG9seWdvbmFsQm91bmRlZEhhbGZTcGFjZT4oY29udi5kYik7CiAgICAgICAgICAgIGlmIChoc19ib3VuZGVkKSB7CiAgICAgICAgICAgICAgICBQcm9jZXNzUG9seWdvbmFsQm91bmRlZEJvb2xlYW5IYWxmU3BhY2VEaWZmZXJlbmNlKGhzX2JvdW5kZWQsIHJlc3VsdCwgZmlyc3Rfb3BlcmFuZCwgY29udik7CiAgICAgICAgICAgIH0KICAgICAgICAgICAgZWxzZSB7CiAgICAgICAgICAgICAgICBQcm9jZXNzQm9vbGVhbkhhbGZTcGFjZURpZmZlcmVuY2UoaHMsIHJlc3VsdCwgZmlyc3Rfb3BlcmFuZCwgY29udik7CiAgICAgICAgICAgIH0KICAgICAgICB9CiAgICAgICAgZWxzZSB7CiAgICAgICAgICAgIFByb2Nlc3NCb29sZWFuRXh0cnVkZWRBcmVhU29saWREaWZmZXJlbmNlKGFzLCByZXN1bHQsIGZpcnN0X29wZXJhbmQsIGNvbnYpOwogICAgICAgIH0KICAgIH0KICAgIGVsc2UgewogICAgICAgIElGQ0ltcG9ydGVyOjpMb2dXYXJuKCJza2lwcGluZyB1bmtub3duIElmY0Jvb2xlYW5SZXN1bHQgZW50aXR5LCB0eXBlIGlzICIgKyBib29sZWFuLkdldENsYXNzTmFtZSgpKTsKICAgIH0KfQoKfSAvLyAhIElGQwp9IC8vICEgQXNzaW1wCgojZW5kaWYKCg==