{
  "_kin": {
    "degraded": {
      "embed_persistence_unavailable": false,
      "embed_worker_failed": false,
      "mass_deletion_blocked": false
    },
    "durability": {
      "durable_entities": 1206,
      "durable_relations": 2393,
      "live_entities": 1206,
      "live_only_entities": 0,
      "live_only_relations": 0,
      "live_relations": 2393,
      "note": "1206 entities and 2393 relations answered here; 0 entities and 0 relations are uncommitted, and durable repository authority records every entity and relation answering here.",
      "state": "recorded"
    },
    "envelope_version": 1,
    "freshness": {
      "age_seconds": 62,
      "at": "2026-09-08T04:12:10.860252+00:00",
      "state": "recorded"
    },
    "graph_as_of": {
      "generation": 3
    },
    "graph_state": {
      "entity_count": 1206,
      "entity_count_scope": "every entity node the daemon holds, including external reference targets this repository does not define; `kin graph status` prints the smaller count of definitions this repository owns and names the excluded targets on its own line",
      "initialized": true,
      "loaded": true,
      "reconciliation_status": "idle"
    },
    "hydration_semantics": {
      "created_under": 11,
      "derives": 11,
      "standing": "current"
    },
    "runtime": "repo-daemon"
  },
  "artifact": {
    "artifact_id": "b339a3a8-0c10-5f96-9b27-708787754cc8",
    "entry": {
      "executable": false,
      "hash": "dbf5270a4645bdf3c27ec153b0fb0ff2d262efc3f9aeb29a66bf682ee4ea1997",
      "type": "blob"
    },
    "path": {
      "bytes_hex": "7364732e63"
    },
    "path_label": "sds.c",
    "path_label_lossy": false
  },
  "content_base64": "LyogU0RTTGliIDIuMCAtLSBBIEMgZHluYW1pYyBzdHJpbmdzIGxpYnJhcnkKICoKICogQ29weXJpZ2h0IChjKSAyMDA2LTIwMTUsIFNhbHZhdG9yZSBTYW5maWxpcHBvIDxhbnRpcmV6IGF0IGdtYWlsIGRvdCBjb20+CiAqIENvcHlyaWdodCAoYykgMjAxNSwgT3JhbiBBZ3JhCiAqIENvcHlyaWdodCAoYykgMjAxNSwgUmVkaXMgTGFicywgSW5jCiAqIEFsbCByaWdodHMgcmVzZXJ2ZWQuCiAqCiAqIFJlZGlzdHJpYnV0aW9uIGFuZCB1c2UgaW4gc291cmNlIGFuZCBiaW5hcnkgZm9ybXMsIHdpdGggb3Igd2l0aG91dAogKiBtb2RpZmljYXRpb24sIGFyZSBwZXJtaXR0ZWQgcHJvdmlkZWQgdGhhdCB0aGUgZm9sbG93aW5nIGNvbmRpdGlvbnMgYXJlIG1ldDoKICoKICogICAqIFJlZGlzdHJpYnV0aW9ucyBvZiBzb3VyY2UgY29kZSBtdXN0IHJldGFpbiB0aGUgYWJvdmUgY29weXJpZ2h0IG5vdGljZSwKICogICAgIHRoaXMgbGlzdCBvZiBjb25kaXRpb25zIGFuZCB0aGUgZm9sbG93aW5nIGRpc2NsYWltZXIuCiAqICAgKiBSZWRpc3RyaWJ1dGlvbnMgaW4gYmluYXJ5IGZvcm0gbXVzdCByZXByb2R1Y2UgdGhlIGFib3ZlIGNvcHlyaWdodAogKiAgICAgbm90aWNlLCB0aGlzIGxpc3Qgb2YgY29uZGl0aW9ucyBhbmQgdGhlIGZvbGxvd2luZyBkaXNjbGFpbWVyIGluIHRoZQogKiAgICAgZG9jdW1lbnRhdGlvbiBhbmQvb3Igb3RoZXIgbWF0ZXJpYWxzIHByb3ZpZGVkIHdpdGggdGhlIGRpc3RyaWJ1dGlvbi4KICogICAqIE5laXRoZXIgdGhlIG5hbWUgb2YgUmVkaXMgbm9yIHRoZSBuYW1lcyBvZiBpdHMgY29udHJpYnV0b3JzIG1heSBiZSB1c2VkCiAqICAgICB0byBlbmRvcnNlIG9yIHByb21vdGUgcHJvZHVjdHMgZGVyaXZlZCBmcm9tIHRoaXMgc29mdHdhcmUgd2l0aG91dAogKiAgICAgc3BlY2lmaWMgcHJpb3Igd3JpdHRlbiBwZXJtaXNzaW9uLgogKgogKiBUSElTIFNPRlRXQVJFIElTIFBST1ZJREVEIEJZIFRIRSBDT1BZUklHSFQgSE9MREVSUyBBTkQgQ09OVFJJQlVUT1JTICJBUyBJUyIKICogQU5EIEFOWSBFWFBSRVNTIE9SIElNUExJRUQgV0FSUkFOVElFUywgSU5DTFVESU5HLCBCVVQgTk9UIExJTUlURUQgVE8sIFRIRQogKiBJTVBMSUVEIFdBUlJBTlRJRVMgT0YgTUVSQ0hBTlRBQklMSVRZIEFORCBGSVRORVNTIEZPUiBBIFBBUlRJQ1VMQVIgUFVSUE9TRQogKiBBUkUgRElTQ0xBSU1FRC4gSU4gTk8gRVZFTlQgU0hBTEwgVEhFIENPUFlSSUdIVCBPV05FUiBPUiBDT05UUklCVVRPUlMgQkUKICogTElBQkxFIEZPUiBBTlkgRElSRUNULCBJTkRJUkVDVCwgSU5DSURFTlRBTCwgU1BFQ0lBTCwgRVhFTVBMQVJZLCBPUgogKiBDT05TRVFVRU5USUFMIERBTUFHRVMgKElOQ0xVRElORywgQlVUIE5PVCBMSU1JVEVEIFRPLCBQUk9DVVJFTUVOVCBPRgogKiBTVUJTVElUVVRFIEdPT0RTIE9SIFNFUlZJQ0VTOyBMT1NTIE9GIFVTRSwgREFUQSwgT1IgUFJPRklUUzsgT1IgQlVTSU5FU1MKICogSU5URVJSVVBUSU9OKSBIT1dFVkVSIENBVVNFRCBBTkQgT04gQU5ZIFRIRU9SWSBPRiBMSUFCSUxJVFksIFdIRVRIRVIgSU4KICogQ09OVFJBQ1QsIFNUUklDVCBMSUFCSUxJVFksIE9SIFRPUlQgKElOQ0xVRElORyBORUdMSUdFTkNFIE9SIE9USEVSV0lTRSkKICogQVJJU0lORyBJTiBBTlkgV0FZIE9VVCBPRiBUSEUgVVNFIE9GIFRISVMgU09GVFdBUkUsIEVWRU4gSUYgQURWSVNFRCBPRiBUSEUKICogUE9TU0lCSUxJVFkgT0YgU1VDSCBEQU1BR0UuCiAqLwoKI2luY2x1ZGUgImZtYWNyb3MuaCIKI2luY2x1ZGUgPHN0ZGlvLmg+CiNpbmNsdWRlIDxzdGRsaWIuaD4KI2luY2x1ZGUgPHN0cmluZy5oPgojaW5jbHVkZSA8Y3R5cGUuaD4KI2luY2x1ZGUgPGFzc2VydC5oPgojaW5jbHVkZSA8bGltaXRzLmg+CiNpbmNsdWRlICJzZHMuaCIKI2luY2x1ZGUgInNkc2FsbG9jLmgiCgpzdGF0aWMgaW5saW5lIGludCBzZHNIZHJTaXplKGNoYXIgdHlwZSkgewogICAgc3dpdGNoKHR5cGUmU0RTX1RZUEVfTUFTSykgewogICAgICAgIGNhc2UgU0RTX1RZUEVfNToKICAgICAgICAgICAgcmV0dXJuIHNpemVvZihzdHJ1Y3Qgc2RzaGRyNSk7CiAgICAgICAgY2FzZSBTRFNfVFlQRV84OgogICAgICAgICAgICByZXR1cm4gc2l6ZW9mKHN0cnVjdCBzZHNoZHI4KTsKICAgICAgICBjYXNlIFNEU19UWVBFXzE2OgogICAgICAgICAgICByZXR1cm4gc2l6ZW9mKHN0cnVjdCBzZHNoZHIxNik7CiAgICAgICAgY2FzZSBTRFNfVFlQRV8zMjoKICAgICAgICAgICAgcmV0dXJuIHNpemVvZihzdHJ1Y3Qgc2RzaGRyMzIpOwogICAgICAgIGNhc2UgU0RTX1RZUEVfNjQ6CiAgICAgICAgICAgIHJldHVybiBzaXplb2Yoc3RydWN0IHNkc2hkcjY0KTsKICAgIH0KICAgIHJldHVybiAwOwp9CgpzdGF0aWMgaW5saW5lIGNoYXIgc2RzUmVxVHlwZShzaXplX3Qgc3RyaW5nX3NpemUpIHsKICAgIGlmIChzdHJpbmdfc2l6ZSA8IDMyKQogICAgICAgIHJldHVybiBTRFNfVFlQRV81OwogICAgaWYgKHN0cmluZ19zaXplIDwgMHhmZikKICAgICAgICByZXR1cm4gU0RTX1RZUEVfODsKICAgIGlmIChzdHJpbmdfc2l6ZSA8IDB4ZmZmZikKICAgICAgICByZXR1cm4gU0RTX1RZUEVfMTY7CiAgICBpZiAoc3RyaW5nX3NpemUgPCAweGZmZmZmZmZmKQogICAgICAgIHJldHVybiBTRFNfVFlQRV8zMjsKICAgIHJldHVybiBTRFNfVFlQRV82NDsKfQoKLyogQ3JlYXRlIGEgbmV3IHNkcyBzdHJpbmcgd2l0aCB0aGUgY29udGVudCBzcGVjaWZpZWQgYnkgdGhlICdpbml0JyBwb2ludGVyCiAqIGFuZCAnaW5pdGxlbicuCiAqIElmIE5VTEwgaXMgdXNlZCBmb3IgJ2luaXQnIHRoZSBzdHJpbmcgaXMgaW5pdGlhbGl6ZWQgd2l0aCB6ZXJvIGJ5dGVzLgogKgogKiBUaGUgc3RyaW5nIGlzIGFsd2F5cyBudWxsLXRlcm1pbmF0ZWQgKGFsbCB0aGUgc2RzIHN0cmluZ3MgYXJlLCBhbHdheXMpIHNvCiAqIGV2ZW4gaWYgeW91IGNyZWF0ZSBhbiBzZHMgc3RyaW5nIHdpdGg6CiAqCiAqIG15c3RyaW5nID0gc2RzbmV3bGVuKCJhYmMiLDMpOwogKgogKiBZb3UgY2FuIHByaW50IHRoZSBzdHJpbmcgd2l0aCBwcmludGYoKSBhcyB0aGVyZSBpcyBhbiBpbXBsaWNpdCBcMCBhdCB0aGUKICogZW5kIG9mIHRoZSBzdHJpbmcuIEhvd2V2ZXIgdGhlIHN0cmluZyBpcyBiaW5hcnkgc2FmZSBhbmQgY2FuIGNvbnRhaW4KICogXDAgY2hhcmFjdGVycyBpbiB0aGUgbWlkZGxlLCBhcyB0aGUgbGVuZ3RoIGlzIHN0b3JlZCBpbiB0aGUgc2RzIGhlYWRlci4gKi8Kc2RzIHNkc25ld2xlbihjb25zdCB2b2lkICppbml0LCBzaXplX3QgaW5pdGxlbikgewogICAgdm9pZCAqc2g7CiAgICBzZHMgczsKICAgIGNoYXIgdHlwZSA9IHNkc1JlcVR5cGUoaW5pdGxlbik7CiAgICAvKiBFbXB0eSBzdHJpbmdzIGFyZSB1c3VhbGx5IGNyZWF0ZWQgaW4gb3JkZXIgdG8gYXBwZW5kLiBVc2UgdHlwZSA4CiAgICAgKiBzaW5jZSB0eXBlIDUgaXMgbm90IGdvb2QgYXQgdGhpcy4gKi8KICAgIGlmICh0eXBlID09IFNEU19UWVBFXzUgJiYgaW5pdGxlbiA9PSAwKSB0eXBlID0gU0RTX1RZUEVfODsKICAgIGludCBoZHJsZW4gPSBzZHNIZHJTaXplKHR5cGUpOwogICAgdW5zaWduZWQgY2hhciAqZnA7IC8qIGZsYWdzIHBvaW50ZXIuICovCgogICAgaWYgKGhkcmxlbitpbml0bGVuKzEgPD0gaW5pdGxlbikgcmV0dXJuIE5VTEw7IC8qIENhdGNoIHNpemVfdCBvdmVyZmxvdyAqLwogICAgc2ggPSBzX21hbGxvYyhoZHJsZW4raW5pdGxlbisxKTsKICAgIGlmIChzaCA9PSBOVUxMKSByZXR1cm4gTlVMTDsKICAgIGlmICghaW5pdCkKICAgICAgICBtZW1zZXQoc2gsIDAsIGhkcmxlbitpbml0bGVuKzEpOwogICAgcyA9IChjaGFyKilzaCtoZHJsZW47CiAgICBmcCA9ICgodW5zaWduZWQgY2hhciopcyktMTsKICAgIHN3aXRjaCh0eXBlKSB7CiAgICAgICAgY2FzZSBTRFNfVFlQRV81OiB7CiAgICAgICAgICAgICpmcCA9IHR5cGUgfCAoaW5pdGxlbiA8PCBTRFNfVFlQRV9CSVRTKTsKICAgICAgICAgICAgYnJlYWs7CiAgICAgICAgfQogICAgICAgIGNhc2UgU0RTX1RZUEVfODogewogICAgICAgICAgICBTRFNfSERSX1ZBUig4LHMpOwogICAgICAgICAgICBzaC0+bGVuID0gaW5pdGxlbjsKICAgICAgICAgICAgc2gtPmFsbG9jID0gaW5pdGxlbjsKICAgICAgICAgICAgKmZwID0gdHlwZTsKICAgICAgICAgICAgYnJlYWs7CiAgICAgICAgfQogICAgICAgIGNhc2UgU0RTX1RZUEVfMTY6IHsKICAgICAgICAgICAgU0RTX0hEUl9WQVIoMTYscyk7CiAgICAgICAgICAgIHNoLT5sZW4gPSBpbml0bGVuOwogICAgICAgICAgICBzaC0+YWxsb2MgPSBpbml0bGVuOwogICAgICAgICAgICAqZnAgPSB0eXBlOwogICAgICAgICAgICBicmVhazsKICAgICAgICB9CiAgICAgICAgY2FzZSBTRFNfVFlQRV8zMjogewogICAgICAgICAgICBTRFNfSERSX1ZBUigzMixzKTsKICAgICAgICAgICAgc2gtPmxlbiA9IGluaXRsZW47CiAgICAgICAgICAgIHNoLT5hbGxvYyA9IGluaXRsZW47CiAgICAgICAgICAgICpmcCA9IHR5cGU7CiAgICAgICAgICAgIGJyZWFrOwogICAgICAgIH0KICAgICAgICBjYXNlIFNEU19UWVBFXzY0OiB7CiAgICAgICAgICAgIFNEU19IRFJfVkFSKDY0LHMpOwogICAgICAgICAgICBzaC0+bGVuID0gaW5pdGxlbjsKICAgICAgICAgICAgc2gtPmFsbG9jID0gaW5pdGxlbjsKICAgICAgICAgICAgKmZwID0gdHlwZTsKICAgICAgICAgICAgYnJlYWs7CiAgICAgICAgfQogICAgfQogICAgaWYgKGluaXRsZW4gJiYgaW5pdCkKICAgICAgICBtZW1jcHkocywgaW5pdCwgaW5pdGxlbik7CiAgICBzW2luaXRsZW5dID0gJ1wwJzsKICAgIHJldHVybiBzOwp9CgovKiBDcmVhdGUgYW4gZW1wdHkgKHplcm8gbGVuZ3RoKSBzZHMgc3RyaW5nLiBFdmVuIGluIHRoaXMgY2FzZSB0aGUgc3RyaW5nCiAqIGFsd2F5cyBoYXMgYW4gaW1wbGljaXQgbnVsbCB0ZXJtLiAqLwpzZHMgc2RzZW1wdHkodm9pZCkgewogICAgcmV0dXJuIHNkc25ld2xlbigiIiwwKTsKfQoKLyogQ3JlYXRlIGEgbmV3IHNkcyBzdHJpbmcgc3RhcnRpbmcgZnJvbSBhIG51bGwgdGVybWluYXRlZCBDIHN0cmluZy4gKi8Kc2RzIHNkc25ldyhjb25zdCBjaGFyICppbml0KSB7CiAgICBzaXplX3QgaW5pdGxlbiA9IChpbml0ID09IE5VTEwpID8gMCA6IHN0cmxlbihpbml0KTsKICAgIHJldHVybiBzZHNuZXdsZW4oaW5pdCwgaW5pdGxlbik7Cn0KCi8qIER1cGxpY2F0ZSBhbiBzZHMgc3RyaW5nLiAqLwpzZHMgc2RzZHVwKGNvbnN0IHNkcyBzKSB7CiAgICByZXR1cm4gc2RzbmV3bGVuKHMsIHNkc2xlbihzKSk7Cn0KCi8qIEZyZWUgYW4gc2RzIHN0cmluZy4gTm8gb3BlcmF0aW9uIGlzIHBlcmZvcm1lZCBpZiAncycgaXMgTlVMTC4gKi8Kdm9pZCBzZHNmcmVlKHNkcyBzKSB7CiAgICBpZiAocyA9PSBOVUxMKSByZXR1cm47CiAgICBzX2ZyZWUoKGNoYXIqKXMtc2RzSGRyU2l6ZShzWy0xXSkpOwp9CgovKiBTZXQgdGhlIHNkcyBzdHJpbmcgbGVuZ3RoIHRvIHRoZSBsZW5ndGggYXMgb2J0YWluZWQgd2l0aCBzdHJsZW4oKSwgc28KICogY29uc2lkZXJpbmcgYXMgY29udGVudCBvbmx5IHVwIHRvIHRoZSBmaXJzdCBudWxsIHRlcm0gY2hhcmFjdGVyLgogKgogKiBUaGlzIGZ1bmN0aW9uIGlzIHVzZWZ1bCB3aGVuIHRoZSBzZHMgc3RyaW5nIGlzIGhhY2tlZCBtYW51YWxseSBpbiBzb21lCiAqIHdheSwgbGlrZSBpbiB0aGUgZm9sbG93aW5nIGV4YW1wbGU6CiAqCiAqIHMgPSBzZHNuZXcoImZvb2JhciIpOwogKiBzWzJdID0gJ1wwJzsKICogc2RzdXBkYXRlbGVuKHMpOwogKiBwcmludGYoIiVkXG4iLCBzZHNsZW4ocykpOwogKgogKiBUaGUgb3V0cHV0IHdpbGwgYmUgIjIiLCBidXQgaWYgd2UgY29tbWVudCBvdXQgdGhlIGNhbGwgdG8gc2RzdXBkYXRlbGVuKCkKICogdGhlIG91dHB1dCB3aWxsIGJlICI2IiBhcyB0aGUgc3RyaW5nIHdhcyBtb2RpZmllZCBidXQgdGhlIGxvZ2ljYWwgbGVuZ3RoCiAqIHJlbWFpbnMgNiBieXRlcy4gKi8Kdm9pZCBzZHN1cGRhdGVsZW4oc2RzIHMpIHsKICAgIHNpemVfdCByZWFsbGVuID0gc3RybGVuKHMpOwogICAgc2Rzc2V0bGVuKHMsIHJlYWxsZW4pOwp9CgovKiBNb2RpZnkgYW4gc2RzIHN0cmluZyBpbi1wbGFjZSB0byBtYWtlIGl0IGVtcHR5ICh6ZXJvIGxlbmd0aCkuCiAqIEhvd2V2ZXIgYWxsIHRoZSBleGlzdGluZyBidWZmZXIgaXMgbm90IGRpc2NhcmRlZCBidXQgc2V0IGFzIGZyZWUgc3BhY2UKICogc28gdGhhdCBuZXh0IGFwcGVuZCBvcGVyYXRpb25zIHdpbGwgbm90IHJlcXVpcmUgYWxsb2NhdGlvbnMgdXAgdG8gdGhlCiAqIG51bWJlciBvZiBieXRlcyBwcmV2aW91c2x5IGF2YWlsYWJsZS4gKi8Kdm9pZCBzZHNjbGVhcihzZHMgcykgewogICAgc2Rzc2V0bGVuKHMsIDApOwogICAgc1swXSA9ICdcMCc7Cn0KCi8qIEVubGFyZ2UgdGhlIGZyZWUgc3BhY2UgYXQgdGhlIGVuZCBvZiB0aGUgc2RzIHN0cmluZyBzbyB0aGF0IHRoZSBjYWxsZXIKICogaXMgc3VyZSB0aGF0IGFmdGVyIGNhbGxpbmcgdGhpcyBmdW5jdGlvbiBjYW4gb3ZlcndyaXRlIHVwIHRvIGFkZGxlbgogKiBieXRlcyBhZnRlciB0aGUgZW5kIG9mIHRoZSBzdHJpbmcsIHBsdXMgb25lIG1vcmUgYnl0ZSBmb3IgbnVsIHRlcm0uCiAqCiAqIE5vdGU6IHRoaXMgZG9lcyBub3QgY2hhbmdlIHRoZSAqbGVuZ3RoKiBvZiB0aGUgc2RzIHN0cmluZyBhcyByZXR1cm5lZAogKiBieSBzZHNsZW4oKSwgYnV0IG9ubHkgdGhlIGZyZWUgYnVmZmVyIHNwYWNlIHdlIGhhdmUuICovCnNkcyBzZHNNYWtlUm9vbUZvcihzZHMgcywgc2l6ZV90IGFkZGxlbikgewogICAgdm9pZCAqc2gsICpuZXdzaDsKICAgIHNpemVfdCBhdmFpbCA9IHNkc2F2YWlsKHMpOwogICAgc2l6ZV90IGxlbiwgbmV3bGVuLCByZXF1aXJlZF9sZW47CiAgICBjaGFyIHR5cGUsIG9sZHR5cGUgPSBzWy0xXSAmIFNEU19UWVBFX01BU0s7CiAgICBpbnQgaGRybGVuOwoKICAgIC8qIFJldHVybiBBU0FQIGlmIHRoZXJlIGlzIGVub3VnaCBzcGFjZSBsZWZ0LiAqLwogICAgaWYgKGF2YWlsID49IGFkZGxlbikgcmV0dXJuIHM7CgogICAgbGVuID0gc2RzbGVuKHMpOwogICAgc2ggPSAoY2hhciopcy1zZHNIZHJTaXplKG9sZHR5cGUpOwogICAgcmVxdWlyZWRfbGVuID0gbmV3bGVuID0gKGxlbithZGRsZW4pOwogICAgaWYgKG5ld2xlbiA8PSBsZW4pIHJldHVybiBOVUxMOyAvKiBDYXRjaCBzaXplX3Qgb3ZlcmZsb3cgKi8KICAgIGlmIChuZXdsZW4gPCBTRFNfTUFYX1BSRUFMTE9DKQogICAgICAgIG5ld2xlbiAqPSAyOwogICAgZWxzZQogICAgICAgIG5ld2xlbiArPSBTRFNfTUFYX1BSRUFMTE9DOwoKICAgIHR5cGUgPSBzZHNSZXFUeXBlKG5ld2xlbik7CgogICAgLyogRG9uJ3QgdXNlIHR5cGUgNTogdGhlIHVzZXIgaXMgYXBwZW5kaW5nIHRvIHRoZSBzdHJpbmcgYW5kIHR5cGUgNSBpcwogICAgICogbm90IGFibGUgdG8gcmVtZW1iZXIgZW1wdHkgc3BhY2UsIHNvIHNkc01ha2VSb29tRm9yKCkgbXVzdCBiZSBjYWxsZWQKICAgICAqIGF0IGV2ZXJ5IGFwcGVuZGluZyBvcGVyYXRpb24uICovCiAgICBpZiAodHlwZSA9PSBTRFNfVFlQRV81KSB0eXBlID0gU0RTX1RZUEVfODsKCiAgICBoZHJsZW4gPSBzZHNIZHJTaXplKHR5cGUpOwogICAgaWYgKGhkcmxlbituZXdsZW4rMSA8PSByZXF1aXJlZF9sZW4pIHJldHVybiBOVUxMOyAvKiBDYXRjaCBzaXplX3Qgb3ZlcmZsb3cgKi8KICAgIGlmIChvbGR0eXBlPT10eXBlKSB7CiAgICAgICAgbmV3c2ggPSBzX3JlYWxsb2Moc2gsIGhkcmxlbituZXdsZW4rMSk7CiAgICAgICAgaWYgKG5ld3NoID09IE5VTEwpIHJldHVybiBOVUxMOwogICAgICAgIHMgPSAoY2hhciopbmV3c2graGRybGVuOwogICAgfSBlbHNlIHsKICAgICAgICAvKiBTaW5jZSB0aGUgaGVhZGVyIHNpemUgY2hhbmdlcywgbmVlZCB0byBtb3ZlIHRoZSBzdHJpbmcgZm9yd2FyZCwKICAgICAgICAgKiBhbmQgY2FuJ3QgdXNlIHJlYWxsb2MgKi8KICAgICAgICBuZXdzaCA9IHNfbWFsbG9jKGhkcmxlbituZXdsZW4rMSk7CiAgICAgICAgaWYgKG5ld3NoID09IE5VTEwpIHJldHVybiBOVUxMOwogICAgICAgIG1lbWNweSgoY2hhciopbmV3c2graGRybGVuLCBzLCBsZW4rMSk7CiAgICAgICAgc19mcmVlKHNoKTsKICAgICAgICBzID0gKGNoYXIqKW5ld3NoK2hkcmxlbjsKICAgICAgICBzWy0xXSA9IHR5cGU7CiAgICAgICAgc2Rzc2V0bGVuKHMsIGxlbik7CiAgICB9CiAgICBzZHNzZXRhbGxvYyhzLCBuZXdsZW4pOwogICAgcmV0dXJuIHM7Cn0KCi8qIFJlYWxsb2NhdGUgdGhlIHNkcyBzdHJpbmcgc28gdGhhdCBpdCBoYXMgbm8gZnJlZSBzcGFjZSBhdCB0aGUgZW5kLiBUaGUKICogY29udGFpbmVkIHN0cmluZyByZW1haW5zIG5vdCBhbHRlcmVkLCBidXQgbmV4dCBjb25jYXRlbmF0aW9uIG9wZXJhdGlvbnMKICogd2lsbCByZXF1aXJlIGEgcmVhbGxvY2F0aW9uLgogKgogKiBBZnRlciB0aGUgY2FsbCwgdGhlIHBhc3NlZCBzZHMgc3RyaW5nIGlzIG5vIGxvbmdlciB2YWxpZCBhbmQgYWxsIHRoZQogKiByZWZlcmVuY2VzIG11c3QgYmUgc3Vic3RpdHV0ZWQgd2l0aCB0aGUgbmV3IHBvaW50ZXIgcmV0dXJuZWQgYnkgdGhlIGNhbGwuICovCnNkcyBzZHNSZW1vdmVGcmVlU3BhY2Uoc2RzIHMpIHsKICAgIHZvaWQgKnNoLCAqbmV3c2g7CiAgICBjaGFyIHR5cGUsIG9sZHR5cGUgPSBzWy0xXSAmIFNEU19UWVBFX01BU0s7CiAgICBpbnQgaGRybGVuOwogICAgc2l6ZV90IGxlbiA9IHNkc2xlbihzKTsKICAgIHNoID0gKGNoYXIqKXMtc2RzSGRyU2l6ZShvbGR0eXBlKTsKCiAgICB0eXBlID0gc2RzUmVxVHlwZShsZW4pOwogICAgaGRybGVuID0gc2RzSGRyU2l6ZSh0eXBlKTsKICAgIGlmIChvbGR0eXBlPT10eXBlKSB7CiAgICAgICAgbmV3c2ggPSBzX3JlYWxsb2Moc2gsIGhkcmxlbitsZW4rMSk7CiAgICAgICAgaWYgKG5ld3NoID09IE5VTEwpIHJldHVybiBOVUxMOwogICAgICAgIHMgPSAoY2hhciopbmV3c2graGRybGVuOwogICAgfSBlbHNlIHsKICAgICAgICBuZXdzaCA9IHNfbWFsbG9jKGhkcmxlbitsZW4rMSk7CiAgICAgICAgaWYgKG5ld3NoID09IE5VTEwpIHJldHVybiBOVUxMOwogICAgICAgIG1lbWNweSgoY2hhciopbmV3c2graGRybGVuLCBzLCBsZW4rMSk7CiAgICAgICAgc19mcmVlKHNoKTsKICAgICAgICBzID0gKGNoYXIqKW5ld3NoK2hkcmxlbjsKICAgICAgICBzWy0xXSA9IHR5cGU7CiAgICAgICAgc2Rzc2V0bGVuKHMsIGxlbik7CiAgICB9CiAgICBzZHNzZXRhbGxvYyhzLCBsZW4pOwogICAgcmV0dXJuIHM7Cn0KCi8qIFJldHVybiB0aGUgdG90YWwgc2l6ZSBvZiB0aGUgYWxsb2NhdGlvbiBvZiB0aGUgc3BlY2lmZWQgc2RzIHN0cmluZywKICogaW5jbHVkaW5nOgogKiAxKSBUaGUgc2RzIGhlYWRlciBiZWZvcmUgdGhlIHBvaW50ZXIuCiAqIDIpIFRoZSBzdHJpbmcuCiAqIDMpIFRoZSBmcmVlIGJ1ZmZlciBhdCB0aGUgZW5kIGlmIGFueS4KICogNCkgVGhlIGltcGxpY2l0IG51bGwgdGVybS4KICovCnNpemVfdCBzZHNBbGxvY1NpemUoc2RzIHMpIHsKICAgIHNpemVfdCBhbGxvYyA9IHNkc2FsbG9jKHMpOwogICAgcmV0dXJuIHNkc0hkclNpemUoc1stMV0pK2FsbG9jKzE7Cn0KCi8qIFJldHVybiB0aGUgcG9pbnRlciBvZiB0aGUgYWN0dWFsIFNEUyBhbGxvY2F0aW9uIChub3JtYWxseSBTRFMgc3RyaW5ncwogKiBhcmUgcmVmZXJlbmNlZCBieSB0aGUgc3RhcnQgb2YgdGhlIHN0cmluZyBidWZmZXIpLiAqLwp2b2lkICpzZHNBbGxvY1B0cihzZHMgcykgewogICAgcmV0dXJuICh2b2lkKikgKHMtc2RzSGRyU2l6ZShzWy0xXSkpOwp9CgovKiBJbmNyZW1lbnQgdGhlIHNkcyBsZW5ndGggYW5kIGRlY3JlbWVudHMgdGhlIGxlZnQgZnJlZSBzcGFjZSBhdCB0aGUKICogZW5kIG9mIHRoZSBzdHJpbmcgYWNjb3JkaW5nIHRvICdpbmNyJy4gQWxzbyBzZXQgdGhlIG51bGwgdGVybQogKiBpbiB0aGUgbmV3IGVuZCBvZiB0aGUgc3RyaW5nLgogKgogKiBUaGlzIGZ1bmN0aW9uIGlzIHVzZWQgaW4gb3JkZXIgdG8gZml4IHRoZSBzdHJpbmcgbGVuZ3RoIGFmdGVyIHRoZQogKiB1c2VyIGNhbGxzIHNkc01ha2VSb29tRm9yKCksIHdyaXRlcyBzb21ldGhpbmcgYWZ0ZXIgdGhlIGVuZCBvZgogKiB0aGUgY3VycmVudCBzdHJpbmcsIGFuZCBmaW5hbGx5IG5lZWRzIHRvIHNldCB0aGUgbmV3IGxlbmd0aC4KICoKICogTm90ZTogaXQgaXMgcG9zc2libGUgdG8gdXNlIGEgbmVnYXRpdmUgaW5jcmVtZW50IGluIG9yZGVyIHRvCiAqIHJpZ2h0LXRyaW0gdGhlIHN0cmluZy4KICoKICogVXNhZ2UgZXhhbXBsZToKICoKICogVXNpbmcgc2RzSW5jckxlbigpIGFuZCBzZHNNYWtlUm9vbUZvcigpIGl0IGlzIHBvc3NpYmxlIHRvIG1vdW50IHRoZQogKiBmb2xsb3dpbmcgc2NoZW1hLCB0byBjYXQgYnl0ZXMgY29taW5nIGZyb20gdGhlIGtlcm5lbCB0byB0aGUgZW5kIG9mIGFuCiAqIHNkcyBzdHJpbmcgd2l0aG91dCBjb3B5aW5nIGludG8gYW4gaW50ZXJtZWRpYXRlIGJ1ZmZlcjoKICoKICogb2xkbGVuID0gc2RzbGVuKHMpOwogKiBzID0gc2RzTWFrZVJvb21Gb3IocywgQlVGRkVSX1NJWkUpOwogKiBucmVhZCA9IHJlYWQoZmQsIHMrb2xkbGVuLCBCVUZGRVJfU0laRSk7CiAqIC4uLiBjaGVjayBmb3IgbnJlYWQgPD0gMCBhbmQgaGFuZGxlIGl0IC4uLgogKiBzZHNJbmNyTGVuKHMsIG5yZWFkKTsKICovCnZvaWQgc2RzSW5jckxlbihzZHMgcywgaW50IGluY3IpIHsKICAgIHVuc2lnbmVkIGNoYXIgZmxhZ3MgPSBzWy0xXTsKICAgIHNpemVfdCBsZW47CiAgICBzd2l0Y2goZmxhZ3MmU0RTX1RZUEVfTUFTSykgewogICAgICAgIGNhc2UgU0RTX1RZUEVfNTogewogICAgICAgICAgICB1bnNpZ25lZCBjaGFyICpmcCA9ICgodW5zaWduZWQgY2hhciopcyktMTsKICAgICAgICAgICAgdW5zaWduZWQgY2hhciBvbGRsZW4gPSBTRFNfVFlQRV81X0xFTihmbGFncyk7CiAgICAgICAgICAgIGFzc2VydCgoaW5jciA+IDAgJiYgb2xkbGVuK2luY3IgPCAzMikgfHwgKGluY3IgPCAwICYmIG9sZGxlbiA+PSAodW5zaWduZWQgaW50KSgtaW5jcikpKTsKICAgICAgICAgICAgKmZwID0gU0RTX1RZUEVfNSB8ICgob2xkbGVuK2luY3IpIDw8IFNEU19UWVBFX0JJVFMpOwogICAgICAgICAgICBsZW4gPSBvbGRsZW4raW5jcjsKICAgICAgICAgICAgYnJlYWs7CiAgICAgICAgfQogICAgICAgIGNhc2UgU0RTX1RZUEVfODogewogICAgICAgICAgICBTRFNfSERSX1ZBUig4LHMpOwogICAgICAgICAgICBhc3NlcnQoKGluY3IgPj0gMCAmJiBzaC0+YWxsb2Mtc2gtPmxlbiA+PSBpbmNyKSB8fCAoaW5jciA8IDAgJiYgc2gtPmxlbiA+PSAodW5zaWduZWQgaW50KSgtaW5jcikpKTsKICAgICAgICAgICAgbGVuID0gKHNoLT5sZW4gKz0gaW5jcik7CiAgICAgICAgICAgIGJyZWFrOwogICAgICAgIH0KICAgICAgICBjYXNlIFNEU19UWVBFXzE2OiB7CiAgICAgICAgICAgIFNEU19IRFJfVkFSKDE2LHMpOwogICAgICAgICAgICBhc3NlcnQoKGluY3IgPj0gMCAmJiBzaC0+YWxsb2Mtc2gtPmxlbiA+PSBpbmNyKSB8fCAoaW5jciA8IDAgJiYgc2gtPmxlbiA+PSAodW5zaWduZWQgaW50KSgtaW5jcikpKTsKICAgICAgICAgICAgbGVuID0gKHNoLT5sZW4gKz0gaW5jcik7CiAgICAgICAgICAgIGJyZWFrOwogICAgICAgIH0KICAgICAgICBjYXNlIFNEU19UWVBFXzMyOiB7CiAgICAgICAgICAgIFNEU19IRFJfVkFSKDMyLHMpOwogICAgICAgICAgICBhc3NlcnQoKGluY3IgPj0gMCAmJiBzaC0+YWxsb2Mtc2gtPmxlbiA+PSAodW5zaWduZWQgaW50KWluY3IpIHx8IChpbmNyIDwgMCAmJiBzaC0+bGVuID49ICh1bnNpZ25lZCBpbnQpKC1pbmNyKSkpOwogICAgICAgICAgICBsZW4gPSAoc2gtPmxlbiArPSBpbmNyKTsKICAgICAgICAgICAgYnJlYWs7CiAgICAgICAgfQogICAgICAgIGNhc2UgU0RTX1RZUEVfNjQ6IHsKICAgICAgICAgICAgU0RTX0hEUl9WQVIoNjQscyk7CiAgICAgICAgICAgIGFzc2VydCgoaW5jciA+PSAwICYmIHNoLT5hbGxvYy1zaC0+bGVuID49ICh1aW50NjRfdClpbmNyKSB8fCAoaW5jciA8IDAgJiYgc2gtPmxlbiA+PSAodWludDY0X3QpKC1pbmNyKSkpOwogICAgICAgICAgICBsZW4gPSAoc2gtPmxlbiArPSBpbmNyKTsKICAgICAgICAgICAgYnJlYWs7CiAgICAgICAgfQogICAgICAgIGRlZmF1bHQ6IGxlbiA9IDA7IC8qIEp1c3QgdG8gYXZvaWQgY29tcGlsYXRpb24gd2FybmluZ3MuICovCiAgICB9CiAgICBzW2xlbl0gPSAnXDAnOwp9CgovKiBHcm93IHRoZSBzZHMgdG8gaGF2ZSB0aGUgc3BlY2lmaWVkIGxlbmd0aC4gQnl0ZXMgdGhhdCB3ZXJlIG5vdCBwYXJ0IG9mCiAqIHRoZSBvcmlnaW5hbCBsZW5ndGggb2YgdGhlIHNkcyB3aWxsIGJlIHNldCB0byB6ZXJvLgogKgogKiBpZiB0aGUgc3BlY2lmaWVkIGxlbmd0aCBpcyBzbWFsbGVyIHRoYW4gdGhlIGN1cnJlbnQgbGVuZ3RoLCBubyBvcGVyYXRpb24KICogaXMgcGVyZm9ybWVkLiAqLwpzZHMgc2RzZ3Jvd3plcm8oc2RzIHMsIHNpemVfdCBsZW4pIHsKICAgIHNpemVfdCBjdXJsZW4gPSBzZHNsZW4ocyk7CgogICAgaWYgKGxlbiA8PSBjdXJsZW4pIHJldHVybiBzOwogICAgcyA9IHNkc01ha2VSb29tRm9yKHMsbGVuLWN1cmxlbik7CiAgICBpZiAocyA9PSBOVUxMKSByZXR1cm4gTlVMTDsKCiAgICAvKiBNYWtlIHN1cmUgYWRkZWQgcmVnaW9uIGRvZXNuJ3QgY29udGFpbiBnYXJiYWdlICovCiAgICBtZW1zZXQocytjdXJsZW4sMCwobGVuLWN1cmxlbisxKSk7IC8qIGFsc28gc2V0IHRyYWlsaW5nIFwwIGJ5dGUgKi8KICAgIHNkc3NldGxlbihzLCBsZW4pOwogICAgcmV0dXJuIHM7Cn0KCi8qIEFwcGVuZCB0aGUgc3BlY2lmaWVkIGJpbmFyeS1zYWZlIHN0cmluZyBwb2ludGVkIGJ5ICd0JyBvZiAnbGVuJyBieXRlcyB0byB0aGUKICogZW5kIG9mIHRoZSBzcGVjaWZpZWQgc2RzIHN0cmluZyAncycuCiAqCiAqIEFmdGVyIHRoZSBjYWxsLCB0aGUgcGFzc2VkIHNkcyBzdHJpbmcgaXMgbm8gbG9uZ2VyIHZhbGlkIGFuZCBhbGwgdGhlCiAqIHJlZmVyZW5jZXMgbXVzdCBiZSBzdWJzdGl0dXRlZCB3aXRoIHRoZSBuZXcgcG9pbnRlciByZXR1cm5lZCBieSB0aGUgY2FsbC4gKi8Kc2RzIHNkc2NhdGxlbihzZHMgcywgY29uc3Qgdm9pZCAqdCwgc2l6ZV90IGxlbikgewogICAgc2l6ZV90IGN1cmxlbiA9IHNkc2xlbihzKTsKCiAgICBzID0gc2RzTWFrZVJvb21Gb3IocyxsZW4pOwogICAgaWYgKHMgPT0gTlVMTCkgcmV0dXJuIE5VTEw7CiAgICBtZW1jcHkocytjdXJsZW4sIHQsIGxlbik7CiAgICBzZHNzZXRsZW4ocywgY3VybGVuK2xlbik7CiAgICBzW2N1cmxlbitsZW5dID0gJ1wwJzsKICAgIHJldHVybiBzOwp9CgovKiBBcHBlbmQgdGhlIHNwZWNpZmllZCBudWxsIHRlcm1pYW50ZWQgQyBzdHJpbmcgdG8gdGhlIHNkcyBzdHJpbmcgJ3MnLgogKgogKiBBZnRlciB0aGUgY2FsbCwgdGhlIHBhc3NlZCBzZHMgc3RyaW5nIGlzIG5vIGxvbmdlciB2YWxpZCBhbmQgYWxsIHRoZQogKiByZWZlcmVuY2VzIG11c3QgYmUgc3Vic3RpdHV0ZWQgd2l0aCB0aGUgbmV3IHBvaW50ZXIgcmV0dXJuZWQgYnkgdGhlIGNhbGwuICovCnNkcyBzZHNjYXQoc2RzIHMsIGNvbnN0IGNoYXIgKnQpIHsKICAgIHJldHVybiBzZHNjYXRsZW4ocywgdCwgc3RybGVuKHQpKTsKfQoKLyogQXBwZW5kIHRoZSBzcGVjaWZpZWQgc2RzICd0JyB0byB0aGUgZXhpc3Rpbmcgc2RzICdzJy4KICoKICogQWZ0ZXIgdGhlIGNhbGwsIHRoZSBtb2RpZmllZCBzZHMgc3RyaW5nIGlzIG5vIGxvbmdlciB2YWxpZCBhbmQgYWxsIHRoZQogKiByZWZlcmVuY2VzIG11c3QgYmUgc3Vic3RpdHV0ZWQgd2l0aCB0aGUgbmV3IHBvaW50ZXIgcmV0dXJuZWQgYnkgdGhlIGNhbGwuICovCnNkcyBzZHNjYXRzZHMoc2RzIHMsIGNvbnN0IHNkcyB0KSB7CiAgICByZXR1cm4gc2RzY2F0bGVuKHMsIHQsIHNkc2xlbih0KSk7Cn0KCi8qIERlc3RydWN0aXZlbHkgbW9kaWZ5IHRoZSBzZHMgc3RyaW5nICdzJyB0byBob2xkIHRoZSBzcGVjaWZpZWQgYmluYXJ5CiAqIHNhZmUgc3RyaW5nIHBvaW50ZWQgYnkgJ3QnIG9mIGxlbmd0aCAnbGVuJyBieXRlcy4gKi8Kc2RzIHNkc2NweWxlbihzZHMgcywgY29uc3QgY2hhciAqdCwgc2l6ZV90IGxlbikgewogICAgaWYgKHNkc2FsbG9jKHMpIDwgbGVuKSB7CiAgICAgICAgcyA9IHNkc01ha2VSb29tRm9yKHMsbGVuLXNkc2xlbihzKSk7CiAgICAgICAgaWYgKHMgPT0gTlVMTCkgcmV0dXJuIE5VTEw7CiAgICB9CiAgICBtZW1jcHkocywgdCwgbGVuKTsKICAgIHNbbGVuXSA9ICdcMCc7CiAgICBzZHNzZXRsZW4ocywgbGVuKTsKICAgIHJldHVybiBzOwp9CgovKiBMaWtlIHNkc2NweWxlbigpIGJ1dCAndCcgbXVzdCBiZSBhIG51bGwtdGVybWluYXRlZCBzdHJpbmcgc28gdGhhdCB0aGUgbGVuZ3RoCiAqIG9mIHRoZSBzdHJpbmcgaXMgb2J0YWluZWQgd2l0aCBzdHJsZW4oKS4gKi8Kc2RzIHNkc2NweShzZHMgcywgY29uc3QgY2hhciAqdCkgewogICAgcmV0dXJuIHNkc2NweWxlbihzLCB0LCBzdHJsZW4odCkpOwp9CgovKiBIZWxwZXIgZm9yIHNkc2NhdGxvbmdsb25nKCkgZG9pbmcgdGhlIGFjdHVhbCBudW1iZXIgLT4gc3RyaW5nCiAqIGNvbnZlcnNpb24uICdzJyBtdXN0IHBvaW50IHRvIGEgc3RyaW5nIHdpdGggcm9vbSBmb3IgYXQgbGVhc3QKICogU0RTX0xMU1RSX1NJWkUgYnl0ZXMuCiAqCiAqIFRoZSBmdW5jdGlvbiByZXR1cm5zIHRoZSBsZW5ndGggb2YgdGhlIG51bGwtdGVybWluYXRlZCBzdHJpbmcKICogcmVwcmVzZW50YXRpb24gc3RvcmVkIGF0ICdzJy4gKi8KI2RlZmluZSBTRFNfTExTVFJfU0laRSAyMQppbnQgc2RzbGwyc3RyKGNoYXIgKnMsIGxvbmcgbG9uZyB2YWx1ZSkgewogICAgY2hhciAqcCwgYXV4OwogICAgdW5zaWduZWQgbG9uZyBsb25nIHY7CiAgICBzaXplX3QgbDsKCiAgICAvKiBHZW5lcmF0ZSB0aGUgc3RyaW5nIHJlcHJlc2VudGF0aW9uLCB0aGlzIG1ldGhvZCBwcm9kdWNlcwogICAgICogYW4gcmV2ZXJzZWQgc3RyaW5nLiAqLwogICAgdiA9ICh2YWx1ZSA8IDApID8gLXZhbHVlIDogdmFsdWU7CiAgICBwID0gczsKICAgIGRvIHsKICAgICAgICAqcCsrID0gJzAnKyh2JTEwKTsKICAgICAgICB2IC89IDEwOwogICAgfSB3aGlsZSh2KTsKICAgIGlmICh2YWx1ZSA8IDApICpwKysgPSAnLSc7CgogICAgLyogQ29tcHV0ZSBsZW5ndGggYW5kIGFkZCBudWxsIHRlcm0uICovCiAgICBsID0gcC1zOwogICAgKnAgPSAnXDAnOwoKICAgIC8qIFJldmVyc2UgdGhlIHN0cmluZy4gKi8KICAgIHAtLTsKICAgIHdoaWxlKHMgPCBwKSB7CiAgICAgICAgYXV4ID0gKnM7CiAgICAgICAgKnMgPSAqcDsKICAgICAgICAqcCA9IGF1eDsKICAgICAgICBzKys7CiAgICAgICAgcC0tOwogICAgfQogICAgcmV0dXJuIGw7Cn0KCi8qIElkZW50aWNhbCBzZHNsbDJzdHIoKSwgYnV0IGZvciB1bnNpZ25lZCBsb25nIGxvbmcgdHlwZS4gKi8KaW50IHNkc3VsbDJzdHIoY2hhciAqcywgdW5zaWduZWQgbG9uZyBsb25nIHYpIHsKICAgIGNoYXIgKnAsIGF1eDsKICAgIHNpemVfdCBsOwoKICAgIC8qIEdlbmVyYXRlIHRoZSBzdHJpbmcgcmVwcmVzZW50YXRpb24sIHRoaXMgbWV0aG9kIHByb2R1Y2VzCiAgICAgKiBhbiByZXZlcnNlZCBzdHJpbmcuICovCiAgICBwID0gczsKICAgIGRvIHsKICAgICAgICAqcCsrID0gJzAnKyh2JTEwKTsKICAgICAgICB2IC89IDEwOwogICAgfSB3aGlsZSh2KTsKCiAgICAvKiBDb21wdXRlIGxlbmd0aCBhbmQgYWRkIG51bGwgdGVybS4gKi8KICAgIGwgPSBwLXM7CiAgICAqcCA9ICdcMCc7CgogICAgLyogUmV2ZXJzZSB0aGUgc3RyaW5nLiAqLwogICAgcC0tOwogICAgd2hpbGUocyA8IHApIHsKICAgICAgICBhdXggPSAqczsKICAgICAgICAqcyA9ICpwOwogICAgICAgICpwID0gYXV4OwogICAgICAgIHMrKzsKICAgICAgICBwLS07CiAgICB9CiAgICByZXR1cm4gbDsKfQoKLyogQ3JlYXRlIGFuIHNkcyBzdHJpbmcgZnJvbSBhIGxvbmcgbG9uZyB2YWx1ZS4gSXQgaXMgbXVjaCBmYXN0ZXIgdGhhbjoKICoKICogc2RzY2F0cHJpbnRmKHNkc2VtcHR5KCksIiVsbGRcbiIsIHZhbHVlKTsKICovCnNkcyBzZHNmcm9tbG9uZ2xvbmcobG9uZyBsb25nIHZhbHVlKSB7CiAgICBjaGFyIGJ1ZltTRFNfTExTVFJfU0laRV07CiAgICBpbnQgbGVuID0gc2RzbGwyc3RyKGJ1Zix2YWx1ZSk7CgogICAgcmV0dXJuIHNkc25ld2xlbihidWYsbGVuKTsKfQoKLyogTGlrZSBzZHNjYXRwcmludGYoKSBidXQgZ2V0cyB2YV9saXN0IGluc3RlYWQgb2YgYmVpbmcgdmFyaWFkaWMuICovCnNkcyBzZHNjYXR2cHJpbnRmKHNkcyBzLCBjb25zdCBjaGFyICpmbXQsIHZhX2xpc3QgYXApIHsKICAgIHZhX2xpc3QgY3B5OwogICAgY2hhciBzdGF0aWNidWZbMTAyNF0sICpidWYgPSBzdGF0aWNidWYsICp0OwogICAgc2l6ZV90IGJ1ZmxlbiA9IHN0cmxlbihmbXQpKjI7CgogICAgLyogV2UgdHJ5IHRvIHN0YXJ0IHVzaW5nIGEgc3RhdGljIGJ1ZmZlciBmb3Igc3BlZWQuCiAgICAgKiBJZiBub3QgcG9zc2libGUgd2UgcmV2ZXJ0IHRvIGhlYXAgYWxsb2NhdGlvbi4gKi8KICAgIGlmIChidWZsZW4gPiBzaXplb2Yoc3RhdGljYnVmKSkgewogICAgICAgIGJ1ZiA9IHNfbWFsbG9jKGJ1Zmxlbik7CiAgICAgICAgaWYgKGJ1ZiA9PSBOVUxMKSByZXR1cm4gTlVMTDsKICAgIH0gZWxzZSB7CiAgICAgICAgYnVmbGVuID0gc2l6ZW9mKHN0YXRpY2J1Zik7CiAgICB9CgogICAgLyogVHJ5IHdpdGggYnVmZmVycyB0d28gdGltZXMgYmlnZ2VyIGV2ZXJ5IHRpbWUgd2UgZmFpbCB0bwogICAgICogZml0IHRoZSBzdHJpbmcgaW4gdGhlIGN1cnJlbnQgYnVmZmVyIHNpemUuICovCiAgICB3aGlsZSgxKSB7CiAgICAgICAgYnVmW2J1Zmxlbi0yXSA9ICdcMCc7CiAgICAgICAgdmFfY29weShjcHksYXApOwogICAgICAgIHZzbnByaW50ZihidWYsIGJ1ZmxlbiwgZm10LCBjcHkpOwogICAgICAgIHZhX2VuZChjcHkpOwogICAgICAgIGlmIChidWZbYnVmbGVuLTJdICE9ICdcMCcpIHsKICAgICAgICAgICAgaWYgKGJ1ZiAhPSBzdGF0aWNidWYpIHNfZnJlZShidWYpOwogICAgICAgICAgICBidWZsZW4gKj0gMjsKICAgICAgICAgICAgYnVmID0gc19tYWxsb2MoYnVmbGVuKTsKICAgICAgICAgICAgaWYgKGJ1ZiA9PSBOVUxMKSByZXR1cm4gTlVMTDsKICAgICAgICAgICAgY29udGludWU7CiAgICAgICAgfQogICAgICAgIGJyZWFrOwogICAgfQoKICAgIC8qIEZpbmFsbHkgY29uY2F0IHRoZSBvYnRhaW5lZCBzdHJpbmcgdG8gdGhlIFNEUyBzdHJpbmcgYW5kIHJldHVybiBpdC4gKi8KICAgIHQgPSBzZHNjYXQocywgYnVmKTsKICAgIGlmIChidWYgIT0gc3RhdGljYnVmKSBzX2ZyZWUoYnVmKTsKICAgIHJldHVybiB0Owp9CgovKiBBcHBlbmQgdG8gdGhlIHNkcyBzdHJpbmcgJ3MnIGEgc3RyaW5nIG9idGFpbmVkIHVzaW5nIHByaW50Zi1hbGlrZSBmb3JtYXQKICogc3BlY2lmaWVyLgogKgogKiBBZnRlciB0aGUgY2FsbCwgdGhlIG1vZGlmaWVkIHNkcyBzdHJpbmcgaXMgbm8gbG9uZ2VyIHZhbGlkIGFuZCBhbGwgdGhlCiAqIHJlZmVyZW5jZXMgbXVzdCBiZSBzdWJzdGl0dXRlZCB3aXRoIHRoZSBuZXcgcG9pbnRlciByZXR1cm5lZCBieSB0aGUgY2FsbC4KICoKICogRXhhbXBsZToKICoKICogcyA9IHNkc25ldygiU3VtIGlzOiAiKTsKICogcyA9IHNkc2NhdHByaW50ZihzLCIlZCslZCA9ICVkIixhLGIsYStiKS4KICoKICogT2Z0ZW4geW91IG5lZWQgdG8gY3JlYXRlIGEgc3RyaW5nIGZyb20gc2NyYXRjaCB3aXRoIHRoZSBwcmludGYtYWxpa2UKICogZm9ybWF0LiBXaGVuIHRoaXMgaXMgdGhlIG5lZWQsIGp1c3QgdXNlIHNkc2VtcHR5KCkgYXMgdGhlIHRhcmdldCBzdHJpbmc6CiAqCiAqIHMgPSBzZHNjYXRwcmludGYoc2RzZW1wdHkoKSwgIi4uLiB5b3VyIGZvcm1hdCAuLi4iLCBhcmdzKTsKICovCnNkcyBzZHNjYXRwcmludGYoc2RzIHMsIGNvbnN0IGNoYXIgKmZtdCwgLi4uKSB7CiAgICB2YV9saXN0IGFwOwogICAgY2hhciAqdDsKICAgIHZhX3N0YXJ0KGFwLCBmbXQpOwogICAgdCA9IHNkc2NhdHZwcmludGYocyxmbXQsYXApOwogICAgdmFfZW5kKGFwKTsKICAgIHJldHVybiB0Owp9CgovKiBUaGlzIGZ1bmN0aW9uIGlzIHNpbWlsYXIgdG8gc2RzY2F0cHJpbnRmLCBidXQgbXVjaCBmYXN0ZXIgYXMgaXQgZG9lcwogKiBub3QgcmVseSBvbiBzcHJpbnRmKCkgZmFtaWx5IGZ1bmN0aW9ucyBpbXBsZW1lbnRlZCBieSB0aGUgbGliYyB0aGF0CiAqIGFyZSBvZnRlbiB2ZXJ5IHNsb3cuIE1vcmVvdmVyIGRpcmVjdGx5IGhhbmRsaW5nIHRoZSBzZHMgc3RyaW5nIGFzCiAqIG5ldyBkYXRhIGlzIGNvbmNhdGVuYXRlZCBwcm92aWRlcyBhIHBlcmZvcm1hbmNlIGltcHJvdmVtZW50LgogKgogKiBIb3dldmVyIHRoaXMgZnVuY3Rpb24gb25seSBoYW5kbGVzIGFuIGluY29tcGF0aWJsZSBzdWJzZXQgb2YgcHJpbnRmLWFsaWtlCiAqIGZvcm1hdCBzcGVjaWZpZXJzOgogKgogKiAlcyAtIEMgU3RyaW5nCiAqICVTIC0gU0RTIHN0cmluZwogKiAlaSAtIHNpZ25lZCBpbnQKICogJUkgLSA2NCBiaXQgc2lnbmVkIGludGVnZXIgKGxvbmcgbG9uZywgaW50NjRfdCkKICogJXUgLSB1bnNpZ25lZCBpbnQKICogJVUgLSA2NCBiaXQgdW5zaWduZWQgaW50ZWdlciAodW5zaWduZWQgbG9uZyBsb25nLCB1aW50NjRfdCkKICogJSUgLSBWZXJiYXRpbSAiJSIgY2hhcmFjdGVyLgogKi8Kc2RzIHNkc2NhdGZtdChzZHMgcywgY2hhciBjb25zdCAqZm10LCAuLi4pIHsKICAgIGNvbnN0IGNoYXIgKmYgPSBmbXQ7CiAgICBsb25nIGk7CiAgICB2YV9saXN0IGFwOwoKICAgIHZhX3N0YXJ0KGFwLGZtdCk7CiAgICBpID0gc2RzbGVuKHMpOyAvKiBQb3NpdGlvbiBvZiB0aGUgbmV4dCBieXRlIHRvIHdyaXRlIHRvIGRlc3Qgc3RyLiAqLwogICAgd2hpbGUoKmYpIHsKICAgICAgICBjaGFyIG5leHQsICpzdHI7CiAgICAgICAgc2l6ZV90IGw7CiAgICAgICAgbG9uZyBsb25nIG51bTsKICAgICAgICB1bnNpZ25lZCBsb25nIGxvbmcgdW51bTsKCiAgICAgICAgLyogTWFrZSBzdXJlIHRoZXJlIGlzIGFsd2F5cyBzcGFjZSBmb3IgYXQgbGVhc3QgMSBjaGFyLiAqLwogICAgICAgIGlmIChzZHNhdmFpbChzKT09MCkgewogICAgICAgICAgICBzID0gc2RzTWFrZVJvb21Gb3IocywxKTsKICAgICAgICAgICAgaWYgKHMgPT0gTlVMTCkgZ290byBmbXRfZXJyb3I7CiAgICAgICAgfQoKICAgICAgICBzd2l0Y2goKmYpIHsKICAgICAgICBjYXNlICclJzoKICAgICAgICAgICAgbmV4dCA9ICooZisxKTsKICAgICAgICAgICAgZisrOwogICAgICAgICAgICBzd2l0Y2gobmV4dCkgewogICAgICAgICAgICBjYXNlICdzJzoKICAgICAgICAgICAgY2FzZSAnUyc6CiAgICAgICAgICAgICAgICBzdHIgPSB2YV9hcmcoYXAsY2hhciopOwogICAgICAgICAgICAgICAgbCA9IChuZXh0ID09ICdzJykgPyBzdHJsZW4oc3RyKSA6IHNkc2xlbihzdHIpOwogICAgICAgICAgICAgICAgaWYgKHNkc2F2YWlsKHMpIDwgbCkgewogICAgICAgICAgICAgICAgICAgIHMgPSBzZHNNYWtlUm9vbUZvcihzLGwpOwogICAgICAgICAgICAgICAgICAgIGlmIChzID09IE5VTEwpIGdvdG8gZm10X2Vycm9yOwogICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICAgbWVtY3B5KHMraSxzdHIsbCk7CiAgICAgICAgICAgICAgICBzZHNpbmNsZW4ocyxsKTsKICAgICAgICAgICAgICAgIGkgKz0gbDsKICAgICAgICAgICAgICAgIGJyZWFrOwogICAgICAgICAgICBjYXNlICdpJzoKICAgICAgICAgICAgY2FzZSAnSSc6CiAgICAgICAgICAgICAgICBpZiAobmV4dCA9PSAnaScpCiAgICAgICAgICAgICAgICAgICAgbnVtID0gdmFfYXJnKGFwLGludCk7CiAgICAgICAgICAgICAgICBlbHNlCiAgICAgICAgICAgICAgICAgICAgbnVtID0gdmFfYXJnKGFwLGxvbmcgbG9uZyk7CiAgICAgICAgICAgICAgICB7CiAgICAgICAgICAgICAgICAgICAgY2hhciBidWZbU0RTX0xMU1RSX1NJWkVdOwogICAgICAgICAgICAgICAgICAgIGwgPSBzZHNsbDJzdHIoYnVmLG51bSk7CiAgICAgICAgICAgICAgICAgICAgaWYgKHNkc2F2YWlsKHMpIDwgbCkgewogICAgICAgICAgICAgICAgICAgICAgICBzID0gc2RzTWFrZVJvb21Gb3IocyxsKTsKICAgICAgICAgICAgICAgICAgICAgICAgaWYgKHMgPT0gTlVMTCkgZ290byBmbXRfZXJyb3I7CiAgICAgICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICAgICAgIG1lbWNweShzK2ksYnVmLGwpOwogICAgICAgICAgICAgICAgICAgIHNkc2luY2xlbihzLGwpOwogICAgICAgICAgICAgICAgICAgIGkgKz0gbDsKICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgIGJyZWFrOwogICAgICAgICAgICBjYXNlICd1JzoKICAgICAgICAgICAgY2FzZSAnVSc6CiAgICAgICAgICAgICAgICBpZiAobmV4dCA9PSAndScpCiAgICAgICAgICAgICAgICAgICAgdW51bSA9IHZhX2FyZyhhcCx1bnNpZ25lZCBpbnQpOwogICAgICAgICAgICAgICAgZWxzZQogICAgICAgICAgICAgICAgICAgIHVudW0gPSB2YV9hcmcoYXAsdW5zaWduZWQgbG9uZyBsb25nKTsKICAgICAgICAgICAgICAgIHsKICAgICAgICAgICAgICAgICAgICBjaGFyIGJ1ZltTRFNfTExTVFJfU0laRV07CiAgICAgICAgICAgICAgICAgICAgbCA9IHNkc3VsbDJzdHIoYnVmLHVudW0pOwogICAgICAgICAgICAgICAgICAgIGlmIChzZHNhdmFpbChzKSA8IGwpIHsKICAgICAgICAgICAgICAgICAgICAgICAgcyA9IHNkc01ha2VSb29tRm9yKHMsbCk7CiAgICAgICAgICAgICAgICAgICAgICAgIGlmIChzID09IE5VTEwpIGdvdG8gZm10X2Vycm9yOwogICAgICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgICAgICBtZW1jcHkocytpLGJ1ZixsKTsKICAgICAgICAgICAgICAgICAgICBzZHNpbmNsZW4ocyxsKTsKICAgICAgICAgICAgICAgICAgICBpICs9IGw7CiAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICBicmVhazsKICAgICAgICAgICAgZGVmYXVsdDogLyogSGFuZGxlICUlIGFuZCBnZW5lcmFsbHkgJTx1bmtub3duPi4gKi8KICAgICAgICAgICAgICAgIHNbaSsrXSA9IG5leHQ7CiAgICAgICAgICAgICAgICBzZHNpbmNsZW4ocywxKTsKICAgICAgICAgICAgICAgIGJyZWFrOwogICAgICAgICAgICB9CiAgICAgICAgICAgIGJyZWFrOwogICAgICAgIGRlZmF1bHQ6CiAgICAgICAgICAgIHNbaSsrXSA9ICpmOwogICAgICAgICAgICBzZHNpbmNsZW4ocywxKTsKICAgICAgICAgICAgYnJlYWs7CiAgICAgICAgfQogICAgICAgIGYrKzsKICAgIH0KICAgIHZhX2VuZChhcCk7CgogICAgLyogQWRkIG51bGwtdGVybSAqLwogICAgc1tpXSA9ICdcMCc7CiAgICByZXR1cm4gczsKCmZtdF9lcnJvcjoKICAgIHZhX2VuZChhcCk7CiAgICByZXR1cm4gTlVMTDsKfQoKLyogUmVtb3ZlIHRoZSBwYXJ0IG9mIHRoZSBzdHJpbmcgZnJvbSBsZWZ0IGFuZCBmcm9tIHJpZ2h0IGNvbXBvc2VkIGp1c3Qgb2YKICogY29udGlndW91cyBjaGFyYWN0ZXJzIGZvdW5kIGluICdjc2V0JywgdGhhdCBpcyBhIG51bGwgdGVybWludGVkIEMgc3RyaW5nLgogKgogKiBBZnRlciB0aGUgY2FsbCwgdGhlIG1vZGlmaWVkIHNkcyBzdHJpbmcgaXMgbm8gbG9uZ2VyIHZhbGlkIGFuZCBhbGwgdGhlCiAqIHJlZmVyZW5jZXMgbXVzdCBiZSBzdWJzdGl0dXRlZCB3aXRoIHRoZSBuZXcgcG9pbnRlciByZXR1cm5lZCBieSB0aGUgY2FsbC4KICoKICogRXhhbXBsZToKICoKICogcyA9IHNkc25ldygiQUEuLi5BQS5hLmFhLmFIZWxsb1dvcmxkICAgICA6OjoiKTsKICogcyA9IHNkc3RyaW0ocywiQWEuIDoiKTsKICogcHJpbnRmKCIlc1xuIiwgcyk7CiAqCiAqIE91dHB1dCB3aWxsIGJlIGp1c3QgIkhlbGxvIFdvcmxkIi4KICovCnNkcyBzZHN0cmltKHNkcyBzLCBjb25zdCBjaGFyICpjc2V0KSB7CiAgICBjaGFyICplbmQsICpzcCwgKmVwOwogICAgc2l6ZV90IGxlbjsKCiAgICBzcCA9IHM7CiAgICBlcCA9IGVuZCA9IHMrc2RzbGVuKHMpLTE7CiAgICB3aGlsZShzcCA8PSBlbmQgJiYgc3RyY2hyKGNzZXQsICpzcCkpIHNwKys7CiAgICB3aGlsZShlcCA+IHNwICYmIHN0cmNocihjc2V0LCAqZXApKSBlcC0tOwogICAgbGVuID0gKHNwID4gZXApID8gMCA6ICgoZXAtc3ApKzEpOwogICAgaWYgKHMgIT0gc3ApIG1lbW1vdmUocywgc3AsIGxlbik7CiAgICBzW2xlbl0gPSAnXDAnOwogICAgc2Rzc2V0bGVuKHMsbGVuKTsKICAgIHJldHVybiBzOwp9CgovKiBUdXJuIHRoZSBzdHJpbmcgaW50byBhIHNtYWxsZXIgKG9yIGVxdWFsKSBzdHJpbmcgY29udGFpbmluZyBvbmx5IHRoZQogKiBzdWJzdHJpbmcgc3BlY2lmaWVkIGJ5IHRoZSAnc3RhcnQnIGFuZCAnZW5kJyBpbmRleGVzLgogKgogKiBzdGFydCBhbmQgZW5kIGNhbiBiZSBuZWdhdGl2ZSwgd2hlcmUgLTEgbWVhbnMgdGhlIGxhc3QgY2hhcmFjdGVyIG9mIHRoZQogKiBzdHJpbmcsIC0yIHRoZSBwZW51bHRpbWF0ZSBjaGFyYWN0ZXIsIGFuZCBzbyBmb3J0aC4KICoKICogVGhlIGludGVydmFsIGlzIGluY2x1c2l2ZSwgc28gdGhlIHN0YXJ0IGFuZCBlbmQgY2hhcmFjdGVycyB3aWxsIGJlIHBhcnQKICogb2YgdGhlIHJlc3VsdGluZyBzdHJpbmcuCiAqCiAqIFRoZSBzdHJpbmcgaXMgbW9kaWZpZWQgaW4tcGxhY2UuCiAqCiAqIFJldHVybiB2YWx1ZToKICogLTEgKGVycm9yKSBpZiBzZHNsZW4ocykgaXMgbGFyZ2VyIHRoYW4gbWF4aW11bSBwb3NpdGl2ZSBzc2l6ZV90IHZhbHVlLgogKiAgMCBvbiBzdWNjZXNzLgogKgogKiBFeGFtcGxlOgogKgogKiBzID0gc2RzbmV3KCJIZWxsbyBXb3JsZCIpOwogKiBzZHNyYW5nZShzLDEsLTEpOyA9PiAiZWxsbyBXb3JsZCIKICovCmludCBzZHNyYW5nZShzZHMgcywgc3NpemVfdCBzdGFydCwgc3NpemVfdCBlbmQpIHsKICAgIHNpemVfdCBuZXdsZW4sIGxlbiA9IHNkc2xlbihzKTsKICAgIGlmIChsZW4gPiBTU0laRV9NQVgpIHJldHVybiAtMTsKCiAgICBpZiAobGVuID09IDApIHJldHVybiAwOwogICAgaWYgKHN0YXJ0IDwgMCkgewogICAgICAgIHN0YXJ0ID0gbGVuK3N0YXJ0OwogICAgICAgIGlmIChzdGFydCA8IDApIHN0YXJ0ID0gMDsKICAgIH0KICAgIGlmIChlbmQgPCAwKSB7CiAgICAgICAgZW5kID0gbGVuK2VuZDsKICAgICAgICBpZiAoZW5kIDwgMCkgZW5kID0gMDsKICAgIH0KICAgIG5ld2xlbiA9IChzdGFydCA+IGVuZCkgPyAwIDogKGVuZC1zdGFydCkrMTsKICAgIGlmIChuZXdsZW4gIT0gMCkgewogICAgICAgIGlmIChzdGFydCA+PSAoc3NpemVfdClsZW4pIHsKICAgICAgICAgICAgbmV3bGVuID0gMDsKICAgICAgICB9IGVsc2UgaWYgKGVuZCA+PSAoc3NpemVfdClsZW4pIHsKICAgICAgICAgICAgZW5kID0gbGVuLTE7CiAgICAgICAgICAgIG5ld2xlbiA9IChzdGFydCA+IGVuZCkgPyAwIDogKGVuZC1zdGFydCkrMTsKICAgICAgICB9CiAgICB9IGVsc2UgewogICAgICAgIHN0YXJ0ID0gMDsKICAgIH0KICAgIGlmIChzdGFydCAmJiBuZXdsZW4pIG1lbW1vdmUocywgcytzdGFydCwgbmV3bGVuKTsKICAgIHNbbmV3bGVuXSA9IDA7CiAgICBzZHNzZXRsZW4ocyxuZXdsZW4pOwogICAgcmV0dXJuIDA7Cn0KCi8qIEFwcGx5IHRvbG93ZXIoKSB0byBldmVyeSBjaGFyYWN0ZXIgb2YgdGhlIHNkcyBzdHJpbmcgJ3MnLiAqLwp2b2lkIHNkc3RvbG93ZXIoc2RzIHMpIHsKICAgIHNpemVfdCBsZW4gPSBzZHNsZW4ocyksIGo7CgogICAgZm9yIChqID0gMDsgaiA8IGxlbjsgaisrKSBzW2pdID0gdG9sb3dlcihzW2pdKTsKfQoKLyogQXBwbHkgdG91cHBlcigpIHRvIGV2ZXJ5IGNoYXJhY3RlciBvZiB0aGUgc2RzIHN0cmluZyAncycuICovCnZvaWQgc2RzdG91cHBlcihzZHMgcykgewogICAgc2l6ZV90IGxlbiA9IHNkc2xlbihzKSwgajsKCiAgICBmb3IgKGogPSAwOyBqIDwgbGVuOyBqKyspIHNbal0gPSB0b3VwcGVyKHNbal0pOwp9CgovKiBDb21wYXJlIHR3byBzZHMgc3RyaW5ncyBzMSBhbmQgczIgd2l0aCBtZW1jbXAoKS4KICoKICogUmV0dXJuIHZhbHVlOgogKgogKiAgICAgcG9zaXRpdmUgaWYgczEgPiBzMi4KICogICAgIG5lZ2F0aXZlIGlmIHMxIDwgczIuCiAqICAgICAwIGlmIHMxIGFuZCBzMiBhcmUgZXhhY3RseSB0aGUgc2FtZSBiaW5hcnkgc3RyaW5nLgogKgogKiBJZiB0d28gc3RyaW5ncyBzaGFyZSBleGFjdGx5IHRoZSBzYW1lIHByZWZpeCwgYnV0IG9uZSBvZiB0aGUgdHdvIGhhcwogKiBhZGRpdGlvbmFsIGNoYXJhY3RlcnMsIHRoZSBsb25nZXIgc3RyaW5nIGlzIGNvbnNpZGVyZWQgdG8gYmUgZ3JlYXRlciB0aGFuCiAqIHRoZSBzbWFsbGVyIG9uZS4gKi8KaW50IHNkc2NtcChjb25zdCBzZHMgczEsIGNvbnN0IHNkcyBzMikgewogICAgc2l6ZV90IGwxLCBsMiwgbWlubGVuOwogICAgaW50IGNtcDsKCiAgICBsMSA9IHNkc2xlbihzMSk7CiAgICBsMiA9IHNkc2xlbihzMik7CiAgICBtaW5sZW4gPSAobDEgPCBsMikgPyBsMSA6IGwyOwogICAgY21wID0gbWVtY21wKHMxLHMyLG1pbmxlbik7CiAgICBpZiAoY21wID09IDApIHJldHVybiBsMS1sMjsKICAgIHJldHVybiBjbXA7Cn0KCi8qIFNwbGl0ICdzJyB3aXRoIHNlcGFyYXRvciBpbiAnc2VwJy4gQW4gYXJyYXkKICogb2Ygc2RzIHN0cmluZ3MgaXMgcmV0dXJuZWQuICpjb3VudCB3aWxsIGJlIHNldAogKiBieSByZWZlcmVuY2UgdG8gdGhlIG51bWJlciBvZiB0b2tlbnMgcmV0dXJuZWQuCiAqCiAqIE9uIG91dCBvZiBtZW1vcnksIHplcm8gbGVuZ3RoIHN0cmluZywgemVybyBsZW5ndGgKICogc2VwYXJhdG9yLCBOVUxMIGlzIHJldHVybmVkLgogKgogKiBOb3RlIHRoYXQgJ3NlcCcgaXMgYWJsZSB0byBzcGxpdCBhIHN0cmluZyB1c2luZwogKiBhIG11bHRpLWNoYXJhY3RlciBzZXBhcmF0b3IuIEZvciBleGFtcGxlCiAqIHNkc3NwbGl0KCJmb29fLV9iYXIiLCJfLV8iKTsgd2lsbCByZXR1cm4gdHdvCiAqIGVsZW1lbnRzICJmb28iIGFuZCAiYmFyIi4KICoKICogVGhpcyB2ZXJzaW9uIG9mIHRoZSBmdW5jdGlvbiBpcyBiaW5hcnktc2FmZSBidXQKICogcmVxdWlyZXMgbGVuZ3RoIGFyZ3VtZW50cy4gc2Rzc3BsaXQoKSBpcyBqdXN0IHRoZQogKiBzYW1lIGZ1bmN0aW9uIGJ1dCBmb3IgemVyby10ZXJtaW5hdGVkIHN0cmluZ3MuCiAqLwpzZHMgKnNkc3NwbGl0bGVuKGNvbnN0IGNoYXIgKnMsIGludCBsZW4sIGNvbnN0IGNoYXIgKnNlcCwgaW50IHNlcGxlbiwgaW50ICpjb3VudCkgewogICAgaW50IGVsZW1lbnRzID0gMCwgc2xvdHMgPSA1LCBzdGFydCA9IDAsIGo7CiAgICBzZHMgKnRva2VuczsKCiAgICBpZiAoc2VwbGVuIDwgMSB8fCBsZW4gPCAwKSByZXR1cm4gTlVMTDsKCiAgICB0b2tlbnMgPSBzX21hbGxvYyhzaXplb2Yoc2RzKSpzbG90cyk7CiAgICBpZiAodG9rZW5zID09IE5VTEwpIHJldHVybiBOVUxMOwoKICAgIGlmIChsZW4gPT0gMCkgewogICAgICAgICpjb3VudCA9IDA7CiAgICAgICAgcmV0dXJuIHRva2VuczsKICAgIH0KICAgIGZvciAoaiA9IDA7IGogPCAobGVuLShzZXBsZW4tMSkpOyBqKyspIHsKICAgICAgICAvKiBtYWtlIHN1cmUgdGhlcmUgaXMgcm9vbSBmb3IgdGhlIG5leHQgZWxlbWVudCBhbmQgdGhlIGZpbmFsIG9uZSAqLwogICAgICAgIGlmIChzbG90cyA8IGVsZW1lbnRzKzIpIHsKICAgICAgICAgICAgc2RzICpuZXd0b2tlbnM7CgogICAgICAgICAgICBzbG90cyAqPSAyOwogICAgICAgICAgICBuZXd0b2tlbnMgPSBzX3JlYWxsb2ModG9rZW5zLHNpemVvZihzZHMpKnNsb3RzKTsKICAgICAgICAgICAgaWYgKG5ld3Rva2VucyA9PSBOVUxMKSBnb3RvIGNsZWFudXA7CiAgICAgICAgICAgIHRva2VucyA9IG5ld3Rva2VuczsKICAgICAgICB9CiAgICAgICAgLyogc2VhcmNoIHRoZSBzZXBhcmF0b3IgKi8KICAgICAgICBpZiAoKHNlcGxlbiA9PSAxICYmICoocytqKSA9PSBzZXBbMF0pIHx8IChtZW1jbXAocytqLHNlcCxzZXBsZW4pID09IDApKSB7CiAgICAgICAgICAgIHRva2Vuc1tlbGVtZW50c10gPSBzZHNuZXdsZW4ocytzdGFydCxqLXN0YXJ0KTsKICAgICAgICAgICAgaWYgKHRva2Vuc1tlbGVtZW50c10gPT0gTlVMTCkgZ290byBjbGVhbnVwOwogICAgICAgICAgICBlbGVtZW50cysrOwogICAgICAgICAgICBzdGFydCA9IGorc2VwbGVuOwogICAgICAgICAgICBqID0gaitzZXBsZW4tMTsgLyogc2tpcCB0aGUgc2VwYXJhdG9yICovCiAgICAgICAgfQogICAgfQogICAgLyogQWRkIHRoZSBmaW5hbCBlbGVtZW50LiBXZSBhcmUgc3VyZSB0aGVyZSBpcyByb29tIGluIHRoZSB0b2tlbnMgYXJyYXkuICovCiAgICB0b2tlbnNbZWxlbWVudHNdID0gc2RzbmV3bGVuKHMrc3RhcnQsbGVuLXN0YXJ0KTsKICAgIGlmICh0b2tlbnNbZWxlbWVudHNdID09IE5VTEwpIGdvdG8gY2xlYW51cDsKICAgIGVsZW1lbnRzKys7CiAgICAqY291bnQgPSBlbGVtZW50czsKICAgIHJldHVybiB0b2tlbnM7CgpjbGVhbnVwOgogICAgewogICAgICAgIGludCBpOwogICAgICAgIGZvciAoaSA9IDA7IGkgPCBlbGVtZW50czsgaSsrKSBzZHNmcmVlKHRva2Vuc1tpXSk7CiAgICAgICAgc19mcmVlKHRva2Vucyk7CiAgICAgICAgKmNvdW50ID0gMDsKICAgICAgICByZXR1cm4gTlVMTDsKICAgIH0KfQoKLyogRnJlZSB0aGUgcmVzdWx0IHJldHVybmVkIGJ5IHNkc3NwbGl0bGVuKCksIG9yIGRvIG5vdGhpbmcgaWYgJ3Rva2VucycgaXMgTlVMTC4gKi8Kdm9pZCBzZHNmcmVlc3BsaXRyZXMoc2RzICp0b2tlbnMsIGludCBjb3VudCkgewogICAgaWYgKCF0b2tlbnMpIHJldHVybjsKICAgIHdoaWxlKGNvdW50LS0pCiAgICAgICAgc2RzZnJlZSh0b2tlbnNbY291bnRdKTsKICAgIHNfZnJlZSh0b2tlbnMpOwp9CgovKiBBcHBlbmQgdG8gdGhlIHNkcyBzdHJpbmcgInMiIGFuIGVzY2FwZWQgc3RyaW5nIHJlcHJlc2VudGF0aW9uIHdoZXJlCiAqIGFsbCB0aGUgbm9uLXByaW50YWJsZSBjaGFyYWN0ZXJzICh0ZXN0ZWQgd2l0aCBpc3ByaW50KCkpIGFyZSB0dXJuZWQgaW50bwogKiBlc2NhcGVzIGluIHRoZSBmb3JtICJcblxyXGEuLi4uIiBvciAiXHg8aGV4LW51bWJlcj4iLgogKgogKiBBZnRlciB0aGUgY2FsbCwgdGhlIG1vZGlmaWVkIHNkcyBzdHJpbmcgaXMgbm8gbG9uZ2VyIHZhbGlkIGFuZCBhbGwgdGhlCiAqIHJlZmVyZW5jZXMgbXVzdCBiZSBzdWJzdGl0dXRlZCB3aXRoIHRoZSBuZXcgcG9pbnRlciByZXR1cm5lZCBieSB0aGUgY2FsbC4gKi8Kc2RzIHNkc2NhdHJlcHIoc2RzIHMsIGNvbnN0IGNoYXIgKnAsIHNpemVfdCBsZW4pIHsKICAgIHMgPSBzZHNjYXRsZW4ocywiXCIiLDEpOwogICAgd2hpbGUobGVuLS0pIHsKICAgICAgICBzd2l0Y2goKnApIHsKICAgICAgICBjYXNlICdcXCc6CiAgICAgICAgY2FzZSAnIic6CiAgICAgICAgICAgIHMgPSBzZHNjYXRwcmludGYocywiXFwlYyIsKnApOwogICAgICAgICAgICBicmVhazsKICAgICAgICBjYXNlICdcbic6IHMgPSBzZHNjYXRsZW4ocywiXFxuIiwyKTsgYnJlYWs7CiAgICAgICAgY2FzZSAnXHInOiBzID0gc2RzY2F0bGVuKHMsIlxcciIsMik7IGJyZWFrOwogICAgICAgIGNhc2UgJ1x0JzogcyA9IHNkc2NhdGxlbihzLCJcXHQiLDIpOyBicmVhazsKICAgICAgICBjYXNlICdcYSc6IHMgPSBzZHNjYXRsZW4ocywiXFxhIiwyKTsgYnJlYWs7CiAgICAgICAgY2FzZSAnXGInOiBzID0gc2RzY2F0bGVuKHMsIlxcYiIsMik7IGJyZWFrOwogICAgICAgIGRlZmF1bHQ6CiAgICAgICAgICAgIGlmIChpc3ByaW50KChpbnQpICpwKSkKICAgICAgICAgICAgICAgIHMgPSBzZHNjYXRwcmludGYocywiJWMiLCpwKTsKICAgICAgICAgICAgZWxzZQogICAgICAgICAgICAgICAgcyA9IHNkc2NhdHByaW50ZihzLCJcXHglMDJ4IiwodW5zaWduZWQgY2hhcikqcCk7CiAgICAgICAgICAgIGJyZWFrOwogICAgICAgIH0KICAgICAgICBwKys7CiAgICB9CiAgICByZXR1cm4gc2RzY2F0bGVuKHMsIlwiIiwxKTsKfQoKLyogSGVscGVyIGZ1bmN0aW9uIGZvciBzZHNzcGxpdGFyZ3MoKSB0aGF0IGNvbnZlcnRzIGEgaGV4IGRpZ2l0IGludG8gYW4KICogaW50ZWdlciBmcm9tIDAgdG8gMTUgKi8KaW50IGhleF9kaWdpdF90b19pbnQoY2hhciBjKSB7CiAgICBzd2l0Y2goYykgewogICAgY2FzZSAnMCc6IHJldHVybiAwOwogICAgY2FzZSAnMSc6IHJldHVybiAxOwogICAgY2FzZSAnMic6IHJldHVybiAyOwogICAgY2FzZSAnMyc6IHJldHVybiAzOwogICAgY2FzZSAnNCc6IHJldHVybiA0OwogICAgY2FzZSAnNSc6IHJldHVybiA1OwogICAgY2FzZSAnNic6IHJldHVybiA2OwogICAgY2FzZSAnNyc6IHJldHVybiA3OwogICAgY2FzZSAnOCc6IHJldHVybiA4OwogICAgY2FzZSAnOSc6IHJldHVybiA5OwogICAgY2FzZSAnYSc6IGNhc2UgJ0EnOiByZXR1cm4gMTA7CiAgICBjYXNlICdiJzogY2FzZSAnQic6IHJldHVybiAxMTsKICAgIGNhc2UgJ2MnOiBjYXNlICdDJzogcmV0dXJuIDEyOwogICAgY2FzZSAnZCc6IGNhc2UgJ0QnOiByZXR1cm4gMTM7CiAgICBjYXNlICdlJzogY2FzZSAnRSc6IHJldHVybiAxNDsKICAgIGNhc2UgJ2YnOiBjYXNlICdGJzogcmV0dXJuIDE1OwogICAgZGVmYXVsdDogcmV0dXJuIDA7CiAgICB9Cn0KCi8qIFNwbGl0IGEgbGluZSBpbnRvIGFyZ3VtZW50cywgd2hlcmUgZXZlcnkgYXJndW1lbnQgY2FuIGJlIGluIHRoZQogKiBmb2xsb3dpbmcgcHJvZ3JhbW1pbmctbGFuZ3VhZ2UgUkVQTC1hbGlrZSBmb3JtOgogKgogKiBmb28gYmFyICJuZXdsaW5lIGFyZSBzdXBwb3J0ZWRcbiIgYW5kICJceGZmXHgwMG90aGVyc3R1ZmYiCiAqCiAqIFRoZSBudW1iZXIgb2YgYXJndW1lbnRzIGlzIHN0b3JlZCBpbnRvICphcmdjLCBhbmQgYW4gYXJyYXkKICogb2Ygc2RzIGlzIHJldHVybmVkLgogKgogKiBUaGUgY2FsbGVyIHNob3VsZCBmcmVlIHRoZSByZXN1bHRpbmcgYXJyYXkgb2Ygc2RzIHN0cmluZ3Mgd2l0aAogKiBzZHNmcmVlc3BsaXRyZXMoKS4KICoKICogTm90ZSB0aGF0IHNkc2NhdHJlcHIoKSBpcyBhYmxlIHRvIGNvbnZlcnQgYmFjayBhIHN0cmluZyBpbnRvCiAqIGEgcXVvdGVkIHN0cmluZyBpbiB0aGUgc2FtZSBmb3JtYXQgc2Rzc3BsaXRhcmdzKCkgaXMgYWJsZSB0byBwYXJzZS4KICoKICogVGhlIGZ1bmN0aW9uIHJldHVybnMgdGhlIGFsbG9jYXRlZCB0b2tlbnMgb24gc3VjY2VzcywgZXZlbiB3aGVuIHRoZQogKiBpbnB1dCBzdHJpbmcgaXMgZW1wdHksIG9yIE5VTEwgaWYgdGhlIGlucHV0IGNvbnRhaW5zIHVuYmFsYW5jZWQKICogcXVvdGVzIG9yIGNsb3NlZCBxdW90ZXMgZm9sbG93ZWQgYnkgbm9uIHNwYWNlIGNoYXJhY3RlcnMKICogYXMgaW46ICJmb28iYmFyIG9yICJmb28nCiAqLwpzZHMgKnNkc3NwbGl0YXJncyhjb25zdCBjaGFyICpsaW5lLCBpbnQgKmFyZ2MpIHsKICAgIGNvbnN0IGNoYXIgKnAgPSBsaW5lOwogICAgY2hhciAqY3VycmVudCA9IE5VTEw7CiAgICBjaGFyICoqdmVjdG9yID0gTlVMTDsKCiAgICAqYXJnYyA9IDA7CiAgICB3aGlsZSgxKSB7CiAgICAgICAgLyogc2tpcCBibGFua3MgKi8KICAgICAgICB3aGlsZSgqcCAmJiBpc3NwYWNlKChpbnQpICpwKSkgcCsrOwogICAgICAgIGlmICgqcCkgewogICAgICAgICAgICAvKiBnZXQgYSB0b2tlbiAqLwogICAgICAgICAgICBpbnQgaW5xPTA7ICAvKiBzZXQgdG8gMSBpZiB3ZSBhcmUgaW4gInF1b3RlcyIgKi8KICAgICAgICAgICAgaW50IGluc3E9MDsgLyogc2V0IHRvIDEgaWYgd2UgYXJlIGluICdzaW5nbGUgcXVvdGVzJyAqLwogICAgICAgICAgICBpbnQgZG9uZT0wOwoKICAgICAgICAgICAgaWYgKGN1cnJlbnQgPT0gTlVMTCkgY3VycmVudCA9IHNkc2VtcHR5KCk7CiAgICAgICAgICAgIHdoaWxlKCFkb25lKSB7CiAgICAgICAgICAgICAgICBpZiAoaW5xKSB7CiAgICAgICAgICAgICAgICAgICAgaWYgKCpwID09ICdcXCcgJiYgKihwKzEpID09ICd4JyAmJgogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBpc3hkaWdpdCgoaW50KSAqKHArMikpICYmCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGlzeGRpZ2l0KChpbnQpICoocCszKSkpCiAgICAgICAgICAgICAgICAgICAgewogICAgICAgICAgICAgICAgICAgICAgICB1bnNpZ25lZCBjaGFyIGJ5dGU7CgogICAgICAgICAgICAgICAgICAgICAgICBieXRlID0gKGhleF9kaWdpdF90b19pbnQoKihwKzIpKSoxNikrCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgaGV4X2RpZ2l0X3RvX2ludCgqKHArMykpOwogICAgICAgICAgICAgICAgICAgICAgICBjdXJyZW50ID0gc2RzY2F0bGVuKGN1cnJlbnQsKGNoYXIqKSZieXRlLDEpOwogICAgICAgICAgICAgICAgICAgICAgICBwICs9IDM7CiAgICAgICAgICAgICAgICAgICAgfSBlbHNlIGlmICgqcCA9PSAnXFwnICYmICoocCsxKSkgewogICAgICAgICAgICAgICAgICAgICAgICBjaGFyIGM7CgogICAgICAgICAgICAgICAgICAgICAgICBwKys7CiAgICAgICAgICAgICAgICAgICAgICAgIHN3aXRjaCgqcCkgewogICAgICAgICAgICAgICAgICAgICAgICBjYXNlICduJzogYyA9ICdcbic7IGJyZWFrOwogICAgICAgICAgICAgICAgICAgICAgICBjYXNlICdyJzogYyA9ICdccic7IGJyZWFrOwogICAgICAgICAgICAgICAgICAgICAgICBjYXNlICd0JzogYyA9ICdcdCc7IGJyZWFrOwogICAgICAgICAgICAgICAgICAgICAgICBjYXNlICdiJzogYyA9ICdcYic7IGJyZWFrOwogICAgICAgICAgICAgICAgICAgICAgICBjYXNlICdhJzogYyA9ICdcYSc7IGJyZWFrOwogICAgICAgICAgICAgICAgICAgICAgICBkZWZhdWx0OiBjID0gKnA7IGJyZWFrOwogICAgICAgICAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICAgICAgICAgIGN1cnJlbnQgPSBzZHNjYXRsZW4oY3VycmVudCwmYywxKTsKICAgICAgICAgICAgICAgICAgICB9IGVsc2UgaWYgKCpwID09ICciJykgewogICAgICAgICAgICAgICAgICAgICAgICAvKiBjbG9zaW5nIHF1b3RlIG11c3QgYmUgZm9sbG93ZWQgYnkgYSBzcGFjZSBvcgogICAgICAgICAgICAgICAgICAgICAgICAgKiBub3RoaW5nIGF0IGFsbC4gKi8KICAgICAgICAgICAgICAgICAgICAgICAgaWYgKCoocCsxKSAmJiAhaXNzcGFjZSgoaW50KSAqKHArMSkpKSBnb3RvIGVycjsKICAgICAgICAgICAgICAgICAgICAgICAgZG9uZT0xOwogICAgICAgICAgICAgICAgICAgIH0gZWxzZSBpZiAoISpwKSB7CiAgICAgICAgICAgICAgICAgICAgICAgIC8qIHVudGVybWluYXRlZCBxdW90ZXMgKi8KICAgICAgICAgICAgICAgICAgICAgICAgZ290byBlcnI7CiAgICAgICAgICAgICAgICAgICAgfSBlbHNlIHsKICAgICAgICAgICAgICAgICAgICAgICAgY3VycmVudCA9IHNkc2NhdGxlbihjdXJyZW50LHAsMSk7CiAgICAgICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICAgfSBlbHNlIGlmIChpbnNxKSB7CiAgICAgICAgICAgICAgICAgICAgaWYgKCpwID09ICdcXCcgJiYgKihwKzEpID09ICdcJycpIHsKICAgICAgICAgICAgICAgICAgICAgICAgcCsrOwogICAgICAgICAgICAgICAgICAgICAgICBjdXJyZW50ID0gc2RzY2F0bGVuKGN1cnJlbnQsIiciLDEpOwogICAgICAgICAgICAgICAgICAgIH0gZWxzZSBpZiAoKnAgPT0gJ1wnJykgewogICAgICAgICAgICAgICAgICAgICAgICAvKiBjbG9zaW5nIHF1b3RlIG11c3QgYmUgZm9sbG93ZWQgYnkgYSBzcGFjZSBvcgogICAgICAgICAgICAgICAgICAgICAgICAgKiBub3RoaW5nIGF0IGFsbC4gKi8KICAgICAgICAgICAgICAgICAgICAgICAgaWYgKCoocCsxKSAmJiAhaXNzcGFjZSgoaW50KSAqKHArMSkpKSBnb3RvIGVycjsKICAgICAgICAgICAgICAgICAgICAgICAgZG9uZT0xOwogICAgICAgICAgICAgICAgICAgIH0gZWxzZSBpZiAoISpwKSB7CiAgICAgICAgICAgICAgICAgICAgICAgIC8qIHVudGVybWluYXRlZCBxdW90ZXMgKi8KICAgICAgICAgICAgICAgICAgICAgICAgZ290byBlcnI7CiAgICAgICAgICAgICAgICAgICAgfSBlbHNlIHsKICAgICAgICAgICAgICAgICAgICAgICAgY3VycmVudCA9IHNkc2NhdGxlbihjdXJyZW50LHAsMSk7CiAgICAgICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICAgfSBlbHNlIHsKICAgICAgICAgICAgICAgICAgICBzd2l0Y2goKnApIHsKICAgICAgICAgICAgICAgICAgICBjYXNlICcgJzoKICAgICAgICAgICAgICAgICAgICBjYXNlICdcbic6CiAgICAgICAgICAgICAgICAgICAgY2FzZSAnXHInOgogICAgICAgICAgICAgICAgICAgIGNhc2UgJ1x0JzoKICAgICAgICAgICAgICAgICAgICBjYXNlICdcMCc6CiAgICAgICAgICAgICAgICAgICAgICAgIGRvbmU9MTsKICAgICAgICAgICAgICAgICAgICAgICAgYnJlYWs7CiAgICAgICAgICAgICAgICAgICAgY2FzZSAnIic6CiAgICAgICAgICAgICAgICAgICAgICAgIGlucT0xOwogICAgICAgICAgICAgICAgICAgICAgICBicmVhazsKICAgICAgICAgICAgICAgICAgICBjYXNlICdcJyc6CiAgICAgICAgICAgICAgICAgICAgICAgIGluc3E9MTsKICAgICAgICAgICAgICAgICAgICAgICAgYnJlYWs7CiAgICAgICAgICAgICAgICAgICAgZGVmYXVsdDoKICAgICAgICAgICAgICAgICAgICAgICAgY3VycmVudCA9IHNkc2NhdGxlbihjdXJyZW50LHAsMSk7CiAgICAgICAgICAgICAgICAgICAgICAgIGJyZWFrOwogICAgICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgIGlmICgqcCkgcCsrOwogICAgICAgICAgICB9CiAgICAgICAgICAgIC8qIGFkZCB0aGUgdG9rZW4gdG8gdGhlIHZlY3RvciAqLwogICAgICAgICAgICB7CiAgICAgICAgICAgICAgICBjaGFyICoqbmV3X3ZlY3RvciA9IHNfcmVhbGxvYyh2ZWN0b3IsKCgqYXJnYykrMSkqc2l6ZW9mKGNoYXIqKSk7CiAgICAgICAgICAgICAgICBpZiAobmV3X3ZlY3RvciA9PSBOVUxMKSB7CiAgICAgICAgICAgICAgICAgICAgc19mcmVlKHZlY3Rvcik7CiAgICAgICAgICAgICAgICAgICAgcmV0dXJuIE5VTEw7CiAgICAgICAgICAgICAgICB9CgogICAgICAgICAgICAgICAgdmVjdG9yID0gbmV3X3ZlY3RvcjsKICAgICAgICAgICAgICAgIHZlY3RvclsqYXJnY10gPSBjdXJyZW50OwogICAgICAgICAgICAgICAgKCphcmdjKSsrOwogICAgICAgICAgICAgICAgY3VycmVudCA9IE5VTEw7CiAgICAgICAgICAgIH0KICAgICAgICB9IGVsc2UgewogICAgICAgICAgICAvKiBFdmVuIG9uIGVtcHR5IGlucHV0IHN0cmluZyByZXR1cm4gc29tZXRoaW5nIG5vdCBOVUxMLiAqLwogICAgICAgICAgICBpZiAodmVjdG9yID09IE5VTEwpIHZlY3RvciA9IHNfbWFsbG9jKHNpemVvZih2b2lkKikpOwogICAgICAgICAgICByZXR1cm4gdmVjdG9yOwogICAgICAgIH0KICAgIH0KCmVycjoKICAgIHdoaWxlKCgqYXJnYyktLSkKICAgICAgICBzZHNmcmVlKHZlY3RvclsqYXJnY10pOwogICAgc19mcmVlKHZlY3Rvcik7CiAgICBpZiAoY3VycmVudCkgc2RzZnJlZShjdXJyZW50KTsKICAgICphcmdjID0gMDsKICAgIHJldHVybiBOVUxMOwp9CgovKiBNb2RpZnkgdGhlIHN0cmluZyBzdWJzdGl0dXRpbmcgYWxsIHRoZSBvY2N1cnJlbmNlcyBvZiB0aGUgc2V0IG9mCiAqIGNoYXJhY3RlcnMgc3BlY2lmaWVkIGluIHRoZSAnZnJvbScgc3RyaW5nIHRvIHRoZSBjb3JyZXNwb25kaW5nIGNoYXJhY3RlcgogKiBpbiB0aGUgJ3RvJyBhcnJheS4KICoKICogRm9yIGluc3RhbmNlOiBzZHNtYXBjaGFycyhteXN0cmluZywgImhvIiwgIjAxIiwgMikKICogd2lsbCBoYXZlIHRoZSBlZmZlY3Qgb2YgdHVybmluZyB0aGUgc3RyaW5nICJoZWxsbyIgaW50byAiMGVsbDEiLgogKgogKiBUaGUgZnVuY3Rpb24gcmV0dXJucyB0aGUgc2RzIHN0cmluZyBwb2ludGVyLCB0aGF0IGlzIGFsd2F5cyB0aGUgc2FtZQogKiBhcyB0aGUgaW5wdXQgcG9pbnRlciBzaW5jZSBubyByZXNpemUgaXMgbmVlZGVkLiAqLwpzZHMgc2RzbWFwY2hhcnMoc2RzIHMsIGNvbnN0IGNoYXIgKmZyb20sIGNvbnN0IGNoYXIgKnRvLCBzaXplX3Qgc2V0bGVuKSB7CiAgICBzaXplX3QgaiwgaSwgbCA9IHNkc2xlbihzKTsKCiAgICBmb3IgKGogPSAwOyBqIDwgbDsgaisrKSB7CiAgICAgICAgZm9yIChpID0gMDsgaSA8IHNldGxlbjsgaSsrKSB7CiAgICAgICAgICAgIGlmIChzW2pdID09IGZyb21baV0pIHsKICAgICAgICAgICAgICAgIHNbal0gPSB0b1tpXTsKICAgICAgICAgICAgICAgIGJyZWFrOwogICAgICAgICAgICB9CiAgICAgICAgfQogICAgfQogICAgcmV0dXJuIHM7Cn0KCi8qIEpvaW4gYW4gYXJyYXkgb2YgQyBzdHJpbmdzIHVzaW5nIHRoZSBzcGVjaWZpZWQgc2VwYXJhdG9yIChhbHNvIGEgQyBzdHJpbmcpLgogKiBSZXR1cm5zIHRoZSByZXN1bHQgYXMgYW4gc2RzIHN0cmluZy4gKi8Kc2RzIHNkc2pvaW4oY2hhciAqKmFyZ3YsIGludCBhcmdjLCBjaGFyICpzZXApIHsKICAgIHNkcyBqb2luID0gc2RzZW1wdHkoKTsKICAgIGludCBqOwoKICAgIGZvciAoaiA9IDA7IGogPCBhcmdjOyBqKyspIHsKICAgICAgICBqb2luID0gc2RzY2F0KGpvaW4sIGFyZ3Zbal0pOwogICAgICAgIGlmIChqICE9IGFyZ2MtMSkgam9pbiA9IHNkc2NhdChqb2luLHNlcCk7CiAgICB9CiAgICByZXR1cm4gam9pbjsKfQoKLyogTGlrZSBzZHNqb2luLCBidXQgam9pbnMgYW4gYXJyYXkgb2YgU0RTIHN0cmluZ3MuICovCnNkcyBzZHNqb2luc2RzKHNkcyAqYXJndiwgaW50IGFyZ2MsIGNvbnN0IGNoYXIgKnNlcCwgc2l6ZV90IHNlcGxlbikgewogICAgc2RzIGpvaW4gPSBzZHNlbXB0eSgpOwogICAgaW50IGo7CgogICAgZm9yIChqID0gMDsgaiA8IGFyZ2M7IGorKykgewogICAgICAgIGpvaW4gPSBzZHNjYXRzZHMoam9pbiwgYXJndltqXSk7CiAgICAgICAgaWYgKGogIT0gYXJnYy0xKSBqb2luID0gc2RzY2F0bGVuKGpvaW4sc2VwLHNlcGxlbik7CiAgICB9CiAgICByZXR1cm4gam9pbjsKfQoKLyogV3JhcHBlcnMgdG8gdGhlIGFsbG9jYXRvcnMgdXNlZCBieSBTRFMuIE5vdGUgdGhhdCBTRFMgd2lsbCBhY3R1YWxseQogKiBqdXN0IHVzZSB0aGUgbWFjcm9zIGRlZmluZWQgaW50byBzZHNhbGxvYy5oIGluIG9yZGVyIHRvIGF2b2lkIHRvIHBheQogKiB0aGUgb3ZlcmhlYWQgb2YgZnVuY3Rpb24gY2FsbHMuIEhlcmUgd2UgZGVmaW5lIHRoZXNlIHdyYXBwZXJzIG9ubHkgZm9yCiAqIHRoZSBwcm9ncmFtcyBTRFMgaXMgbGlua2VkIHRvLCBpZiB0aGV5IHdhbnQgdG8gdG91Y2ggdGhlIFNEUyBpbnRlcm5hbHMKICogZXZlbiBpZiB0aGV5IHVzZSBhIGRpZmZlcmVudCBhbGxvY2F0b3IuICovCnZvaWQgKnNkc19tYWxsb2Moc2l6ZV90IHNpemUpIHsgcmV0dXJuIHNfbWFsbG9jKHNpemUpOyB9CnZvaWQgKnNkc19yZWFsbG9jKHZvaWQgKnB0ciwgc2l6ZV90IHNpemUpIHsgcmV0dXJuIHNfcmVhbGxvYyhwdHIsc2l6ZSk7IH0Kdm9pZCBzZHNfZnJlZSh2b2lkICpwdHIpIHsgc19mcmVlKHB0cik7IH0KCiNpZiBkZWZpbmVkKFNEU19URVNUX01BSU4pCiNpbmNsdWRlIDxzdGRpby5oPgojaW5jbHVkZSAidGVzdGhlbHAuaCIKI2luY2x1ZGUgImxpbWl0cy5oIgoKI2RlZmluZSBVTlVTRUQoeCkgKHZvaWQpKHgpCmludCBzZHNUZXN0KHZvaWQpIHsKICAgIHsKICAgICAgICBzZHMgeCA9IHNkc25ldygiZm9vIiksIHk7CgogICAgICAgIHRlc3RfY29uZCgiQ3JlYXRlIGEgc3RyaW5nIGFuZCBvYnRhaW4gdGhlIGxlbmd0aCIsCiAgICAgICAgICAgIHNkc2xlbih4KSA9PSAzICYmIG1lbWNtcCh4LCJmb29cMCIsNCkgPT0gMCkKCiAgICAgICAgc2RzZnJlZSh4KTsKICAgICAgICB4ID0gc2RzbmV3bGVuKCJmb28iLDIpOwogICAgICAgIHRlc3RfY29uZCgiQ3JlYXRlIGEgc3RyaW5nIHdpdGggc3BlY2lmaWVkIGxlbmd0aCIsCiAgICAgICAgICAgIHNkc2xlbih4KSA9PSAyICYmIG1lbWNtcCh4LCJmb1wwIiwzKSA9PSAwKQoKICAgICAgICB4ID0gc2RzY2F0KHgsImJhciIpOwogICAgICAgIHRlc3RfY29uZCgiU3RyaW5ncyBjb25jYXRlbmF0aW9uIiwKICAgICAgICAgICAgc2RzbGVuKHgpID09IDUgJiYgbWVtY21wKHgsImZvYmFyXDAiLDYpID09IDApOwoKICAgICAgICB4ID0gc2RzY3B5KHgsImEiKTsKICAgICAgICB0ZXN0X2NvbmQoInNkc2NweSgpIGFnYWluc3QgYW4gb3JpZ2luYWxseSBsb25nZXIgc3RyaW5nIiwKICAgICAgICAgICAgc2RzbGVuKHgpID09IDEgJiYgbWVtY21wKHgsImFcMCIsMikgPT0gMCkKCiAgICAgICAgeCA9IHNkc2NweSh4LCJ4eXp4eHh4eHh4eHh4eXl5eXl5eXl5eWtra2tra2tra2siKTsKICAgICAgICB0ZXN0X2NvbmQoInNkc2NweSgpIGFnYWluc3QgYW4gb3JpZ2luYWxseSBzaG9ydGVyIHN0cmluZyIsCiAgICAgICAgICAgIHNkc2xlbih4KSA9PSAzMyAmJgogICAgICAgICAgICBtZW1jbXAoeCwieHl6eHh4eHh4eHh4eHl5eXl5eXl5eXlra2tra2tra2trXDAiLDMzKSA9PSAwKQoKICAgICAgICBzZHNmcmVlKHgpOwogICAgICAgIHggPSBzZHNjYXRwcmludGYoc2RzZW1wdHkoKSwiJWQiLDEyMyk7CiAgICAgICAgdGVzdF9jb25kKCJzZHNjYXRwcmludGYoKSBzZWVtcyB3b3JraW5nIGluIHRoZSBiYXNlIGNhc2UiLAogICAgICAgICAgICBzZHNsZW4oeCkgPT0gMyAmJiBtZW1jbXAoeCwiMTIzXDAiLDQpID09IDApCgogICAgICAgIHNkc2ZyZWUoeCk7CiAgICAgICAgeCA9IHNkc25ldygiLS0iKTsKICAgICAgICB4ID0gc2RzY2F0Zm10KHgsICJIZWxsbyAlcyBXb3JsZCAlSSwlSS0tIiwgIkhpISIsIExMT05HX01JTixMTE9OR19NQVgpOwogICAgICAgIHRlc3RfY29uZCgic2RzY2F0Zm10KCkgc2VlbXMgd29ya2luZyBpbiB0aGUgYmFzZSBjYXNlIiwKICAgICAgICAgICAgc2RzbGVuKHgpID09IDYwICYmCiAgICAgICAgICAgIG1lbWNtcCh4LCItLUhlbGxvIEhpISBXb3JsZCAtOTIyMzM3MjAzNjg1NDc3NTgwOCwiCiAgICAgICAgICAgICAgICAgICAgICI5MjIzMzcyMDM2ODU0Nzc1ODA3LS0iLDYwKSA9PSAwKQogICAgICAgIHByaW50ZigiWyVzXVxuIix4KTsKCiAgICAgICAgc2RzZnJlZSh4KTsKICAgICAgICB4ID0gc2RzbmV3KCItLSIpOwogICAgICAgIHggPSBzZHNjYXRmbXQoeCwgIiV1LCVVLS0iLCBVSU5UX01BWCwgVUxMT05HX01BWCk7CiAgICAgICAgdGVzdF9jb25kKCJzZHNjYXRmbXQoKSBzZWVtcyB3b3JraW5nIHdpdGggdW5zaWduZWQgbnVtYmVycyIsCiAgICAgICAgICAgIHNkc2xlbih4KSA9PSAzNSAmJgogICAgICAgICAgICBtZW1jbXAoeCwiLS00Mjk0OTY3Mjk1LDE4NDQ2NzQ0MDczNzA5NTUxNjE1LS0iLDM1KSA9PSAwKQoKICAgICAgICBzZHNmcmVlKHgpOwogICAgICAgIHggPSBzZHNuZXcoIiB4ICIpOwogICAgICAgIHNkc3RyaW0oeCwiIHgiKTsKICAgICAgICB0ZXN0X2NvbmQoInNkc3RyaW0oKSB3b3JrcyB3aGVuIGFsbCBjaGFycyBtYXRjaCIsCiAgICAgICAgICAgIHNkc2xlbih4KSA9PSAwKQoKICAgICAgICBzZHNmcmVlKHgpOwogICAgICAgIHggPSBzZHNuZXcoIiB4ICIpOwogICAgICAgIHNkc3RyaW0oeCwiICIpOwogICAgICAgIHRlc3RfY29uZCgic2RzdHJpbSgpIHdvcmtzIHdoZW4gYSBzaW5nbGUgY2hhciByZW1haW5zIiwKICAgICAgICAgICAgc2RzbGVuKHgpID09IDEgJiYgeFswXSA9PSAneCcpCgogICAgICAgIHNkc2ZyZWUoeCk7CiAgICAgICAgeCA9IHNkc25ldygieHhjaWFveXl5Iik7CiAgICAgICAgc2RzdHJpbSh4LCJ4eSIpOwogICAgICAgIHRlc3RfY29uZCgic2RzdHJpbSgpIGNvcnJlY3RseSB0cmltcyBjaGFyYWN0ZXJzIiwKICAgICAgICAgICAgc2RzbGVuKHgpID09IDQgJiYgbWVtY21wKHgsImNpYW9cMCIsNSkgPT0gMCkKCiAgICAgICAgeSA9IHNkc2R1cCh4KTsKICAgICAgICBzZHNyYW5nZSh5LDEsMSk7CiAgICAgICAgdGVzdF9jb25kKCJzZHNyYW5nZSguLi4sMSwxKSIsCiAgICAgICAgICAgIHNkc2xlbih5KSA9PSAxICYmIG1lbWNtcCh5LCJpXDAiLDIpID09IDApCgogICAgICAgIHNkc2ZyZWUoeSk7CiAgICAgICAgeSA9IHNkc2R1cCh4KTsKICAgICAgICBzZHNyYW5nZSh5LDEsLTEpOwogICAgICAgIHRlc3RfY29uZCgic2RzcmFuZ2UoLi4uLDEsLTEpIiwKICAgICAgICAgICAgc2RzbGVuKHkpID09IDMgJiYgbWVtY21wKHksImlhb1wwIiw0KSA9PSAwKQoKICAgICAgICBzZHNmcmVlKHkpOwogICAgICAgIHkgPSBzZHNkdXAoeCk7CiAgICAgICAgc2RzcmFuZ2UoeSwtMiwtMSk7CiAgICAgICAgdGVzdF9jb25kKCJzZHNyYW5nZSguLi4sLTIsLTEpIiwKICAgICAgICAgICAgc2RzbGVuKHkpID09IDIgJiYgbWVtY21wKHksImFvXDAiLDMpID09IDApCgogICAgICAgIHNkc2ZyZWUoeSk7CiAgICAgICAgeSA9IHNkc2R1cCh4KTsKICAgICAgICBzZHNyYW5nZSh5LDIsMSk7CiAgICAgICAgdGVzdF9jb25kKCJzZHNyYW5nZSguLi4sMiwxKSIsCiAgICAgICAgICAgIHNkc2xlbih5KSA9PSAwICYmIG1lbWNtcCh5LCJcMCIsMSkgPT0gMCkKCiAgICAgICAgc2RzZnJlZSh5KTsKICAgICAgICB5ID0gc2RzZHVwKHgpOwogICAgICAgIHNkc3JhbmdlKHksMSwxMDApOwogICAgICAgIHRlc3RfY29uZCgic2RzcmFuZ2UoLi4uLDEsMTAwKSIsCiAgICAgICAgICAgIHNkc2xlbih5KSA9PSAzICYmIG1lbWNtcCh5LCJpYW9cMCIsNCkgPT0gMCkKCiAgICAgICAgc2RzZnJlZSh5KTsKICAgICAgICB5ID0gc2RzZHVwKHgpOwogICAgICAgIHNkc3JhbmdlKHksMTAwLDEwMCk7CiAgICAgICAgdGVzdF9jb25kKCJzZHNyYW5nZSguLi4sMTAwLDEwMCkiLAogICAgICAgICAgICBzZHNsZW4oeSkgPT0gMCAmJiBtZW1jbXAoeSwiXDAiLDEpID09IDApCgogICAgICAgIHNkc2ZyZWUoeSk7CiAgICAgICAgc2RzZnJlZSh4KTsKICAgICAgICB4ID0gc2RzbmV3KCJmb28iKTsKICAgICAgICB5ID0gc2RzbmV3KCJmb2EiKTsKICAgICAgICB0ZXN0X2NvbmQoInNkc2NtcChmb28sZm9hKSIsIHNkc2NtcCh4LHkpID4gMCkKCiAgICAgICAgc2RzZnJlZSh5KTsKICAgICAgICBzZHNmcmVlKHgpOwogICAgICAgIHggPSBzZHNuZXcoImJhciIpOwogICAgICAgIHkgPSBzZHNuZXcoImJhciIpOwogICAgICAgIHRlc3RfY29uZCgic2RzY21wKGJhcixiYXIpIiwgc2RzY21wKHgseSkgPT0gMCkKCiAgICAgICAgc2RzZnJlZSh5KTsKICAgICAgICBzZHNmcmVlKHgpOwogICAgICAgIHggPSBzZHNuZXcoImFhciIpOwogICAgICAgIHkgPSBzZHNuZXcoImJhciIpOwogICAgICAgIHRlc3RfY29uZCgic2RzY21wKGJhcixiYXIpIiwgc2RzY21wKHgseSkgPCAwKQoKICAgICAgICBzZHNmcmVlKHkpOwogICAgICAgIHNkc2ZyZWUoeCk7CiAgICAgICAgeCA9IHNkc25ld2xlbigiXGFcblwwZm9vXHIiLDcpOwogICAgICAgIHkgPSBzZHNjYXRyZXByKHNkc2VtcHR5KCkseCxzZHNsZW4oeCkpOwogICAgICAgIHRlc3RfY29uZCgic2RzY2F0cmVwciguLi5kYXRhLi4uKSIsCiAgICAgICAgICAgIG1lbWNtcCh5LCJcIlxcYVxcblxceDAwZm9vXFxyXCIiLDE1KSA9PSAwKQoKICAgICAgICB7CiAgICAgICAgICAgIHVuc2lnbmVkIGludCBvbGRmcmVlOwogICAgICAgICAgICBjaGFyICpwOwogICAgICAgICAgICBpbnQgc3RlcCA9IDEwLCBqLCBpOwoKICAgICAgICAgICAgc2RzZnJlZSh4KTsKICAgICAgICAgICAgc2RzZnJlZSh5KTsKICAgICAgICAgICAgeCA9IHNkc25ldygiMCIpOwogICAgICAgICAgICB0ZXN0X2NvbmQoInNkc25ldygpIGZyZWUvbGVuIGJ1ZmZlcnMiLCBzZHNsZW4oeCkgPT0gMSAmJiBzZHNhdmFpbCh4KSA9PSAwKTsKCiAgICAgICAgICAgIC8qIFJ1biB0aGUgdGVzdCBhIGZldyB0aW1lcyBpbiBvcmRlciB0byBoaXQgdGhlIGZpcnN0IHR3bwogICAgICAgICAgICAgKiBTRFMgaGVhZGVyIHR5cGVzLiAqLwogICAgICAgICAgICBmb3IgKGkgPSAwOyBpIDwgMTA7IGkrKykgewogICAgICAgICAgICAgICAgaW50IG9sZGxlbiA9IHNkc2xlbih4KTsKICAgICAgICAgICAgICAgIHggPSBzZHNNYWtlUm9vbUZvcih4LHN0ZXApOwogICAgICAgICAgICAgICAgaW50IHR5cGUgPSB4Wy0xXSZTRFNfVFlQRV9NQVNLOwoKICAgICAgICAgICAgICAgIHRlc3RfY29uZCgic2RzTWFrZVJvb21Gb3IoKSBsZW4iLCBzZHNsZW4oeCkgPT0gb2xkbGVuKTsKICAgICAgICAgICAgICAgIGlmICh0eXBlICE9IFNEU19UWVBFXzUpIHsKICAgICAgICAgICAgICAgICAgICB0ZXN0X2NvbmQoInNkc01ha2VSb29tRm9yKCkgZnJlZSIsIHNkc2F2YWlsKHgpID49IHN0ZXApOwogICAgICAgICAgICAgICAgICAgIG9sZGZyZWUgPSBzZHNhdmFpbCh4KTsKICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgIHAgPSB4K29sZGxlbjsKICAgICAgICAgICAgICAgIGZvciAoaiA9IDA7IGogPCBzdGVwOyBqKyspIHsKICAgICAgICAgICAgICAgICAgICBwW2pdID0gJ0EnK2o7CiAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICBzZHNJbmNyTGVuKHgsc3RlcCk7CiAgICAgICAgICAgIH0KICAgICAgICAgICAgdGVzdF9jb25kKCJzZHNNYWtlUm9vbUZvcigpIGNvbnRlbnQiLAogICAgICAgICAgICAgICAgbWVtY21wKCIwQUJDREVGR0hJSkFCQ0RFRkdISUpBQkNERUZHSElKQUJDREVGR0hJSkFCQ0RFRkdISUpBQkNERUZHSElKQUJDREVGR0hJSkFCQ0RFRkdISUpBQkNERUZHSElKQUJDREVGR0hJSiIseCwxMDEpID09IDApOwogICAgICAgICAgICB0ZXN0X2NvbmQoInNkc01ha2VSb29tRm9yKCkgZmluYWwgbGVuZ3RoIixzZHNsZW4oeCk9PTEwMSk7CgogICAgICAgICAgICBzZHNmcmVlKHgpOwogICAgICAgIH0KICAgIH0KICAgIHRlc3RfcmVwb3J0KCkKICAgIHJldHVybiAwOwp9CiNlbmRpZgoKI2lmZGVmIFNEU19URVNUX01BSU4KaW50IG1haW4odm9pZCkgewogICAgcmV0dXJuIHNkc1Rlc3QoKTsKfQojZW5kaWYK",
  "content_kind": "blob",
  "content_length": 40557,
  "source_change_id": "e2c14c00e234abd7a8945cf1a5e5b1ce3e35b01a650311580e1fc47729132f0b",
  "text_utf8": "/* SDSLib 2.0 -- A C dynamic strings library\n *\n * Copyright (c) 2006-2015, Salvatore Sanfilippo <antirez at gmail dot com>\n * Copyright (c) 2015, Oran Agra\n * Copyright (c) 2015, Redis Labs, Inc\n * All rights reserved.\n *\n * Redistribution and use in source and binary forms, with or without\n * modification, are permitted provided that the following conditions are met:\n *\n *   * Redistributions of source code must retain the above copyright notice,\n *     this list of conditions and the following disclaimer.\n *   * Redistributions in binary form must reproduce the above copyright\n *     notice, this list of conditions and the following disclaimer in the\n *     documentation and/or other materials provided with the distribution.\n *   * Neither the name of Redis nor the names of its contributors may be used\n *     to endorse or promote products derived from this software without\n *     specific prior written permission.\n *\n * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS \"AS IS\"\n * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE\n * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE\n * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE\n * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR\n * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF\n * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS\n * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN\n * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)\n * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE\n * POSSIBILITY OF SUCH DAMAGE.\n */\n\n#include \"fmacros.h\"\n#include <stdio.h>\n#include <stdlib.h>\n#include <string.h>\n#include <ctype.h>\n#include <assert.h>\n#include <limits.h>\n#include \"sds.h\"\n#include \"sdsalloc.h\"\n\nstatic inline int sdsHdrSize(char type) {\n    switch(type&SDS_TYPE_MASK) {\n        case SDS_TYPE_5:\n            return sizeof(struct sdshdr5);\n        case SDS_TYPE_8:\n            return sizeof(struct sdshdr8);\n        case SDS_TYPE_16:\n            return sizeof(struct sdshdr16);\n        case SDS_TYPE_32:\n            return sizeof(struct sdshdr32);\n        case SDS_TYPE_64:\n            return sizeof(struct sdshdr64);\n    }\n    return 0;\n}\n\nstatic inline char sdsReqType(size_t string_size) {\n    if (string_size < 32)\n        return SDS_TYPE_5;\n    if (string_size < 0xff)\n        return SDS_TYPE_8;\n    if (string_size < 0xffff)\n        return SDS_TYPE_16;\n    if (string_size < 0xffffffff)\n        return SDS_TYPE_32;\n    return SDS_TYPE_64;\n}\n\n/* Create a new sds string with the content specified by the 'init' pointer\n * and 'initlen'.\n * If NULL is used for 'init' the string is initialized with zero bytes.\n *\n * The string is always null-terminated (all the sds strings are, always) so\n * even if you create an sds string with:\n *\n * mystring = sdsnewlen(\"abc\",3);\n *\n * You can print the string with printf() as there is an implicit \\0 at the\n * end of the string. However the string is binary safe and can contain\n * \\0 characters in the middle, as the length is stored in the sds header. */\nsds sdsnewlen(const void *init, size_t initlen) {\n    void *sh;\n    sds s;\n    char type = sdsReqType(initlen);\n    /* Empty strings are usually created in order to append. Use type 8\n     * since type 5 is not good at this. */\n    if (type == SDS_TYPE_5 && initlen == 0) type = SDS_TYPE_8;\n    int hdrlen = sdsHdrSize(type);\n    unsigned char *fp; /* flags pointer. */\n\n    if (hdrlen+initlen+1 <= initlen) return NULL; /* Catch size_t overflow */\n    sh = s_malloc(hdrlen+initlen+1);\n    if (sh == NULL) return NULL;\n    if (!init)\n        memset(sh, 0, hdrlen+initlen+1);\n    s = (char*)sh+hdrlen;\n    fp = ((unsigned char*)s)-1;\n    switch(type) {\n        case SDS_TYPE_5: {\n            *fp = type | (initlen << SDS_TYPE_BITS);\n            break;\n        }\n        case SDS_TYPE_8: {\n            SDS_HDR_VAR(8,s);\n            sh->len = initlen;\n            sh->alloc = initlen;\n            *fp = type;\n            break;\n        }\n        case SDS_TYPE_16: {\n            SDS_HDR_VAR(16,s);\n            sh->len = initlen;\n            sh->alloc = initlen;\n            *fp = type;\n            break;\n        }\n        case SDS_TYPE_32: {\n            SDS_HDR_VAR(32,s);\n            sh->len = initlen;\n            sh->alloc = initlen;\n            *fp = type;\n            break;\n        }\n        case SDS_TYPE_64: {\n            SDS_HDR_VAR(64,s);\n            sh->len = initlen;\n            sh->alloc = initlen;\n            *fp = type;\n            break;\n        }\n    }\n    if (initlen && init)\n        memcpy(s, init, initlen);\n    s[initlen] = '\\0';\n    return s;\n}\n\n/* Create an empty (zero length) sds string. Even in this case the string\n * always has an implicit null term. */\nsds sdsempty(void) {\n    return sdsnewlen(\"\",0);\n}\n\n/* Create a new sds string starting from a null terminated C string. */\nsds sdsnew(const char *init) {\n    size_t initlen = (init == NULL) ? 0 : strlen(init);\n    return sdsnewlen(init, initlen);\n}\n\n/* Duplicate an sds string. */\nsds sdsdup(const sds s) {\n    return sdsnewlen(s, sdslen(s));\n}\n\n/* Free an sds string. No operation is performed if 's' is NULL. */\nvoid sdsfree(sds s) {\n    if (s == NULL) return;\n    s_free((char*)s-sdsHdrSize(s[-1]));\n}\n\n/* Set the sds string length to the length as obtained with strlen(), so\n * considering as content only up to the first null term character.\n *\n * This function is useful when the sds string is hacked manually in some\n * way, like in the following example:\n *\n * s = sdsnew(\"foobar\");\n * s[2] = '\\0';\n * sdsupdatelen(s);\n * printf(\"%d\\n\", sdslen(s));\n *\n * The output will be \"2\", but if we comment out the call to sdsupdatelen()\n * the output will be \"6\" as the string was modified but the logical length\n * remains 6 bytes. */\nvoid sdsupdatelen(sds s) {\n    size_t reallen = strlen(s);\n    sdssetlen(s, reallen);\n}\n\n/* Modify an sds string in-place to make it empty (zero length).\n * However all the existing buffer is not discarded but set as free space\n * so that next append operations will not require allocations up to the\n * number of bytes previously available. */\nvoid sdsclear(sds s) {\n    sdssetlen(s, 0);\n    s[0] = '\\0';\n}\n\n/* Enlarge the free space at the end of the sds string so that the caller\n * is sure that after calling this function can overwrite up to addlen\n * bytes after the end of the string, plus one more byte for nul term.\n *\n * Note: this does not change the *length* of the sds string as returned\n * by sdslen(), but only the free buffer space we have. */\nsds sdsMakeRoomFor(sds s, size_t addlen) {\n    void *sh, *newsh;\n    size_t avail = sdsavail(s);\n    size_t len, newlen, required_len;\n    char type, oldtype = s[-1] & SDS_TYPE_MASK;\n    int hdrlen;\n\n    /* Return ASAP if there is enough space left. */\n    if (avail >= addlen) return s;\n\n    len = sdslen(s);\n    sh = (char*)s-sdsHdrSize(oldtype);\n    required_len = newlen = (len+addlen);\n    if (newlen <= len) return NULL; /* Catch size_t overflow */\n    if (newlen < SDS_MAX_PREALLOC)\n        newlen *= 2;\n    else\n        newlen += SDS_MAX_PREALLOC;\n\n    type = sdsReqType(newlen);\n\n    /* Don't use type 5: the user is appending to the string and type 5 is\n     * not able to remember empty space, so sdsMakeRoomFor() must be called\n     * at every appending operation. */\n    if (type == SDS_TYPE_5) type = SDS_TYPE_8;\n\n    hdrlen = sdsHdrSize(type);\n    if (hdrlen+newlen+1 <= required_len) return NULL; /* Catch size_t overflow */\n    if (oldtype==type) {\n        newsh = s_realloc(sh, hdrlen+newlen+1);\n        if (newsh == NULL) return NULL;\n        s = (char*)newsh+hdrlen;\n    } else {\n        /* Since the header size changes, need to move the string forward,\n         * and can't use realloc */\n        newsh = s_malloc(hdrlen+newlen+1);\n        if (newsh == NULL) return NULL;\n        memcpy((char*)newsh+hdrlen, s, len+1);\n        s_free(sh);\n        s = (char*)newsh+hdrlen;\n        s[-1] = type;\n        sdssetlen(s, len);\n    }\n    sdssetalloc(s, newlen);\n    return s;\n}\n\n/* Reallocate the sds string so that it has no free space at the end. The\n * contained string remains not altered, but next concatenation operations\n * will require a reallocation.\n *\n * After the call, the passed sds string is no longer valid and all the\n * references must be substituted with the new pointer returned by the call. */\nsds sdsRemoveFreeSpace(sds s) {\n    void *sh, *newsh;\n    char type, oldtype = s[-1] & SDS_TYPE_MASK;\n    int hdrlen;\n    size_t len = sdslen(s);\n    sh = (char*)s-sdsHdrSize(oldtype);\n\n    type = sdsReqType(len);\n    hdrlen = sdsHdrSize(type);\n    if (oldtype==type) {\n        newsh = s_realloc(sh, hdrlen+len+1);\n        if (newsh == NULL) return NULL;\n        s = (char*)newsh+hdrlen;\n    } else {\n        newsh = s_malloc(hdrlen+len+1);\n        if (newsh == NULL) return NULL;\n        memcpy((char*)newsh+hdrlen, s, len+1);\n        s_free(sh);\n        s = (char*)newsh+hdrlen;\n        s[-1] = type;\n        sdssetlen(s, len);\n    }\n    sdssetalloc(s, len);\n    return s;\n}\n\n/* Return the total size of the allocation of the specifed sds string,\n * including:\n * 1) The sds header before the pointer.\n * 2) The string.\n * 3) The free buffer at the end if any.\n * 4) The implicit null term.\n */\nsize_t sdsAllocSize(sds s) {\n    size_t alloc = sdsalloc(s);\n    return sdsHdrSize(s[-1])+alloc+1;\n}\n\n/* Return the pointer of the actual SDS allocation (normally SDS strings\n * are referenced by the start of the string buffer). */\nvoid *sdsAllocPtr(sds s) {\n    return (void*) (s-sdsHdrSize(s[-1]));\n}\n\n/* Increment the sds length and decrements the left free space at the\n * end of the string according to 'incr'. Also set the null term\n * in the new end of the string.\n *\n * This function is used in order to fix the string length after the\n * user calls sdsMakeRoomFor(), writes something after the end of\n * the current string, and finally needs to set the new length.\n *\n * Note: it is possible to use a negative increment in order to\n * right-trim the string.\n *\n * Usage example:\n *\n * Using sdsIncrLen() and sdsMakeRoomFor() it is possible to mount the\n * following schema, to cat bytes coming from the kernel to the end of an\n * sds string without copying into an intermediate buffer:\n *\n * oldlen = sdslen(s);\n * s = sdsMakeRoomFor(s, BUFFER_SIZE);\n * nread = read(fd, s+oldlen, BUFFER_SIZE);\n * ... check for nread <= 0 and handle it ...\n * sdsIncrLen(s, nread);\n */\nvoid sdsIncrLen(sds s, int incr) {\n    unsigned char flags = s[-1];\n    size_t len;\n    switch(flags&SDS_TYPE_MASK) {\n        case SDS_TYPE_5: {\n            unsigned char *fp = ((unsigned char*)s)-1;\n            unsigned char oldlen = SDS_TYPE_5_LEN(flags);\n            assert((incr > 0 && oldlen+incr < 32) || (incr < 0 && oldlen >= (unsigned int)(-incr)));\n            *fp = SDS_TYPE_5 | ((oldlen+incr) << SDS_TYPE_BITS);\n            len = oldlen+incr;\n            break;\n        }\n        case SDS_TYPE_8: {\n            SDS_HDR_VAR(8,s);\n            assert((incr >= 0 && sh->alloc-sh->len >= incr) || (incr < 0 && sh->len >= (unsigned int)(-incr)));\n            len = (sh->len += incr);\n            break;\n        }\n        case SDS_TYPE_16: {\n            SDS_HDR_VAR(16,s);\n            assert((incr >= 0 && sh->alloc-sh->len >= incr) || (incr < 0 && sh->len >= (unsigned int)(-incr)));\n            len = (sh->len += incr);\n            break;\n        }\n        case SDS_TYPE_32: {\n            SDS_HDR_VAR(32,s);\n            assert((incr >= 0 && sh->alloc-sh->len >= (unsigned int)incr) || (incr < 0 && sh->len >= (unsigned int)(-incr)));\n            len = (sh->len += incr);\n            break;\n        }\n        case SDS_TYPE_64: {\n            SDS_HDR_VAR(64,s);\n            assert((incr >= 0 && sh->alloc-sh->len >= (uint64_t)incr) || (incr < 0 && sh->len >= (uint64_t)(-incr)));\n            len = (sh->len += incr);\n            break;\n        }\n        default: len = 0; /* Just to avoid compilation warnings. */\n    }\n    s[len] = '\\0';\n}\n\n/* Grow the sds to have the specified length. Bytes that were not part of\n * the original length of the sds will be set to zero.\n *\n * if the specified length is smaller than the current length, no operation\n * is performed. */\nsds sdsgrowzero(sds s, size_t len) {\n    size_t curlen = sdslen(s);\n\n    if (len <= curlen) return s;\n    s = sdsMakeRoomFor(s,len-curlen);\n    if (s == NULL) return NULL;\n\n    /* Make sure added region doesn't contain garbage */\n    memset(s+curlen,0,(len-curlen+1)); /* also set trailing \\0 byte */\n    sdssetlen(s, len);\n    return s;\n}\n\n/* Append the specified binary-safe string pointed by 't' of 'len' bytes to the\n * end of the specified sds string 's'.\n *\n * After the call, the passed sds string is no longer valid and all the\n * references must be substituted with the new pointer returned by the call. */\nsds sdscatlen(sds s, const void *t, size_t len) {\n    size_t curlen = sdslen(s);\n\n    s = sdsMakeRoomFor(s,len);\n    if (s == NULL) return NULL;\n    memcpy(s+curlen, t, len);\n    sdssetlen(s, curlen+len);\n    s[curlen+len] = '\\0';\n    return s;\n}\n\n/* Append the specified null termianted C string to the sds string 's'.\n *\n * After the call, the passed sds string is no longer valid and all the\n * references must be substituted with the new pointer returned by the call. */\nsds sdscat(sds s, const char *t) {\n    return sdscatlen(s, t, strlen(t));\n}\n\n/* Append the specified sds 't' to the existing sds 's'.\n *\n * After the call, the modified sds string is no longer valid and all the\n * references must be substituted with the new pointer returned by the call. */\nsds sdscatsds(sds s, const sds t) {\n    return sdscatlen(s, t, sdslen(t));\n}\n\n/* Destructively modify the sds string 's' to hold the specified binary\n * safe string pointed by 't' of length 'len' bytes. */\nsds sdscpylen(sds s, const char *t, size_t len) {\n    if (sdsalloc(s) < len) {\n        s = sdsMakeRoomFor(s,len-sdslen(s));\n        if (s == NULL) return NULL;\n    }\n    memcpy(s, t, len);\n    s[len] = '\\0';\n    sdssetlen(s, len);\n    return s;\n}\n\n/* Like sdscpylen() but 't' must be a null-terminated string so that the length\n * of the string is obtained with strlen(). */\nsds sdscpy(sds s, const char *t) {\n    return sdscpylen(s, t, strlen(t));\n}\n\n/* Helper for sdscatlonglong() doing the actual number -> string\n * conversion. 's' must point to a string with room for at least\n * SDS_LLSTR_SIZE bytes.\n *\n * The function returns the length of the null-terminated string\n * representation stored at 's'. */\n#define SDS_LLSTR_SIZE 21\nint sdsll2str(char *s, long long value) {\n    char *p, aux;\n    unsigned long long v;\n    size_t l;\n\n    /* Generate the string representation, this method produces\n     * an reversed string. */\n    v = (value < 0) ? -value : value;\n    p = s;\n    do {\n        *p++ = '0'+(v%10);\n        v /= 10;\n    } while(v);\n    if (value < 0) *p++ = '-';\n\n    /* Compute length and add null term. */\n    l = p-s;\n    *p = '\\0';\n\n    /* Reverse the string. */\n    p--;\n    while(s < p) {\n        aux = *s;\n        *s = *p;\n        *p = aux;\n        s++;\n        p--;\n    }\n    return l;\n}\n\n/* Identical sdsll2str(), but for unsigned long long type. */\nint sdsull2str(char *s, unsigned long long v) {\n    char *p, aux;\n    size_t l;\n\n    /* Generate the string representation, this method produces\n     * an reversed string. */\n    p = s;\n    do {\n        *p++ = '0'+(v%10);\n        v /= 10;\n    } while(v);\n\n    /* Compute length and add null term. */\n    l = p-s;\n    *p = '\\0';\n\n    /* Reverse the string. */\n    p--;\n    while(s < p) {\n        aux = *s;\n        *s = *p;\n        *p = aux;\n        s++;\n        p--;\n    }\n    return l;\n}\n\n/* Create an sds string from a long long value. It is much faster than:\n *\n * sdscatprintf(sdsempty(),\"%lld\\n\", value);\n */\nsds sdsfromlonglong(long long value) {\n    char buf[SDS_LLSTR_SIZE];\n    int len = sdsll2str(buf,value);\n\n    return sdsnewlen(buf,len);\n}\n\n/* Like sdscatprintf() but gets va_list instead of being variadic. */\nsds sdscatvprintf(sds s, const char *fmt, va_list ap) {\n    va_list cpy;\n    char staticbuf[1024], *buf = staticbuf, *t;\n    size_t buflen = strlen(fmt)*2;\n\n    /* We try to start using a static buffer for speed.\n     * If not possible we revert to heap allocation. */\n    if (buflen > sizeof(staticbuf)) {\n        buf = s_malloc(buflen);\n        if (buf == NULL) return NULL;\n    } else {\n        buflen = sizeof(staticbuf);\n    }\n\n    /* Try with buffers two times bigger every time we fail to\n     * fit the string in the current buffer size. */\n    while(1) {\n        buf[buflen-2] = '\\0';\n        va_copy(cpy,ap);\n        vsnprintf(buf, buflen, fmt, cpy);\n        va_end(cpy);\n        if (buf[buflen-2] != '\\0') {\n            if (buf != staticbuf) s_free(buf);\n            buflen *= 2;\n            buf = s_malloc(buflen);\n            if (buf == NULL) return NULL;\n            continue;\n        }\n        break;\n    }\n\n    /* Finally concat the obtained string to the SDS string and return it. */\n    t = sdscat(s, buf);\n    if (buf != staticbuf) s_free(buf);\n    return t;\n}\n\n/* Append to the sds string 's' a string obtained using printf-alike format\n * specifier.\n *\n * After the call, the modified sds string is no longer valid and all the\n * references must be substituted with the new pointer returned by the call.\n *\n * Example:\n *\n * s = sdsnew(\"Sum is: \");\n * s = sdscatprintf(s,\"%d+%d = %d\",a,b,a+b).\n *\n * Often you need to create a string from scratch with the printf-alike\n * format. When this is the need, just use sdsempty() as the target string:\n *\n * s = sdscatprintf(sdsempty(), \"... your format ...\", args);\n */\nsds sdscatprintf(sds s, const char *fmt, ...) {\n    va_list ap;\n    char *t;\n    va_start(ap, fmt);\n    t = sdscatvprintf(s,fmt,ap);\n    va_end(ap);\n    return t;\n}\n\n/* This function is similar to sdscatprintf, but much faster as it does\n * not rely on sprintf() family functions implemented by the libc that\n * are often very slow. Moreover directly handling the sds string as\n * new data is concatenated provides a performance improvement.\n *\n * However this function only handles an incompatible subset of printf-alike\n * format specifiers:\n *\n * %s - C String\n * %S - SDS string\n * %i - signed int\n * %I - 64 bit signed integer (long long, int64_t)\n * %u - unsigned int\n * %U - 64 bit unsigned integer (unsigned long long, uint64_t)\n * %% - Verbatim \"%\" character.\n */\nsds sdscatfmt(sds s, char const *fmt, ...) {\n    const char *f = fmt;\n    long i;\n    va_list ap;\n\n    va_start(ap,fmt);\n    i = sdslen(s); /* Position of the next byte to write to dest str. */\n    while(*f) {\n        char next, *str;\n        size_t l;\n        long long num;\n        unsigned long long unum;\n\n        /* Make sure there is always space for at least 1 char. */\n        if (sdsavail(s)==0) {\n            s = sdsMakeRoomFor(s,1);\n            if (s == NULL) goto fmt_error;\n        }\n\n        switch(*f) {\n        case '%':\n            next = *(f+1);\n            f++;\n            switch(next) {\n            case 's':\n            case 'S':\n                str = va_arg(ap,char*);\n                l = (next == 's') ? strlen(str) : sdslen(str);\n                if (sdsavail(s) < l) {\n                    s = sdsMakeRoomFor(s,l);\n                    if (s == NULL) goto fmt_error;\n                }\n                memcpy(s+i,str,l);\n                sdsinclen(s,l);\n                i += l;\n                break;\n            case 'i':\n            case 'I':\n                if (next == 'i')\n                    num = va_arg(ap,int);\n                else\n                    num = va_arg(ap,long long);\n                {\n                    char buf[SDS_LLSTR_SIZE];\n                    l = sdsll2str(buf,num);\n                    if (sdsavail(s) < l) {\n                        s = sdsMakeRoomFor(s,l);\n                        if (s == NULL) goto fmt_error;\n                    }\n                    memcpy(s+i,buf,l);\n                    sdsinclen(s,l);\n                    i += l;\n                }\n                break;\n            case 'u':\n            case 'U':\n                if (next == 'u')\n                    unum = va_arg(ap,unsigned int);\n                else\n                    unum = va_arg(ap,unsigned long long);\n                {\n                    char buf[SDS_LLSTR_SIZE];\n                    l = sdsull2str(buf,unum);\n                    if (sdsavail(s) < l) {\n                        s = sdsMakeRoomFor(s,l);\n                        if (s == NULL) goto fmt_error;\n                    }\n                    memcpy(s+i,buf,l);\n                    sdsinclen(s,l);\n                    i += l;\n                }\n                break;\n            default: /* Handle %% and generally %<unknown>. */\n                s[i++] = next;\n                sdsinclen(s,1);\n                break;\n            }\n            break;\n        default:\n            s[i++] = *f;\n            sdsinclen(s,1);\n            break;\n        }\n        f++;\n    }\n    va_end(ap);\n\n    /* Add null-term */\n    s[i] = '\\0';\n    return s;\n\nfmt_error:\n    va_end(ap);\n    return NULL;\n}\n\n/* Remove the part of the string from left and from right composed just of\n * contiguous characters found in 'cset', that is a null terminted C string.\n *\n * After the call, the modified sds string is no longer valid and all the\n * references must be substituted with the new pointer returned by the call.\n *\n * Example:\n *\n * s = sdsnew(\"AA...AA.a.aa.aHelloWorld     :::\");\n * s = sdstrim(s,\"Aa. :\");\n * printf(\"%s\\n\", s);\n *\n * Output will be just \"Hello World\".\n */\nsds sdstrim(sds s, const char *cset) {\n    char *end, *sp, *ep;\n    size_t len;\n\n    sp = s;\n    ep = end = s+sdslen(s)-1;\n    while(sp <= end && strchr(cset, *sp)) sp++;\n    while(ep > sp && strchr(cset, *ep)) ep--;\n    len = (sp > ep) ? 0 : ((ep-sp)+1);\n    if (s != sp) memmove(s, sp, len);\n    s[len] = '\\0';\n    sdssetlen(s,len);\n    return s;\n}\n\n/* Turn the string into a smaller (or equal) string containing only the\n * substring specified by the 'start' and 'end' indexes.\n *\n * start and end can be negative, where -1 means the last character of the\n * string, -2 the penultimate character, and so forth.\n *\n * The interval is inclusive, so the start and end characters will be part\n * of the resulting string.\n *\n * The string is modified in-place.\n *\n * Return value:\n * -1 (error) if sdslen(s) is larger than maximum positive ssize_t value.\n *  0 on success.\n *\n * Example:\n *\n * s = sdsnew(\"Hello World\");\n * sdsrange(s,1,-1); => \"ello World\"\n */\nint sdsrange(sds s, ssize_t start, ssize_t end) {\n    size_t newlen, len = sdslen(s);\n    if (len > SSIZE_MAX) return -1;\n\n    if (len == 0) return 0;\n    if (start < 0) {\n        start = len+start;\n        if (start < 0) start = 0;\n    }\n    if (end < 0) {\n        end = len+end;\n        if (end < 0) end = 0;\n    }\n    newlen = (start > end) ? 0 : (end-start)+1;\n    if (newlen != 0) {\n        if (start >= (ssize_t)len) {\n            newlen = 0;\n        } else if (end >= (ssize_t)len) {\n            end = len-1;\n            newlen = (start > end) ? 0 : (end-start)+1;\n        }\n    } else {\n        start = 0;\n    }\n    if (start && newlen) memmove(s, s+start, newlen);\n    s[newlen] = 0;\n    sdssetlen(s,newlen);\n    return 0;\n}\n\n/* Apply tolower() to every character of the sds string 's'. */\nvoid sdstolower(sds s) {\n    size_t len = sdslen(s), j;\n\n    for (j = 0; j < len; j++) s[j] = tolower(s[j]);\n}\n\n/* Apply toupper() to every character of the sds string 's'. */\nvoid sdstoupper(sds s) {\n    size_t len = sdslen(s), j;\n\n    for (j = 0; j < len; j++) s[j] = toupper(s[j]);\n}\n\n/* Compare two sds strings s1 and s2 with memcmp().\n *\n * Return value:\n *\n *     positive if s1 > s2.\n *     negative if s1 < s2.\n *     0 if s1 and s2 are exactly the same binary string.\n *\n * If two strings share exactly the same prefix, but one of the two has\n * additional characters, the longer string is considered to be greater than\n * the smaller one. */\nint sdscmp(const sds s1, const sds s2) {\n    size_t l1, l2, minlen;\n    int cmp;\n\n    l1 = sdslen(s1);\n    l2 = sdslen(s2);\n    minlen = (l1 < l2) ? l1 : l2;\n    cmp = memcmp(s1,s2,minlen);\n    if (cmp == 0) return l1-l2;\n    return cmp;\n}\n\n/* Split 's' with separator in 'sep'. An array\n * of sds strings is returned. *count will be set\n * by reference to the number of tokens returned.\n *\n * On out of memory, zero length string, zero length\n * separator, NULL is returned.\n *\n * Note that 'sep' is able to split a string using\n * a multi-character separator. For example\n * sdssplit(\"foo_-_bar\",\"_-_\"); will return two\n * elements \"foo\" and \"bar\".\n *\n * This version of the function is binary-safe but\n * requires length arguments. sdssplit() is just the\n * same function but for zero-terminated strings.\n */\nsds *sdssplitlen(const char *s, int len, const char *sep, int seplen, int *count) {\n    int elements = 0, slots = 5, start = 0, j;\n    sds *tokens;\n\n    if (seplen < 1 || len < 0) return NULL;\n\n    tokens = s_malloc(sizeof(sds)*slots);\n    if (tokens == NULL) return NULL;\n\n    if (len == 0) {\n        *count = 0;\n        return tokens;\n    }\n    for (j = 0; j < (len-(seplen-1)); j++) {\n        /* make sure there is room for the next element and the final one */\n        if (slots < elements+2) {\n            sds *newtokens;\n\n            slots *= 2;\n            newtokens = s_realloc(tokens,sizeof(sds)*slots);\n            if (newtokens == NULL) goto cleanup;\n            tokens = newtokens;\n        }\n        /* search the separator */\n        if ((seplen == 1 && *(s+j) == sep[0]) || (memcmp(s+j,sep,seplen) == 0)) {\n            tokens[elements] = sdsnewlen(s+start,j-start);\n            if (tokens[elements] == NULL) goto cleanup;\n            elements++;\n            start = j+seplen;\n            j = j+seplen-1; /* skip the separator */\n        }\n    }\n    /* Add the final element. We are sure there is room in the tokens array. */\n    tokens[elements] = sdsnewlen(s+start,len-start);\n    if (tokens[elements] == NULL) goto cleanup;\n    elements++;\n    *count = elements;\n    return tokens;\n\ncleanup:\n    {\n        int i;\n        for (i = 0; i < elements; i++) sdsfree(tokens[i]);\n        s_free(tokens);\n        *count = 0;\n        return NULL;\n    }\n}\n\n/* Free the result returned by sdssplitlen(), or do nothing if 'tokens' is NULL. */\nvoid sdsfreesplitres(sds *tokens, int count) {\n    if (!tokens) return;\n    while(count--)\n        sdsfree(tokens[count]);\n    s_free(tokens);\n}\n\n/* Append to the sds string \"s\" an escaped string representation where\n * all the non-printable characters (tested with isprint()) are turned into\n * escapes in the form \"\\n\\r\\a....\" or \"\\x<hex-number>\".\n *\n * After the call, the modified sds string is no longer valid and all the\n * references must be substituted with the new pointer returned by the call. */\nsds sdscatrepr(sds s, const char *p, size_t len) {\n    s = sdscatlen(s,\"\\\"\",1);\n    while(len--) {\n        switch(*p) {\n        case '\\\\':\n        case '\"':\n            s = sdscatprintf(s,\"\\\\%c\",*p);\n            break;\n        case '\\n': s = sdscatlen(s,\"\\\\n\",2); break;\n        case '\\r': s = sdscatlen(s,\"\\\\r\",2); break;\n        case '\\t': s = sdscatlen(s,\"\\\\t\",2); break;\n        case '\\a': s = sdscatlen(s,\"\\\\a\",2); break;\n        case '\\b': s = sdscatlen(s,\"\\\\b\",2); break;\n        default:\n            if (isprint((int) *p))\n                s = sdscatprintf(s,\"%c\",*p);\n            else\n                s = sdscatprintf(s,\"\\\\x%02x\",(unsigned char)*p);\n            break;\n        }\n        p++;\n    }\n    return sdscatlen(s,\"\\\"\",1);\n}\n\n/* Helper function for sdssplitargs() that converts a hex digit into an\n * integer from 0 to 15 */\nint hex_digit_to_int(char c) {\n    switch(c) {\n    case '0': return 0;\n    case '1': return 1;\n    case '2': return 2;\n    case '3': return 3;\n    case '4': return 4;\n    case '5': return 5;\n    case '6': return 6;\n    case '7': return 7;\n    case '8': return 8;\n    case '9': return 9;\n    case 'a': case 'A': return 10;\n    case 'b': case 'B': return 11;\n    case 'c': case 'C': return 12;\n    case 'd': case 'D': return 13;\n    case 'e': case 'E': return 14;\n    case 'f': case 'F': return 15;\n    default: return 0;\n    }\n}\n\n/* Split a line into arguments, where every argument can be in the\n * following programming-language REPL-alike form:\n *\n * foo bar \"newline are supported\\n\" and \"\\xff\\x00otherstuff\"\n *\n * The number of arguments is stored into *argc, and an array\n * of sds is returned.\n *\n * The caller should free the resulting array of sds strings with\n * sdsfreesplitres().\n *\n * Note that sdscatrepr() is able to convert back a string into\n * a quoted string in the same format sdssplitargs() is able to parse.\n *\n * The function returns the allocated tokens on success, even when the\n * input string is empty, or NULL if the input contains unbalanced\n * quotes or closed quotes followed by non space characters\n * as in: \"foo\"bar or \"foo'\n */\nsds *sdssplitargs(const char *line, int *argc) {\n    const char *p = line;\n    char *current = NULL;\n    char **vector = NULL;\n\n    *argc = 0;\n    while(1) {\n        /* skip blanks */\n        while(*p && isspace((int) *p)) p++;\n        if (*p) {\n            /* get a token */\n            int inq=0;  /* set to 1 if we are in \"quotes\" */\n            int insq=0; /* set to 1 if we are in 'single quotes' */\n            int done=0;\n\n            if (current == NULL) current = sdsempty();\n            while(!done) {\n                if (inq) {\n                    if (*p == '\\\\' && *(p+1) == 'x' &&\n                                             isxdigit((int) *(p+2)) &&\n                                             isxdigit((int) *(p+3)))\n                    {\n                        unsigned char byte;\n\n                        byte = (hex_digit_to_int(*(p+2))*16)+\n                                hex_digit_to_int(*(p+3));\n                        current = sdscatlen(current,(char*)&byte,1);\n                        p += 3;\n                    } else if (*p == '\\\\' && *(p+1)) {\n                        char c;\n\n                        p++;\n                        switch(*p) {\n                        case 'n': c = '\\n'; break;\n                        case 'r': c = '\\r'; break;\n                        case 't': c = '\\t'; break;\n                        case 'b': c = '\\b'; break;\n                        case 'a': c = '\\a'; break;\n                        default: c = *p; break;\n                        }\n                        current = sdscatlen(current,&c,1);\n                    } else if (*p == '\"') {\n                        /* closing quote must be followed by a space or\n                         * nothing at all. */\n                        if (*(p+1) && !isspace((int) *(p+1))) goto err;\n                        done=1;\n                    } else if (!*p) {\n                        /* unterminated quotes */\n                        goto err;\n                    } else {\n                        current = sdscatlen(current,p,1);\n                    }\n                } else if (insq) {\n                    if (*p == '\\\\' && *(p+1) == '\\'') {\n                        p++;\n                        current = sdscatlen(current,\"'\",1);\n                    } else if (*p == '\\'') {\n                        /* closing quote must be followed by a space or\n                         * nothing at all. */\n                        if (*(p+1) && !isspace((int) *(p+1))) goto err;\n                        done=1;\n                    } else if (!*p) {\n                        /* unterminated quotes */\n                        goto err;\n                    } else {\n                        current = sdscatlen(current,p,1);\n                    }\n                } else {\n                    switch(*p) {\n                    case ' ':\n                    case '\\n':\n                    case '\\r':\n                    case '\\t':\n                    case '\\0':\n                        done=1;\n                        break;\n                    case '\"':\n                        inq=1;\n                        break;\n                    case '\\'':\n                        insq=1;\n                        break;\n                    default:\n                        current = sdscatlen(current,p,1);\n                        break;\n                    }\n                }\n                if (*p) p++;\n            }\n            /* add the token to the vector */\n            {\n                char **new_vector = s_realloc(vector,((*argc)+1)*sizeof(char*));\n                if (new_vector == NULL) {\n                    s_free(vector);\n                    return NULL;\n                }\n\n                vector = new_vector;\n                vector[*argc] = current;\n                (*argc)++;\n                current = NULL;\n            }\n        } else {\n            /* Even on empty input string return something not NULL. */\n            if (vector == NULL) vector = s_malloc(sizeof(void*));\n            return vector;\n        }\n    }\n\nerr:\n    while((*argc)--)\n        sdsfree(vector[*argc]);\n    s_free(vector);\n    if (current) sdsfree(current);\n    *argc = 0;\n    return NULL;\n}\n\n/* Modify the string substituting all the occurrences of the set of\n * characters specified in the 'from' string to the corresponding character\n * in the 'to' array.\n *\n * For instance: sdsmapchars(mystring, \"ho\", \"01\", 2)\n * will have the effect of turning the string \"hello\" into \"0ell1\".\n *\n * The function returns the sds string pointer, that is always the same\n * as the input pointer since no resize is needed. */\nsds sdsmapchars(sds s, const char *from, const char *to, size_t setlen) {\n    size_t j, i, l = sdslen(s);\n\n    for (j = 0; j < l; j++) {\n        for (i = 0; i < setlen; i++) {\n            if (s[j] == from[i]) {\n                s[j] = to[i];\n                break;\n            }\n        }\n    }\n    return s;\n}\n\n/* Join an array of C strings using the specified separator (also a C string).\n * Returns the result as an sds string. */\nsds sdsjoin(char **argv, int argc, char *sep) {\n    sds join = sdsempty();\n    int j;\n\n    for (j = 0; j < argc; j++) {\n        join = sdscat(join, argv[j]);\n        if (j != argc-1) join = sdscat(join,sep);\n    }\n    return join;\n}\n\n/* Like sdsjoin, but joins an array of SDS strings. */\nsds sdsjoinsds(sds *argv, int argc, const char *sep, size_t seplen) {\n    sds join = sdsempty();\n    int j;\n\n    for (j = 0; j < argc; j++) {\n        join = sdscatsds(join, argv[j]);\n        if (j != argc-1) join = sdscatlen(join,sep,seplen);\n    }\n    return join;\n}\n\n/* Wrappers to the allocators used by SDS. Note that SDS will actually\n * just use the macros defined into sdsalloc.h in order to avoid to pay\n * the overhead of function calls. Here we define these wrappers only for\n * the programs SDS is linked to, if they want to touch the SDS internals\n * even if they use a different allocator. */\nvoid *sds_malloc(size_t size) { return s_malloc(size); }\nvoid *sds_realloc(void *ptr, size_t size) { return s_realloc(ptr,size); }\nvoid sds_free(void *ptr) { s_free(ptr); }\n\n#if defined(SDS_TEST_MAIN)\n#include <stdio.h>\n#include \"testhelp.h\"\n#include \"limits.h\"\n\n#define UNUSED(x) (void)(x)\nint sdsTest(void) {\n    {\n        sds x = sdsnew(\"foo\"), y;\n\n        test_cond(\"Create a string and obtain the length\",\n            sdslen(x) == 3 && memcmp(x,\"foo\\0\",4) == 0)\n\n        sdsfree(x);\n        x = sdsnewlen(\"foo\",2);\n        test_cond(\"Create a string with specified length\",\n            sdslen(x) == 2 && memcmp(x,\"fo\\0\",3) == 0)\n\n        x = sdscat(x,\"bar\");\n        test_cond(\"Strings concatenation\",\n            sdslen(x) == 5 && memcmp(x,\"fobar\\0\",6) == 0);\n\n        x = sdscpy(x,\"a\");\n        test_cond(\"sdscpy() against an originally longer string\",\n            sdslen(x) == 1 && memcmp(x,\"a\\0\",2) == 0)\n\n        x = sdscpy(x,\"xyzxxxxxxxxxxyyyyyyyyyykkkkkkkkkk\");\n        test_cond(\"sdscpy() against an originally shorter string\",\n            sdslen(x) == 33 &&\n            memcmp(x,\"xyzxxxxxxxxxxyyyyyyyyyykkkkkkkkkk\\0\",33) == 0)\n\n        sdsfree(x);\n        x = sdscatprintf(sdsempty(),\"%d\",123);\n        test_cond(\"sdscatprintf() seems working in the base case\",\n            sdslen(x) == 3 && memcmp(x,\"123\\0\",4) == 0)\n\n        sdsfree(x);\n        x = sdsnew(\"--\");\n        x = sdscatfmt(x, \"Hello %s World %I,%I--\", \"Hi!\", LLONG_MIN,LLONG_MAX);\n        test_cond(\"sdscatfmt() seems working in the base case\",\n            sdslen(x) == 60 &&\n            memcmp(x,\"--Hello Hi! World -9223372036854775808,\"\n                     \"9223372036854775807--\",60) == 0)\n        printf(\"[%s]\\n\",x);\n\n        sdsfree(x);\n        x = sdsnew(\"--\");\n        x = sdscatfmt(x, \"%u,%U--\", UINT_MAX, ULLONG_MAX);\n        test_cond(\"sdscatfmt() seems working with unsigned numbers\",\n            sdslen(x) == 35 &&\n            memcmp(x,\"--4294967295,18446744073709551615--\",35) == 0)\n\n        sdsfree(x);\n        x = sdsnew(\" x \");\n        sdstrim(x,\" x\");\n        test_cond(\"sdstrim() works when all chars match\",\n            sdslen(x) == 0)\n\n        sdsfree(x);\n        x = sdsnew(\" x \");\n        sdstrim(x,\" \");\n        test_cond(\"sdstrim() works when a single char remains\",\n            sdslen(x) == 1 && x[0] == 'x')\n\n        sdsfree(x);\n        x = sdsnew(\"xxciaoyyy\");\n        sdstrim(x,\"xy\");\n        test_cond(\"sdstrim() correctly trims characters\",\n            sdslen(x) == 4 && memcmp(x,\"ciao\\0\",5) == 0)\n\n        y = sdsdup(x);\n        sdsrange(y,1,1);\n        test_cond(\"sdsrange(...,1,1)\",\n            sdslen(y) == 1 && memcmp(y,\"i\\0\",2) == 0)\n\n        sdsfree(y);\n        y = sdsdup(x);\n        sdsrange(y,1,-1);\n        test_cond(\"sdsrange(...,1,-1)\",\n            sdslen(y) == 3 && memcmp(y,\"iao\\0\",4) == 0)\n\n        sdsfree(y);\n        y = sdsdup(x);\n        sdsrange(y,-2,-1);\n        test_cond(\"sdsrange(...,-2,-1)\",\n            sdslen(y) == 2 && memcmp(y,\"ao\\0\",3) == 0)\n\n        sdsfree(y);\n        y = sdsdup(x);\n        sdsrange(y,2,1);\n        test_cond(\"sdsrange(...,2,1)\",\n            sdslen(y) == 0 && memcmp(y,\"\\0\",1) == 0)\n\n        sdsfree(y);\n        y = sdsdup(x);\n        sdsrange(y,1,100);\n        test_cond(\"sdsrange(...,1,100)\",\n            sdslen(y) == 3 && memcmp(y,\"iao\\0\",4) == 0)\n\n        sdsfree(y);\n        y = sdsdup(x);\n        sdsrange(y,100,100);\n        test_cond(\"sdsrange(...,100,100)\",\n            sdslen(y) == 0 && memcmp(y,\"\\0\",1) == 0)\n\n        sdsfree(y);\n        sdsfree(x);\n        x = sdsnew(\"foo\");\n        y = sdsnew(\"foa\");\n        test_cond(\"sdscmp(foo,foa)\", sdscmp(x,y) > 0)\n\n        sdsfree(y);\n        sdsfree(x);\n        x = sdsnew(\"bar\");\n        y = sdsnew(\"bar\");\n        test_cond(\"sdscmp(bar,bar)\", sdscmp(x,y) == 0)\n\n        sdsfree(y);\n        sdsfree(x);\n        x = sdsnew(\"aar\");\n        y = sdsnew(\"bar\");\n        test_cond(\"sdscmp(bar,bar)\", sdscmp(x,y) < 0)\n\n        sdsfree(y);\n        sdsfree(x);\n        x = sdsnewlen(\"\\a\\n\\0foo\\r\",7);\n        y = sdscatrepr(sdsempty(),x,sdslen(x));\n        test_cond(\"sdscatrepr(...data...)\",\n            memcmp(y,\"\\\"\\\\a\\\\n\\\\x00foo\\\\r\\\"\",15) == 0)\n\n        {\n            unsigned int oldfree;\n            char *p;\n            int step = 10, j, i;\n\n            sdsfree(x);\n            sdsfree(y);\n            x = sdsnew(\"0\");\n            test_cond(\"sdsnew() free/len buffers\", sdslen(x) == 1 && sdsavail(x) == 0);\n\n            /* Run the test a few times in order to hit the first two\n             * SDS header types. */\n            for (i = 0; i < 10; i++) {\n                int oldlen = sdslen(x);\n                x = sdsMakeRoomFor(x,step);\n                int type = x[-1]&SDS_TYPE_MASK;\n\n                test_cond(\"sdsMakeRoomFor() len\", sdslen(x) == oldlen);\n                if (type != SDS_TYPE_5) {\n                    test_cond(\"sdsMakeRoomFor() free\", sdsavail(x) >= step);\n                    oldfree = sdsavail(x);\n                }\n                p = x+oldlen;\n                for (j = 0; j < step; j++) {\n                    p[j] = 'A'+j;\n                }\n                sdsIncrLen(x,step);\n            }\n            test_cond(\"sdsMakeRoomFor() content\",\n                memcmp(\"0ABCDEFGHIJABCDEFGHIJABCDEFGHIJABCDEFGHIJABCDEFGHIJABCDEFGHIJABCDEFGHIJABCDEFGHIJABCDEFGHIJABCDEFGHIJ\",x,101) == 0);\n            test_cond(\"sdsMakeRoomFor() final length\",sdslen(x)==101);\n\n            sdsfree(x);\n        }\n    }\n    test_report()\n    return 0;\n}\n#endif\n\n#ifdef SDS_TEST_MAIN\nint main(void) {\n    return sdsTest();\n}\n#endif\n"
}