Ly89PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT0KLy8KLy8gU3BsYXNoQml0bWFwLmgKLy8KLy89PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT0KCi8vPT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09Ci8vCi8vIE1vZGlmaWVkIHVuZGVyIHRoZSBQb3BwbGVyIHByb2plY3QgLSBodHRwOi8vcG9wcGxlci5mcmVlZGVza3RvcC5vcmcKLy8KLy8gQWxsIGNoYW5nZXMgbWFkZSB1bmRlciB0aGUgUG9wcGxlciBwcm9qZWN0IHRvIHRoaXMgZmlsZSBhcmUgbGljZW5zZWQKLy8gdW5kZXIgR1BMIHZlcnNpb24gMiBvciBsYXRlcgovLwovLyBDb3B5cmlnaHQgKEMpIDIwMDcgSWxtYXJpIEhlaWtraW5lbiA8aWxtYXJpLmhlaWtraW5lbkBnbWFpbC5jb20+Ci8vIENvcHlyaWdodCAoQykgMjAwOSBTaGVuIExpYW5nIDxzaGVuemh1eGlAZ21haWwuY29tPgovLyBDb3B5cmlnaHQgKEMpIDIwMDksIDIwMTIsIDIwMTggQWxiZXJ0IEFzdGFscyBDaWQgPGFhY2lkQGtkZS5vcmc+Ci8vIENvcHlyaWdodCAoQykgMjAwOSBTdGVmYW4gVGhvbWFzIDx0aG9tYXNAZWxvYWQyNC5jb20+Ci8vIENvcHlyaWdodCAoQykgMjAxMCwgMjAxNyBBZHJpYW4gSm9obnNvbiA8YWpvaG5zb25AcmVkbmVvbi5jb20+Ci8vIENvcHlyaWdodCAoQykgMjAxMCBIYXJyeSBSb2JlcnRzIDxoYXJyeS5yb2JlcnRzQG1pZG5pZ2h0LWxhYnMub3JnPgovLyBDb3B5cmlnaHQgKEMpIDIwMTAgQ2hyaXN0aWFuIEZldWVyc+RuZ2VyIDxjZmV1ZXJzYWVuZ2VyQGdvb2dsZW1haWwuY29tPgovLyBDb3B5cmlnaHQgKEMpIDIwMTAgV2lsbGlhbSBCYWRlciA8d2lsbGlhbWJhZGVyQGhvdG1haWwuY29tPgovLyBDb3B5cmlnaHQgKEMpIDIwMTIgVGhvbWFzIEZyZWl0YWcgPFRob21hcy5GcmVpdGFnQGFsZmEuZGU+Ci8vIENvcHlyaWdodCAoQykgMjAxNSBBZGFtIFJlaWNob2xkIDxhZGFtcmVpY2hvbGRAbXlvcGVyYS5jb20+Ci8vIENvcHlyaWdodCAoQykgMjAxNiBLZW5qaSBVbm8gPGt1QGRpZ2l0YWxkb2xwaGlucy5qcD4KLy8gQ29weXJpZ2h0IChDKSAyMDE4IE1hcnRpbiBQYWNrbWFuIDxnemxpc3RAZ29vZ2xlbWFpbC5jb20+Ci8vCi8vIFRvIHNlZSBhIGRlc2NyaXB0aW9uIG9mIHRoZSBjaGFuZ2VzIHBsZWFzZSBzZWUgdGhlIENoYW5nZWxvZyBmaWxlIHRoYXQKLy8gY2FtZSB3aXRoIHlvdXIgdGFyYmFsbCBvciB0eXBlIG1ha2UgQ2hhbmdlTG9nIGlmIHlvdSBhcmUgYnVpbGRpbmcgZnJvbSBnaXQKLy8KLy89PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT0KCiNpZm5kZWYgU1BMQVNIQklUTUFQX0gKI2RlZmluZSBTUExBU0hCSVRNQVBfSAoKI2lmZGVmIFVTRV9HQ0NfUFJBR01BUwojcHJhZ21hIGludGVyZmFjZQojZW5kaWYKCiNpbmNsdWRlICJTcGxhc2hUeXBlcy5oIgojaW5jbHVkZSAicG9wcGxlci9HZnhTdGF0ZS5oIgojaW5jbHVkZSA8c3RkaW8uaD4KCmNsYXNzIEltZ1dyaXRlcjsKCi8vLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tCi8vIFNwbGFzaEJpdG1hcAovLy0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLQoKY2xhc3MgU3BsYXNoQml0bWFwIHsKcHVibGljOgoKICAvLyBDcmVhdGUgYSBuZXcgYml0bWFwLiAgSXQgd2lsbCBoYXZlIDx3aWR0aEE+IHggPGhlaWdodEE+IHBpeGVscyBpbgogIC8vIGNvbG9yIG1vZGUgPG1vZGVBPi4gIFJvd3Mgd2lsbCBiZSBwYWRkZWQgb3V0IHRvIGEgbXVsdGlwbGUgb2YKICAvLyA8cm93UGFkPiBieXRlcy4gIElmIDx0b3BEb3duPiBpcyBmYWxzZSwgdGhlIGJpdG1hcCB3aWxsIGJlIHN0b3JlZAogIC8vIHVwc2lkZS1kb3duLCBpLmUuLCB3aXRoIHRoZSBsYXN0IHJvdyBmaXJzdCBpbiBtZW1vcnkuCiAgU3BsYXNoQml0bWFwKGludCB3aWR0aEEsIGludCBoZWlnaHRBLCBpbnQgcm93UGFkLAoJICAgICAgIFNwbGFzaENvbG9yTW9kZSBtb2RlQSwgR0Jvb2wgYWxwaGFBLAoJICAgICAgIEdCb29sIHRvcERvd24gPSBnVHJ1ZSwgR29vTGlzdCAqc2VwYXJhdGlvbkxpc3QgPSBOVUxMKTsKICBzdGF0aWMgU3BsYXNoQml0bWFwICpjb3B5KFNwbGFzaEJpdG1hcCAqc3JjKTsKCiAgflNwbGFzaEJpdG1hcCgpOwoKICBTcGxhc2hCaXRtYXAoY29uc3QgU3BsYXNoQml0bWFwICYpID0gZGVsZXRlOwogIFNwbGFzaEJpdG1hcCYgb3BlcmF0b3I9KGNvbnN0IFNwbGFzaEJpdG1hcCAmKSA9IGRlbGV0ZTsKCiAgaW50IGdldFdpZHRoKCkgeyByZXR1cm4gd2lkdGg7IH0KICBpbnQgZ2V0SGVpZ2h0KCkgeyByZXR1cm4gaGVpZ2h0OyB9CiAgaW50IGdldFJvd1NpemUoKSB7IHJldHVybiByb3dTaXplOyB9CiAgaW50IGdldEFscGhhUm93U2l6ZSgpIHsgcmV0dXJuIHdpZHRoOyB9CiAgaW50IGdldFJvd1BhZCgpIHsgcmV0dXJuIHJvd1BhZDsgfQogIFNwbGFzaENvbG9yTW9kZSBnZXRNb2RlKCkgeyByZXR1cm4gbW9kZTsgfQogIFNwbGFzaENvbG9yUHRyIGdldERhdGFQdHIoKSB7IHJldHVybiBkYXRhOyB9CiAgR3VjaGFyICpnZXRBbHBoYVB0cigpIHsgcmV0dXJuIGFscGhhOyB9CiAgR29vTGlzdCAqZ2V0U2VwYXJhdGlvbkxpc3QoKSB7IHJldHVybiBzZXBhcmF0aW9uTGlzdDsgfQoKICBTcGxhc2hFcnJvciB3cml0ZVBOTUZpbGUoY2hhciAqZmlsZU5hbWUpOwogIFNwbGFzaEVycm9yIHdyaXRlUE5NRmlsZShGSUxFICpmKTsKICBTcGxhc2hFcnJvciB3cml0ZUFscGhhUEdNRmlsZShjaGFyICpmaWxlTmFtZSk7CgogIHN0cnVjdCBXcml0ZUltZ1BhcmFtcwogIHsKICAgIGludCBqcGVnUXVhbGl0eSA9IC0xOwogICAgR0Jvb2wganBlZ1Byb2dyZXNzaXZlID0gZ0ZhbHNlOwogICAgR29vU3RyaW5nIHRpZmZDb21wcmVzc2lvbjsKICAgIEdCb29sIGpwZWdPcHRpbWl6ZSA9IGdGYWxzZTsKICB9OwoKICBTcGxhc2hFcnJvciB3cml0ZUltZ0ZpbGUoU3BsYXNoSW1hZ2VGaWxlRm9ybWF0IGZvcm1hdCwgY2hhciAqZmlsZU5hbWUsIGludCBoRFBJLCBpbnQgdkRQSSwgV3JpdGVJbWdQYXJhbXMqIHBhcmFtcyA9IG51bGxwdHIpOwogIFNwbGFzaEVycm9yIHdyaXRlSW1nRmlsZShTcGxhc2hJbWFnZUZpbGVGb3JtYXQgZm9ybWF0LCBGSUxFICpmLCBpbnQgaERQSSwgaW50IHZEUEksIFdyaXRlSW1nUGFyYW1zKiBwYXJhbXMgPSBudWxscHRyKTsKICBTcGxhc2hFcnJvciB3cml0ZUltZ0ZpbGUoSW1nV3JpdGVyICp3cml0ZXIsIEZJTEUgKmYsIGludCBoRFBJLCBpbnQgdkRQSSwgU3BsYXNoQ29sb3JNb2RlIGltYWdlV3JpdGVyRm9ybWF0KTsKCiAgZW51bSBDb252ZXJzaW9uTW9kZQogIHsKICAgICAgY29udmVyc2lvbk9wYXF1ZSwKICAgICAgY29udmVyc2lvbkFscGhhLAogICAgICBjb252ZXJzaW9uQWxwaGFQcmVtdWx0aXBsaWVkCiAgfTsKCiAgR0Jvb2wgY29udmVydFRvWEJHUihDb252ZXJzaW9uTW9kZSBjb252ZXJzaW9uTW9kZSA9IGNvbnZlcnNpb25PcGFxdWUpOwoKICB2b2lkIGdldFBpeGVsKGludCB4LCBpbnQgeSwgU3BsYXNoQ29sb3JQdHIgcGl4ZWwpOwogIHZvaWQgZ2V0UkdCTGluZShpbnQgeSwgU3BsYXNoQ29sb3JQdHIgbGluZSk7CiAgdm9pZCBnZXRYQkdSTGluZShpbnQgeSwgU3BsYXNoQ29sb3JQdHIgbGluZSwgQ29udmVyc2lvbk1vZGUgY29udmVyc2lvbk1vZGUgPSBjb252ZXJzaW9uT3BhcXVlKTsKI2lmZGVmIFNQTEFTSF9DTVlLCiAgdm9pZCBnZXRDTVlLTGluZShpbnQgeSwgU3BsYXNoQ29sb3JQdHIgbGluZSk7CiNlbmRpZgogIEd1Y2hhciBnZXRBbHBoYShpbnQgeCwgaW50IHkpOwoKICAvLyBDYWxsZXIgdGFrZXMgb3duZXJzaGlwIG9mIHRoZSBiaXRtYXAgZGF0YS4gIFRoZSBTcGxhc2hCaXRtYXAKICAvLyBvYmplY3QgaXMgbm8gbG9uZ2VyIHZhbGlkIC0tIHRoZSBuZXh0IGNhbGwgc2hvdWxkIGJlIHRvIHRoZQogIC8vIGRlc3RydWN0b3IuCiAgU3BsYXNoQ29sb3JQdHIgdGFrZURhdGEoKTsKCnByaXZhdGU6CgogIGludCB3aWR0aCwgaGVpZ2h0OwkJLy8gc2l6ZSBvZiBiaXRtYXAKICBpbnQgcm93UGFkOwogIGludCByb3dTaXplOwkJCS8vIHNpemUgb2Ygb25lIHJvdyBvZiBkYXRhLCBpbiBieXRlcwoJCQkJLy8gICAtIG5lZ2F0aXZlIGZvciBib3R0b20tdXAgYml0bWFwcwogIFNwbGFzaENvbG9yTW9kZSBtb2RlOwkJLy8gY29sb3IgbW9kZQogIFNwbGFzaENvbG9yUHRyIGRhdGE7CQkvLyBwb2ludGVyIHRvIHJvdyB6ZXJvIG9mIHRoZSBjb2xvciBkYXRhCiAgR3VjaGFyICphbHBoYTsJCS8vIHBvaW50ZXIgdG8gcm93IHplcm8gb2YgdGhlIGFscGhhIGRhdGEKCQkJCS8vICAgKGFsd2F5cyB0b3AtZG93bikKICBHb29MaXN0ICpzZXBhcmF0aW9uTGlzdDsgLy8gbGlzdCBvZiBzcG90IGNvbG9yYW50cyBhbmQgdGhlaXIgbWFwcGluZyBmdW5jdGlvbnMKCiAgZnJpZW5kIGNsYXNzIFNwbGFzaDsKCiAgdm9pZCBzZXRKcGVnUGFyYW1zKEltZ1dyaXRlciAqd3JpdGVyLCBXcml0ZUltZ1BhcmFtcyogcGFyYW1zKTsKfTsKCiNlbmRpZgo=