{
  "ok": true,
  "tool": "webftr-js8-jsc-decompress-source-audit-probe",
  "tool_version": "step69-jsc-decompress-source-audit-probe",
  "schema": "webftr-js8-jsc-decompress-source-audit-v1",
  "rx_only_guard": {
    "tx": false,
    "ptt": false,
    "tune": false,
    "send": false,
    "js8call_runtime_control": false,
    "webftr_productive_integration": false
  },
  "no_gui_runtime_started": true,
  "root": "/decoders/js8_decoder",
  "log_dir": "/decoders/js8_decoder/logs",
  "source_resolution": {
    "source_dir": "/decoders/js8_decoder/runtime/src/JS8Call-improved",
    "source_found": true,
    "checked": [
      {
        "path": "/decoders/js8_decoder/runtime/src/JS8Call-improved",
        "exists": true,
        "is_dir": true
      }
    ],
    "focused_files_present": [
      "JS8_Main/Varicode.cpp",
      "JS8_Main/Varicode.h",
      "JS8_JSC/JSC.cpp",
      "JS8_JSC/JSC.h",
      "JS8_JSC/JSC_map.cpp",
      "JS8_JSC/JSC_list.cpp",
      "JS8_Mode/JS8.cpp",
      "JS8_Mode/JS8.h"
    ],
    "focused_files_missing": [
      "JS8_JSC/jsc.cpp",
      "JS8_JSC/jsc.h"
    ]
  },
  "input_reports": [
    {
      "path": "/decoders/js8_decoder/logs/20260527T181644Z_webftr_rx_ui_contract_output.json",
      "exists": true,
      "selected_latest_step68": true
    }
  ],
  "frame_inventory": {
    "frame_type_counts": {
      "FrameHeartbeat": 2,
      "FrameDirected": 2
    },
    "data_frame_candidates": [],
    "data_frame_candidate_count": 0,
    "current_fixture_has_data_frames": false
  },
  "jsc_decode_path_evidence": {
    "has_jsc_decompress_reference": true,
    "has_unpack_fast_data_message": true,
    "has_unpack_legacy_data_message": true,
    "has_huff_fallback_evidence": true,
    "expected_source_flow": [
      "unpack72bits(message174_text) -> 72 bits",
      "FrameData/FrameDataCompressed bits are trimmed at the final zero padding marker",
      "compressed path calls JSC::decompress(bits)",
      "legacy non-compressed path uses Varicode::huffDecode(defaultHuffTable, bits)",
      "Step69 does not yet display free text; it only extracts and documents the source path for a safe Step70 port."
    ]
  },
  "source_snippets": [
    {
      "keyword": "JSC::decompress",
      "path": "JS8_Main/Varicode.cpp",
      "line": 1938,
      "context": {
        "start_line": 1933,
        "end_line": 1943,
        "lines": [
          {
            "line": 1933,
            "text": "    // trim off the pad bits"
          },
          {
            "line": 1934,
            "text": "    bits = bits.mid(1, n - 1);"
          },
          {
            "line": 1935,
            "text": ""
          },
          {
            "line": 1936,
            "text": "    if (compressed) {"
          },
          {
            "line": 1937,
            "text": "        // partial word (s,c)-dense coding with code tables"
          },
          {
            "line": 1938,
            "text": "        unpacked = JSC::decompress(bits);"
          },
          {
            "line": 1939,
            "text": "    } else {"
          },
          {
            "line": 1940,
            "text": "        // huff decode the bits (without escapes)"
          },
          {
            "line": 1941,
            "text": "        unpacked = Varicode::huffDecode(Varicode::defaultHuffTable(), bits);"
          },
          {
            "line": 1942,
            "text": "    }"
          },
          {
            "line": 1943,
            "text": ""
          }
        ]
      }
    },
    {
      "keyword": "JSC::decompress",
      "path": "JS8_Main/Varicode.cpp",
      "line": 2003,
      "context": {
        "start_line": 1998,
        "end_line": 2008,
        "lines": [
          {
            "line": 1998,
            "text": "    // trim off the pad bits"
          },
          {
            "line": 1999,
            "text": "    bits = bits.mid(1, n - 1);"
          },
          {
            "line": 2000,
            "text": ""
          },
          {
            "line": 2001,
            "text": "    if (compressed) {"
          },
          {
            "line": 2002,
            "text": "        // partial word (s,c)-dense coding with code tables"
          },
          {
            "line": 2003,
            "text": "        unpacked = JSC::decompress(bits);"
          },
          {
            "line": 2004,
            "text": "    } else {"
          },
          {
            "line": 2005,
            "text": "        // huff decode the bits (without escapes)"
          },
          {
            "line": 2006,
            "text": "        unpacked = Varicode::huffDecode(Varicode::defaultHuffTable(), bits);"
          },
          {
            "line": 2007,
            "text": "    }"
          },
          {
            "line": 2008,
            "text": "#else"
          }
        ]
      }
    },
    {
      "keyword": "JSC::decompress",
      "path": "JS8_Main/Varicode.cpp",
      "line": 2015,
      "context": {
        "start_line": 2010,
        "end_line": 2020,
        "lines": [
          {
            "line": 2010,
            "text": ""
          },
          {
            "line": 2011,
            "text": "    // trim off the pad bits"
          },
          {
            "line": 2012,
            "text": "    bits = bits.mid(0, n);"
          },
          {
            "line": 2013,
            "text": ""
          },
          {
            "line": 2014,
            "text": "    // partial word (s,c)-dense coding with code tables"
          },
          {
            "line": 2015,
            "text": "    unpacked = JSC::decompress(bits);"
          },
          {
            "line": 2016,
            "text": "#endif"
          },
          {
            "line": 2017,
            "text": ""
          },
          {
            "line": 2018,
            "text": "    return unpacked;"
          },
          {
            "line": 2019,
            "text": "}"
          },
          {
            "line": 2020,
            "text": ""
          }
        ]
      }
    },
    {
      "keyword": "JSC::compress",
      "path": "JS8_Main/Varicode.cpp",
      "line": 1849,
      "context": {
        "start_line": 1844,
        "end_line": 1854,
        "lines": [
          {
            "line": 1844,
            "text": "    if (!prefix.isEmpty()) {"
          },
          {
            "line": 1845,
            "text": "        frameBits << prefix;"
          },
          {
            "line": 1846,
            "text": "    }"
          },
          {
            "line": 1847,
            "text": ""
          },
          {
            "line": 1848,
            "text": "    int i = 0;"
          },
          {
            "line": 1849,
            "text": "    foreach (auto pair, JSC::compress(input)) {"
          },
          {
            "line": 1850,
            "text": "        auto bits = pair.first;"
          },
          {
            "line": 1851,
            "text": "        auto chars = pair.second;"
          },
          {
            "line": 1852,
            "text": ""
          },
          {
            "line": 1853,
            "text": "        if (frameBits.length() + bits.length() < frameSize) {"
          },
          {
            "line": 1854,
            "text": "            frameBits.append(bits);"
          }
        ]
      }
    },
    {
      "keyword": "unpackDataMessage",
      "path": "JS8_Main/Varicode.cpp",
      "line": 1912,
      "context": {
        "start_line": 1907,
        "end_line": 1917,
        "lines": [
          {
            "line": 1907,
            "text": "}"
          },
          {
            "line": 1908,
            "text": ""
          },
          {
            "line": 1909,
            "text": "// TODO: DEPRECATED in 2.2 (still available for decoding legacy frames, but will"
          },
          {
            "line": 1910,
            "text": "// eventually no longer be decodable) unpack data message using 70 bits"
          },
          {
            "line": 1911,
            "text": "// available flagged as data by the first 2 bits"
          },
          {
            "line": 1912,
            "text": "QString Varicode::unpackDataMessage(const QString &text) {"
          },
          {
            "line": 1913,
            "text": "    QString unpacked;"
          },
          {
            "line": 1914,
            "text": ""
          },
          {
            "line": 1915,
            "text": "    if (text.length() < 12 || text.contains(\" \")) {"
          },
          {
            "line": 1916,
            "text": "        return unpacked;"
          },
          {
            "line": 1917,
            "text": "    }"
          }
        ]
      }
    },
    {
      "keyword": "unpackFastDataMessage",
      "path": "JS8_Main/Varicode.cpp",
      "line": 1983,
      "context": {
        "start_line": 1978,
        "end_line": 1988,
        "lines": [
          {
            "line": 1978,
            "text": "#endif"
          },
          {
            "line": 1979,
            "text": "}"
          },
          {
            "line": 1980,
            "text": ""
          },
          {
            "line": 1981,
            "text": "// unpack data message using the full 72 bits available (with the data flag in"
          },
          {
            "line": 1982,
            "text": "// the i3bit header)"
          },
          {
            "line": 1983,
            "text": "QString Varicode::unpackFastDataMessage(const QString &text) {"
          },
          {
            "line": 1984,
            "text": "    QString unpacked;"
          },
          {
            "line": 1985,
            "text": ""
          },
          {
            "line": 1986,
            "text": "    if (text.length() < 12 || text.contains(\" \")) {"
          },
          {
            "line": 1987,
            "text": "        return unpacked;"
          },
          {
            "line": 1988,
            "text": "    }"
          }
        ]
      }
    },
    {
      "keyword": "packCompressedMessage",
      "path": "JS8_Main/Varicode.cpp",
      "line": 1830,
      "context": {
        "start_line": 1825,
        "end_line": 1835,
        "lines": [
          {
            "line": 1825,
            "text": "        *n = i;"
          },
          {
            "line": 1826,
            "text": ""
          },
          {
            "line": 1827,
            "text": "    return frame;"
          },
          {
            "line": 1828,
            "text": "}"
          },
          {
            "line": 1829,
            "text": ""
          },
          {
            "line": 1830,
            "text": "QString packCompressedMessage(const QString &input, QVector<bool> prefix,"
          },
          {
            "line": 1831,
            "text": "                              int *n) {"
          },
          {
            "line": 1832,
            "text": "    static const int frameSize = 72;"
          },
          {
            "line": 1833,
            "text": ""
          },
          {
            "line": 1834,
            "text": "    QString frame;"
          },
          {
            "line": 1835,
            "text": ""
          }
        ]
      }
    },
    {
      "keyword": "packCompressedMessage",
      "path": "JS8_Main/Varicode.cpp",
      "line": 1896,
      "context": {
        "start_line": 1891,
        "end_line": 1901,
        "lines": [
          {
            "line": 1891,
            "text": "    huffFrame = packHuffMessage(input, {true, false}, &huffChars);"
          },
          {
            "line": 1892,
            "text": ""
          },
          {
            "line": 1893,
            "text": "    QString compressedFrame;"
          },
          {
            "line": 1894,
            "text": "    int compressedChars = 0;"
          },
          {
            "line": 1895,
            "text": "    compressedFrame ="
          },
          {
            "line": 1896,
            "text": "        packCompressedMessage(input, {true, true}, &compressedChars);"
          },
          {
            "line": 1897,
            "text": ""
          },
          {
            "line": 1898,
            "text": "    if (huffChars > compressedChars) {"
          },
          {
            "line": 1899,
            "text": "        if (n)"
          },
          {
            "line": 1900,
            "text": "            *n = huffChars;"
          },
          {
            "line": 1901,
            "text": "        return huffFrame;"
          }
        ]
      }
    },
    {
      "keyword": "packCompressedMessage",
      "path": "JS8_Main/Varicode.cpp",
      "line": 1959,
      "context": {
        "start_line": 1954,
        "end_line": 1964,
        "lines": [
          {
            "line": 1954,
            "text": "    int huffChars = 0;"
          },
          {
            "line": 1955,
            "text": "    huffFrame = packHuffMessage(input, {false}, &huffChars);"
          },
          {
            "line": 1956,
            "text": ""
          },
          {
            "line": 1957,
            "text": "    QString compressedFrame;"
          },
          {
            "line": 1958,
            "text": "    int compressedChars = 0;"
          },
          {
            "line": 1959,
            "text": "    compressedFrame = packCompressedMessage(input, {true}, &compressedChars);"
          },
          {
            "line": 1960,
            "text": ""
          },
          {
            "line": 1961,
            "text": "    if (huffChars > compressedChars) {"
          },
          {
            "line": 1962,
            "text": "        if (n)"
          },
          {
            "line": 1963,
            "text": "            *n = huffChars;"
          },
          {
            "line": 1964,
            "text": "        return huffFrame;"
          }
        ]
      }
    },
    {
      "keyword": "packCompressedMessage",
      "path": "JS8_Main/Varicode.cpp",
      "line": 1973,
      "context": {
        "start_line": 1968,
        "end_line": 1978,
        "lines": [
          {
            "line": 1968,
            "text": "        return compressedFrame;"
          },
          {
            "line": 1969,
            "text": "    }"
          },
          {
            "line": 1970,
            "text": "#else"
          },
          {
            "line": 1971,
            "text": "    QString compressedFrame;"
          },
          {
            "line": 1972,
            "text": "    int compressedChars = 0;"
          },
          {
            "line": 1973,
            "text": "    compressedFrame = packCompressedMessage(input, {}, &compressedChars);"
          },
          {
            "line": 1974,
            "text": ""
          },
          {
            "line": 1975,
            "text": "    if (n)"
          },
          {
            "line": 1976,
            "text": "        *n = compressedChars;"
          },
          {
            "line": 1977,
            "text": "    return compressedFrame;"
          },
          {
            "line": 1978,
            "text": "#endif"
          }
        ]
      }
    },
    {
      "keyword": "packHuffMessage",
      "path": "JS8_Main/Varicode.cpp",
      "line": 1762,
      "context": {
        "start_line": 1757,
        "end_line": 1767,
        "lines": [
          {
            "line": 1757,
            "text": "    if (pType)"
          },
          {
            "line": 1758,
            "text": "        *pType = packed_flag;"
          },
          {
            "line": 1759,
            "text": "    return unpacked;"
          },
          {
            "line": 1760,
            "text": "}"
          },
          {
            "line": 1761,
            "text": ""
          },
          {
            "line": 1762,
            "text": "QString packHuffMessage(const QString &input, const QVector<bool> prefix,"
          },
          {
            "line": 1763,
            "text": "                        int *n) {"
          },
          {
            "line": 1764,
            "text": "    static const int frameSize = 72;"
          },
          {
            "line": 1765,
            "text": ""
          },
          {
            "line": 1766,
            "text": "    QString frame;"
          },
          {
            "line": 1767,
            "text": ""
          }
        ]
      }
    },
    {
      "keyword": "packHuffMessage",
      "path": "JS8_Main/Varicode.cpp",
      "line": 1891,
      "context": {
        "start_line": 1886,
        "end_line": 1896,
        "lines": [
          {
            "line": 1886,
            "text": "// TODO: DEPRECATED in 2.2 (we will eventually stop transmitting these frames)"
          },
          {
            "line": 1887,
            "text": "// pack data message using 70 bits available flagged as data by the first 2 bits"
          },
          {
            "line": 1888,
            "text": "QString Varicode::packDataMessage(const QString &input, int *n) {"
          },
          {
            "line": 1889,
            "text": "    QString huffFrame;"
          },
          {
            "line": 1890,
            "text": "    int huffChars = 0;"
          },
          {
            "line": 1891,
            "text": "    huffFrame = packHuffMessage(input, {true, false}, &huffChars);"
          },
          {
            "line": 1892,
            "text": ""
          },
          {
            "line": 1893,
            "text": "    QString compressedFrame;"
          },
          {
            "line": 1894,
            "text": "    int compressedChars = 0;"
          },
          {
            "line": 1895,
            "text": "    compressedFrame ="
          },
          {
            "line": 1896,
            "text": "        packCompressedMessage(input, {true, true}, &compressedChars);"
          }
        ]
      }
    },
    {
      "keyword": "packHuffMessage",
      "path": "JS8_Main/Varicode.cpp",
      "line": 1955,
      "context": {
        "start_line": 1950,
        "end_line": 1960,
        "lines": [
          {
            "line": 1950,
            "text": "// i3bit header)"
          },
          {
            "line": 1951,
            "text": "QString Varicode::packFastDataMessage(const QString &input, int *n) {"
          },
          {
            "line": 1952,
            "text": "#if JS8_FAST_DATA_CAN_USE_HUFF"
          },
          {
            "line": 1953,
            "text": "    QString huffFrame;"
          },
          {
            "line": 1954,
            "text": "    int huffChars = 0;"
          },
          {
            "line": 1955,
            "text": "    huffFrame = packHuffMessage(input, {false}, &huffChars);"
          },
          {
            "line": 1956,
            "text": ""
          },
          {
            "line": 1957,
            "text": "    QString compressedFrame;"
          },
          {
            "line": 1958,
            "text": "    int compressedChars = 0;"
          },
          {
            "line": 1959,
            "text": "    compressedFrame = packCompressedMessage(input, {true}, &compressedChars);"
          },
          {
            "line": 1960,
            "text": ""
          }
        ]
      }
    },
    {
      "keyword": "huffDecode",
      "path": "JS8_Main/Varicode.cpp",
      "line": 597,
      "context": {
        "start_line": 592,
        "end_line": 602,
        "lines": [
          {
            "line": 592,
            "text": "    }"
          },
          {
            "line": 593,
            "text": ""
          },
          {
            "line": 594,
            "text": "    return out;"
          },
          {
            "line": 595,
            "text": "}"
          },
          {
            "line": 596,
            "text": ""
          },
          {
            "line": 597,
            "text": "QString Varicode::huffDecode(QMap<QString, QString> const &huff,"
          },
          {
            "line": 598,
            "text": "                             QVector<bool> const &bitvec) {"
          },
          {
            "line": 599,
            "text": "    QString text;"
          },
          {
            "line": 600,
            "text": ""
          },
          {
            "line": 601,
            "text": "    QString bits = Varicode::bitsToStr(bitvec);"
          },
          {
            "line": 602,
            "text": ""
          }
        ]
      }
    },
    {
      "keyword": "huffDecode",
      "path": "JS8_Main/Varicode.cpp",
      "line": 1941,
      "context": {
        "start_line": 1936,
        "end_line": 1946,
        "lines": [
          {
            "line": 1936,
            "text": "    if (compressed) {"
          },
          {
            "line": 1937,
            "text": "        // partial word (s,c)-dense coding with code tables"
          },
          {
            "line": 1938,
            "text": "        unpacked = JSC::decompress(bits);"
          },
          {
            "line": 1939,
            "text": "    } else {"
          },
          {
            "line": 1940,
            "text": "        // huff decode the bits (without escapes)"
          },
          {
            "line": 1941,
            "text": "        unpacked = Varicode::huffDecode(Varicode::defaultHuffTable(), bits);"
          },
          {
            "line": 1942,
            "text": "    }"
          },
          {
            "line": 1943,
            "text": ""
          },
          {
            "line": 1944,
            "text": "    return unpacked;"
          },
          {
            "line": 1945,
            "text": "}"
          },
          {
            "line": 1946,
            "text": ""
          }
        ]
      }
    },
    {
      "keyword": "huffDecode",
      "path": "JS8_Main/Varicode.cpp",
      "line": 2006,
      "context": {
        "start_line": 2001,
        "end_line": 2011,
        "lines": [
          {
            "line": 2001,
            "text": "    if (compressed) {"
          },
          {
            "line": 2002,
            "text": "        // partial word (s,c)-dense coding with code tables"
          },
          {
            "line": 2003,
            "text": "        unpacked = JSC::decompress(bits);"
          },
          {
            "line": 2004,
            "text": "    } else {"
          },
          {
            "line": 2005,
            "text": "        // huff decode the bits (without escapes)"
          },
          {
            "line": 2006,
            "text": "        unpacked = Varicode::huffDecode(Varicode::defaultHuffTable(), bits);"
          },
          {
            "line": 2007,
            "text": "    }"
          },
          {
            "line": 2008,
            "text": "#else"
          },
          {
            "line": 2009,
            "text": "    int n = bits.lastIndexOf(0);"
          },
          {
            "line": 2010,
            "text": ""
          },
          {
            "line": 2011,
            "text": "    // trim off the pad bits"
          }
        ]
      }
    },
    {
      "keyword": "defaultHuffTable",
      "path": "JS8_Main/Varicode.cpp",
      "line": 438,
      "context": {
        "start_line": 433,
        "end_line": 443,
        "lines": [
          {
            "line": 433,
            "text": "}"
          },
          {
            "line": 434,
            "text": ""
          },
          {
            "line": 435,
            "text": "/*"
          },
          {
            "line": 436,
            "text": " * VARICODE"
          },
          {
            "line": 437,
            "text": " */"
          },
          {
            "line": 438,
            "text": "QMap<QString, QString> Varicode::defaultHuffTable() { return hufftable; }"
          },
          {
            "line": 439,
            "text": ""
          },
          {
            "line": 440,
            "text": "QString Varicode::cqString(int number) {"
          },
          {
            "line": 441,
            "text": "    if (!cqs.contains(number)) {"
          },
          {
            "line": 442,
            "text": "        return QString{};"
          },
          {
            "line": 443,
            "text": "    }"
          }
        ]
      }
    },
    {
      "keyword": "defaultHuffTable",
      "path": "JS8_Main/Varicode.cpp",
      "line": 1784,
      "context": {
        "start_line": 1779,
        "end_line": 1789,
        "lines": [
          {
            "line": 1779,
            "text": "    int i = 0;"
          },
          {
            "line": 1780,
            "text": ""
          },
          {
            "line": 1781,
            "text": "    // only pack huff messages that only contain valid chars"
          },
          {
            "line": 1782,
            "text": "    QString::const_iterator it;"
          },
          {
            "line": 1783,
            "text": "    QSet<QString> validChars ="
          },
          {
            "line": 1784,
            "text": "        Varicode::huffValidChars(Varicode::defaultHuffTable());"
          },
          {
            "line": 1785,
            "text": "    for (it = input.constBegin(); it != input.constEnd(); it++) {"
          },
          {
            "line": 1786,
            "text": "        auto ch = (*it).toUpper();"
          },
          {
            "line": 1787,
            "text": "        if (!validChars.contains(ch)) {"
          },
          {
            "line": 1788,
            "text": "            if (n)"
          },
          {
            "line": 1789,
            "text": "                *n = 0;"
          }
        ]
      }
    },
    {
      "keyword": "defaultHuffTable",
      "path": "JS8_Main/Varicode.cpp",
      "line": 1796,
      "context": {
        "start_line": 1791,
        "end_line": 1801,
        "lines": [
          {
            "line": 1791,
            "text": "        }"
          },
          {
            "line": 1792,
            "text": "    }"
          },
          {
            "line": 1793,
            "text": ""
          },
          {
            "line": 1794,
            "text": "    // pack using the default huff table"
          },
          {
            "line": 1795,
            "text": "    foreach (auto pair,"
          },
          {
            "line": 1796,
            "text": "             Varicode::huffEncode(Varicode::defaultHuffTable(), input)) {"
          },
          {
            "line": 1797,
            "text": "        auto charN = pair.first;"
          },
          {
            "line": 1798,
            "text": "        auto charBits = pair.second;"
          },
          {
            "line": 1799,
            "text": "        if (frameBits.length() + charBits.length() < frameSize) {"
          },
          {
            "line": 1800,
            "text": "            frameBits += charBits;"
          },
          {
            "line": 1801,
            "text": "            i += charN;"
          }
        ]
      }
    },
    {
      "keyword": "defaultHuffTable",
      "path": "JS8_Main/Varicode.cpp",
      "line": 1941,
      "context": {
        "start_line": 1936,
        "end_line": 1946,
        "lines": [
          {
            "line": 1936,
            "text": "    if (compressed) {"
          },
          {
            "line": 1937,
            "text": "        // partial word (s,c)-dense coding with code tables"
          },
          {
            "line": 1938,
            "text": "        unpacked = JSC::decompress(bits);"
          },
          {
            "line": 1939,
            "text": "    } else {"
          },
          {
            "line": 1940,
            "text": "        // huff decode the bits (without escapes)"
          },
          {
            "line": 1941,
            "text": "        unpacked = Varicode::huffDecode(Varicode::defaultHuffTable(), bits);"
          },
          {
            "line": 1942,
            "text": "    }"
          },
          {
            "line": 1943,
            "text": ""
          },
          {
            "line": 1944,
            "text": "    return unpacked;"
          },
          {
            "line": 1945,
            "text": "}"
          },
          {
            "line": 1946,
            "text": ""
          }
        ]
      }
    },
    {
      "keyword": "FrameData",
      "path": "JS8_Main/Varicode.cpp",
      "line": 1532,
      "context": {
        "start_line": 1527,
        "end_line": 1537,
        "lines": [
          {
            "line": 1527,
            "text": "QString Varicode::packCompoundFrame(const QString &callsign, quint8 type,"
          },
          {
            "line": 1528,
            "text": "                                    quint16 num, quint8 bits3) {"
          },
          {
            "line": 1529,
            "text": "    QString frame;"
          },
          {
            "line": 1530,
            "text": ""
          },
          {
            "line": 1531,
            "text": "    // needs to be a compound type..."
          },
          {
            "line": 1532,
            "text": "    if (type == Varicode::FrameData || type == Varicode::FrameDirected) {"
          },
          {
            "line": 1533,
            "text": "        return frame;"
          },
          {
            "line": 1534,
            "text": "    }"
          },
          {
            "line": 1535,
            "text": ""
          },
          {
            "line": 1536,
            "text": "    quint8 packed_flag = type;"
          },
          {
            "line": 1537,
            "text": "    quint64 packed_callsign = Varicode::packAlphaNumeric50(callsign);"
          }
        ]
      }
    },
    {
      "keyword": "FrameData",
      "path": "JS8_Main/Varicode.cpp",
      "line": 1576,
      "context": {
        "start_line": 1571,
        "end_line": 1581,
        "lines": [
          {
            "line": 1571,
            "text": "    quint8 packed_3 = packed_8 & ((1 << 3) - 1);"
          },
          {
            "line": 1572,
            "text": ""
          },
          {
            "line": 1573,
            "text": "    quint8 packed_flag = Varicode::bitsToInt(bits.mid(0, 3));"
          },
          {
            "line": 1574,
            "text": ""
          },
          {
            "line": 1575,
            "text": "    // needs to be a ping type..."
          },
          {
            "line": 1576,
            "text": "    if (packed_flag == Varicode::FrameData ||"
          },
          {
            "line": 1577,
            "text": "        packed_flag == Varicode::FrameDirected) {"
          },
          {
            "line": 1578,
            "text": "        return unpacked;"
          },
          {
            "line": 1579,
            "text": "    }"
          },
          {
            "line": 1580,
            "text": ""
          },
          {
            "line": 1581,
            "text": "    quint64 packed_callsign = Varicode::bitsToInt(bits.mid(3, 50));"
          }
        ]
      }
    },
    {
      "keyword": "JS8CallData",
      "path": "JS8_Main/Varicode.cpp",
      "line": 1842,
      "context": {
        "start_line": 1837,
        "end_line": 1847,
        "lines": [
          {
            "line": 1837,
            "text": "    // The first bit is a flag that indicates this is a data frame, technically"
          },
          {
            "line": 1838,
            "text": "    // encoded as [100] but, since none of the other frame types start with a 1,"
          },
          {
            "line": 1839,
            "text": "    // we can drop the two zeros and use them for encoding the first two bits of"
          },
          {
            "line": 1840,
            "text": "    // the actuall data sent. boom! The second bit is a flag that indicates this"
          },
          {
            "line": 1841,
            "text": "    // is a compressed frame (dense coding) For fast modes, we don't use the"
          },
          {
            "line": 1842,
            "text": "    // prefix since it is indicated by the JS8CallData flag."
          },
          {
            "line": 1843,
            "text": "    QVector<bool> frameBits;"
          },
          {
            "line": 1844,
            "text": "    if (!prefix.isEmpty()) {"
          },
          {
            "line": 1845,
            "text": "        frameBits << prefix;"
          },
          {
            "line": 1846,
            "text": "    }"
          },
          {
            "line": 1847,
            "text": ""
          }
        ]
      }
    },
    {
      "keyword": "JS8CallData",
      "path": "JS8_Main/Varicode.cpp",
      "line": 2307,
      "context": {
        "start_line": 2302,
        "end_line": 2312,
        "lines": [
          {
            "line": 2302,
            "text": "                }"
          },
          {
            "line": 2303,
            "text": "            }"
          },
          {
            "line": 2304,
            "text": ""
          },
          {
            "line": 2305,
            "text": "            if (useDat) {"
          },
          {
            "line": 2306,
            "text": "                // use the standard data frame"
          },
          {
            "line": 2307,
            "text": "                lineFrames.append({frame, fastDataFrame ? Varicode::JS8CallData"
          },
          {
            "line": 2308,
            "text": "                                                        : Varicode::JS8Call});"
          },
          {
            "line": 2309,
            "text": "                line = line.mid(m);"
          },
          {
            "line": 2310,
            "text": "            }"
          },
          {
            "line": 2311,
            "text": "        }"
          },
          {
            "line": 2312,
            "text": ""
          }
        ]
      }
    },
    {
      "keyword": "lastIndexOf(0)",
      "path": "JS8_Main/Varicode.cpp",
      "line": 1931,
      "context": {
        "start_line": 1926,
        "end_line": 1936,
        "lines": [
          {
            "line": 1926,
            "text": "    }"
          },
          {
            "line": 1927,
            "text": ""
          },
          {
            "line": 1928,
            "text": "    bits = bits.mid(1);"
          },
          {
            "line": 1929,
            "text": ""
          },
          {
            "line": 1930,
            "text": "    bool compressed = bits.at(0);"
          },
          {
            "line": 1931,
            "text": "    int n = bits.lastIndexOf(0);"
          },
          {
            "line": 1932,
            "text": ""
          },
          {
            "line": 1933,
            "text": "    // trim off the pad bits"
          },
          {
            "line": 1934,
            "text": "    bits = bits.mid(1, n - 1);"
          },
          {
            "line": 1935,
            "text": ""
          },
          {
            "line": 1936,
            "text": "    if (compressed) {"
          }
        ]
      }
    },
    {
      "keyword": "lastIndexOf(0)",
      "path": "JS8_Main/Varicode.cpp",
      "line": 1996,
      "context": {
        "start_line": 1991,
        "end_line": 2001,
        "lines": [
          {
            "line": 1991,
            "text": "    quint64 value = Varicode::unpack72bits(text, &rem);"
          },
          {
            "line": 1992,
            "text": "    auto bits = Varicode::intToBits(value, 64) + Varicode::intToBits(rem, 8);"
          },
          {
            "line": 1993,
            "text": ""
          },
          {
            "line": 1994,
            "text": "#if JS8_FAST_DATA_CAN_USE_HUFF"
          },
          {
            "line": 1995,
            "text": "    bool compressed = bits.at(0);"
          },
          {
            "line": 1996,
            "text": "    int n = bits.lastIndexOf(0);"
          },
          {
            "line": 1997,
            "text": ""
          },
          {
            "line": 1998,
            "text": "    // trim off the pad bits"
          },
          {
            "line": 1999,
            "text": "    bits = bits.mid(1, n - 1);"
          },
          {
            "line": 2000,
            "text": ""
          },
          {
            "line": 2001,
            "text": "    if (compressed) {"
          }
        ]
      }
    },
    {
      "keyword": "lastIndexOf(0)",
      "path": "JS8_Main/Varicode.cpp",
      "line": 2009,
      "context": {
        "start_line": 2004,
        "end_line": 2014,
        "lines": [
          {
            "line": 2004,
            "text": "    } else {"
          },
          {
            "line": 2005,
            "text": "        // huff decode the bits (without escapes)"
          },
          {
            "line": 2006,
            "text": "        unpacked = Varicode::huffDecode(Varicode::defaultHuffTable(), bits);"
          },
          {
            "line": 2007,
            "text": "    }"
          },
          {
            "line": 2008,
            "text": "#else"
          },
          {
            "line": 2009,
            "text": "    int n = bits.lastIndexOf(0);"
          },
          {
            "line": 2010,
            "text": ""
          },
          {
            "line": 2011,
            "text": "    // trim off the pad bits"
          },
          {
            "line": 2012,
            "text": "    bits = bits.mid(0, n);"
          },
          {
            "line": 2013,
            "text": ""
          },
          {
            "line": 2014,
            "text": "    // partial word (s,c)-dense coding with code tables"
          }
        ]
      }
    },
    {
      "keyword": "bits.mid",
      "path": "JS8_Main/Varicode.cpp",
      "line": 614,
      "context": {
        "start_line": 609,
        "end_line": 619,
        "lines": [
          {
            "line": 609,
            "text": "                    text.append(\" \");"
          },
          {
            "line": 610,
            "text": "                    found = false;"
          },
          {
            "line": 611,
            "text": "                    break;"
          },
          {
            "line": 612,
            "text": "                }"
          },
          {
            "line": 613,
            "text": "                text.append(key);"
          },
          {
            "line": 614,
            "text": "                bits = bits.mid(huff[key].length());"
          },
          {
            "line": 615,
            "text": "                found = true;"
          },
          {
            "line": 616,
            "text": "            }"
          },
          {
            "line": 617,
            "text": "        }"
          },
          {
            "line": 618,
            "text": "        if (!found) {"
          },
          {
            "line": 619,
            "text": "            break;"
          }
        ]
      }
    },
    {
      "keyword": "bits.mid",
      "path": "JS8_Main/Varicode.cpp",
      "line": 1573,
      "context": {
        "start_line": 1568,
        "end_line": 1578,
        "lines": [
          {
            "line": 1568,
            "text": "        Varicode::intToBits(Varicode::unpack72bits(text, &packed_8), 64);"
          },
          {
            "line": 1569,
            "text": ""
          },
          {
            "line": 1570,
            "text": "    quint8 packed_5 = packed_8 >> 3;"
          },
          {
            "line": 1571,
            "text": "    quint8 packed_3 = packed_8 & ((1 << 3) - 1);"
          },
          {
            "line": 1572,
            "text": ""
          },
          {
            "line": 1573,
            "text": "    quint8 packed_flag = Varicode::bitsToInt(bits.mid(0, 3));"
          },
          {
            "line": 1574,
            "text": ""
          },
          {
            "line": 1575,
            "text": "    // needs to be a ping type..."
          },
          {
            "line": 1576,
            "text": "    if (packed_flag == Varicode::FrameData ||"
          },
          {
            "line": 1577,
            "text": "        packed_flag == Varicode::FrameDirected) {"
          },
          {
            "line": 1578,
            "text": "        return unpacked;"
          }
        ]
      }
    },
    {
      "keyword": "bits.mid",
      "path": "JS8_Main/Varicode.cpp",
      "line": 1581,
      "context": {
        "start_line": 1576,
        "end_line": 1586,
        "lines": [
          {
            "line": 1576,
            "text": "    if (packed_flag == Varicode::FrameData ||"
          },
          {
            "line": 1577,
            "text": "        packed_flag == Varicode::FrameDirected) {"
          },
          {
            "line": 1578,
            "text": "        return unpacked;"
          },
          {
            "line": 1579,
            "text": "    }"
          },
          {
            "line": 1580,
            "text": ""
          },
          {
            "line": 1581,
            "text": "    quint64 packed_callsign = Varicode::bitsToInt(bits.mid(3, 50));"
          },
          {
            "line": 1582,
            "text": "    quint16 packed_11 = Varicode::bitsToInt(bits.mid(53, 11));"
          },
          {
            "line": 1583,
            "text": ""
          },
          {
            "line": 1584,
            "text": "    QString callsign = Varicode::unpackAlphaNumeric50(packed_callsign);"
          },
          {
            "line": 1585,
            "text": ""
          },
          {
            "line": 1586,
            "text": "    quint16 num = (packed_11 << 5) | packed_5;"
          }
        ]
      }
    },
    {
      "keyword": "bits.mid",
      "path": "JS8_Main/Varicode.cpp",
      "line": 1582,
      "context": {
        "start_line": 1577,
        "end_line": 1587,
        "lines": [
          {
            "line": 1577,
            "text": "        packed_flag == Varicode::FrameDirected) {"
          },
          {
            "line": 1578,
            "text": "        return unpacked;"
          },
          {
            "line": 1579,
            "text": "    }"
          },
          {
            "line": 1580,
            "text": ""
          },
          {
            "line": 1581,
            "text": "    quint64 packed_callsign = Varicode::bitsToInt(bits.mid(3, 50));"
          },
          {
            "line": 1582,
            "text": "    quint16 packed_11 = Varicode::bitsToInt(bits.mid(53, 11));"
          },
          {
            "line": 1583,
            "text": ""
          },
          {
            "line": 1584,
            "text": "    QString callsign = Varicode::unpackAlphaNumeric50(packed_callsign);"
          },
          {
            "line": 1585,
            "text": ""
          },
          {
            "line": 1586,
            "text": "    quint16 num = (packed_11 << 5) | packed_5;"
          },
          {
            "line": 1587,
            "text": ""
          }
        ]
      }
    },
    {
      "keyword": "pack72bits",
      "path": "JS8_Main/Varicode.cpp",
      "line": 767,
      "context": {
        "start_line": 762,
        "end_line": 772,
        "lines": [
          {
            "line": 762,
            "text": "    quint32 b = packed & 0xFFFFFFFF;"
          },
          {
            "line": 763,
            "text": "    return pack32bits(a) + pack32bits(b);"
          },
          {
            "line": 764,
            "text": "}"
          },
          {
            "line": 765,
            "text": ""
          },
          {
            "line": 766,
            "text": "// returns the first 64 bits and sets the last 8 bits in pRem"
          },
          {
            "line": 767,
            "text": "quint64 Varicode::unpack72bits(QString const &text, quint8 *pRem) {"
          },
          {
            "line": 768,
            "text": "    quint64 value = 0;"
          },
          {
            "line": 769,
            "text": "    quint8 rem = 0;"
          },
          {
            "line": 770,
            "text": "    quint8 mask2 = ((1 << 2) - 1);"
          },
          {
            "line": 771,
            "text": ""
          },
          {
            "line": 772,
            "text": "    for (int i = 0; i < 10; i++) {"
          }
        ]
      }
    },
    {
      "keyword": "pack72bits",
      "path": "JS8_Main/Varicode.cpp",
      "line": 787,
      "context": {
        "start_line": 782,
        "end_line": 792,
        "lines": [
          {
            "line": 782,
            "text": "    if (pRem)"
          },
          {
            "line": 783,
            "text": "        *pRem = rem;"
          },
          {
            "line": 784,
            "text": "    return value;"
          },
          {
            "line": 785,
            "text": "}"
          },
          {
            "line": 786,
            "text": ""
          },
          {
            "line": 787,
            "text": "QString Varicode::pack72bits(quint64 value, quint8 rem) {"
          },
          {
            "line": 788,
            "text": "    QChar packed[12]; // 12 x 6bit characters"
          },
          {
            "line": 789,
            "text": ""
          },
          {
            "line": 790,
            "text": "    quint8 mask4 = ((1 << 4) - 1);"
          },
          {
            "line": 791,
            "text": "    quint8 mask6 = ((1 << 6) - 1);"
          },
          {
            "line": 792,
            "text": ""
          }
        ]
      }
    },
    {
      "keyword": "pack72bits",
      "path": "JS8_Main/Varicode.cpp",
      "line": 1554,
      "context": {
        "start_line": 1549,
        "end_line": 1559,
        "lines": [
          {
            "line": 1549,
            "text": "    // [3][50][11],[5][3] = 72"
          },
          {
            "line": 1550,
            "text": "    auto bits = (Varicode::intToBits(packed_flag, 3) +"
          },
          {
            "line": 1551,
            "text": "                 Varicode::intToBits(packed_callsign, 50) +"
          },
          {
            "line": 1552,
            "text": "                 Varicode::intToBits(packed_11, 11));"
          },
          {
            "line": 1553,
            "text": ""
          },
          {
            "line": 1554,
            "text": "    return Varicode::pack72bits(Varicode::bitsToInt(bits), packed_8);"
          },
          {
            "line": 1555,
            "text": "}"
          },
          {
            "line": 1556,
            "text": ""
          },
          {
            "line": 1557,
            "text": "QStringList Varicode::unpackCompoundFrame(const QString &text, quint8 *pType,"
          },
          {
            "line": 1558,
            "text": "                                          quint16 *pNum, quint8 *pBits3) {"
          },
          {
            "line": 1559,
            "text": "    QStringList unpacked;"
          }
        ]
      }
    },
    {
      "keyword": "pack72bits",
      "path": "JS8_Main/Varicode.cpp",
      "line": 1568,
      "context": {
        "start_line": 1563,
        "end_line": 1573,
        "lines": [
          {
            "line": 1563,
            "text": "    }"
          },
          {
            "line": 1564,
            "text": ""
          },
          {
            "line": 1565,
            "text": "    // [3][50][11],[5][3] = 72"
          },
          {
            "line": 1566,
            "text": "    quint8 packed_8 = 0;"
          },
          {
            "line": 1567,
            "text": "    auto bits ="
          },
          {
            "line": 1568,
            "text": "        Varicode::intToBits(Varicode::unpack72bits(text, &packed_8), 64);"
          },
          {
            "line": 1569,
            "text": ""
          },
          {
            "line": 1570,
            "text": "    quint8 packed_5 = packed_8 >> 3;"
          },
          {
            "line": 1571,
            "text": "    quint8 packed_3 = packed_8 & ((1 << 3) - 1);"
          },
          {
            "line": 1572,
            "text": ""
          },
          {
            "line": 1573,
            "text": "    quint8 packed_flag = Varicode::bitsToInt(bits.mid(0, 3));"
          }
        ]
      }
    },
    {
      "keyword": "unpack72bits",
      "path": "JS8_Main/Varicode.cpp",
      "line": 767,
      "context": {
        "start_line": 762,
        "end_line": 772,
        "lines": [
          {
            "line": 762,
            "text": "    quint32 b = packed & 0xFFFFFFFF;"
          },
          {
            "line": 763,
            "text": "    return pack32bits(a) + pack32bits(b);"
          },
          {
            "line": 764,
            "text": "}"
          },
          {
            "line": 765,
            "text": ""
          },
          {
            "line": 766,
            "text": "// returns the first 64 bits and sets the last 8 bits in pRem"
          },
          {
            "line": 767,
            "text": "quint64 Varicode::unpack72bits(QString const &text, quint8 *pRem) {"
          },
          {
            "line": 768,
            "text": "    quint64 value = 0;"
          },
          {
            "line": 769,
            "text": "    quint8 rem = 0;"
          },
          {
            "line": 770,
            "text": "    quint8 mask2 = ((1 << 2) - 1);"
          },
          {
            "line": 771,
            "text": ""
          },
          {
            "line": 772,
            "text": "    for (int i = 0; i < 10; i++) {"
          }
        ]
      }
    },
    {
      "keyword": "unpack72bits",
      "path": "JS8_Main/Varicode.cpp",
      "line": 1568,
      "context": {
        "start_line": 1563,
        "end_line": 1573,
        "lines": [
          {
            "line": 1563,
            "text": "    }"
          },
          {
            "line": 1564,
            "text": ""
          },
          {
            "line": 1565,
            "text": "    // [3][50][11],[5][3] = 72"
          },
          {
            "line": 1566,
            "text": "    quint8 packed_8 = 0;"
          },
          {
            "line": 1567,
            "text": "    auto bits ="
          },
          {
            "line": 1568,
            "text": "        Varicode::intToBits(Varicode::unpack72bits(text, &packed_8), 64);"
          },
          {
            "line": 1569,
            "text": ""
          },
          {
            "line": 1570,
            "text": "    quint8 packed_5 = packed_8 >> 3;"
          },
          {
            "line": 1571,
            "text": "    quint8 packed_3 = packed_8 & ((1 << 3) - 1);"
          },
          {
            "line": 1572,
            "text": ""
          },
          {
            "line": 1573,
            "text": "    quint8 packed_flag = Varicode::bitsToInt(bits.mid(0, 3));"
          }
        ]
      }
    },
    {
      "keyword": "unpack72bits",
      "path": "JS8_Main/Varicode.cpp",
      "line": 1726,
      "context": {
        "start_line": 1721,
        "end_line": 1731,
        "lines": [
          {
            "line": 1721,
            "text": "        return unpacked;"
          },
          {
            "line": 1722,
            "text": "    }"
          },
          {
            "line": 1723,
            "text": ""
          },
          {
            "line": 1724,
            "text": "    // [3][28][22][11],[2][6] = 72"
          },
          {
            "line": 1725,
            "text": "    quint8 extra = 0;"
          },
          {
            "line": 1726,
            "text": "    auto bits = Varicode::intToBits(Varicode::unpack72bits(text, &extra), 64);"
          },
          {
            "line": 1727,
            "text": ""
          },
          {
            "line": 1728,
            "text": "    quint8 packed_flag = Varicode::bitsToInt(bits.mid(0, 3));"
          },
          {
            "line": 1729,
            "text": "    if (packed_flag != Varicode::FrameDirected) {"
          },
          {
            "line": 1730,
            "text": "        return unpacked;"
          },
          {
            "line": 1731,
            "text": "    }"
          }
        ]
      }
    },
    {
      "keyword": "unpack72bits",
      "path": "JS8_Main/Varicode.cpp",
      "line": 1920,
      "context": {
        "start_line": 1915,
        "end_line": 1925,
        "lines": [
          {
            "line": 1915,
            "text": "    if (text.length() < 12 || text.contains(\" \")) {"
          },
          {
            "line": 1916,
            "text": "        return unpacked;"
          },
          {
            "line": 1917,
            "text": "    }"
          },
          {
            "line": 1918,
            "text": ""
          },
          {
            "line": 1919,
            "text": "    quint8 rem = 0;"
          },
          {
            "line": 1920,
            "text": "    quint64 value = Varicode::unpack72bits(text, &rem);"
          },
          {
            "line": 1921,
            "text": "    auto bits = Varicode::intToBits(value, 64) + Varicode::intToBits(rem, 8);"
          },
          {
            "line": 1922,
            "text": ""
          },
          {
            "line": 1923,
            "text": "    bool isData = bits.at(0);"
          },
          {
            "line": 1924,
            "text": "    if (!isData) {"
          },
          {
            "line": 1925,
            "text": "        return unpacked;"
          }
        ]
      }
    },
    {
      "keyword": "buildMessageFrames",
      "path": "JS8_Main/Varicode.cpp",
      "line": 159,
      "context": {
        "start_line": 154,
        "end_line": 164,
        "lines": [
          {
            "line": 154,
            "text": "    R\"(^\\s*(?<callsign>[@](?:ALLCALL|HB)\\s+)?(?<type>CQ CQ CQ|CQ DX|CQ QRP|CQ CONTEST|CQ FIELD|CQ FD|CQ CQ|CQ|HB|HEARTBEAT(?!\\s+SNR))(?:\\s(?<grid>[A-R]{2}[0-9]{2}))?\\b)\");"
          },
          {
            "line": 155,
            "text": ""
          },
          {
            "line": 156,
            "text": "QRegularExpression"
          },
          {
            "line": 157,
            "text": "    compound_re(\"^\\\\s*[`]\" + callsign_pattern + \"(?<extra>\" +"
          },
          {
            "line": 158,
            "text": "                optional_grid_pattern + // there's a reason this is first (see:"
          },
          {
            "line": 159,
            "text": "                                        // buildMessageFrames)"
          },
          {
            "line": 160,
            "text": "                optional_cmd_pattern + optional_num_pattern + \")\");"
          },
          {
            "line": 161,
            "text": ""
          },
          {
            "line": 162,
            "text": "QMap<QString, QString> hufftable = {"
          },
          {
            "line": 163,
            "text": "    // char   code                 weight"
          },
          {
            "line": 164,
            "text": "    {\" \", \"01\"},       // 1.0"
          }
        ]
      }
    },
    {
      "keyword": "buildMessageFrames",
      "path": "JS8_Main/Varicode.cpp",
      "line": 2023,
      "context": {
        "start_line": 2018,
        "end_line": 2028,
        "lines": [
          {
            "line": 2018,
            "text": "    return unpacked;"
          },
          {
            "line": 2019,
            "text": "}"
          },
          {
            "line": 2020,
            "text": ""
          },
          {
            "line": 2021,
            "text": "// TODO: remove the dependence on providing all this data?"
          },
          {
            "line": 2022,
            "text": "QList<QPair<QString, int>>"
          },
          {
            "line": 2023,
            "text": "Varicode::buildMessageFrames(QString const &mycall, QString const &mygrid,"
          },
          {
            "line": 2024,
            "text": "                             QString const &selectedCall, QString const &text,"
          },
          {
            "line": 2025,
            "text": "                             bool forceIdentify, bool forceData, int submode,"
          },
          {
            "line": 2026,
            "text": "                             MessageInfo *pInfo) {"
          },
          {
            "line": 2027,
            "text": ""
          },
          {
            "line": 2028,
            "text": "#define ALLOW_SEND_COMPOUND 1"
          }
        ]
      }
    },
    {
      "keyword": "buildMessageFrames",
      "path": "JS8_Main/Varicode.cpp",
      "line": 2335,
      "context": {
        "start_line": 2330,
        "end_line": 2340,
        "lines": [
          {
            "line": 2330,
            "text": "      m_forceIdentify{forceIdentify}, m_forceData{forceData},"
          },
          {
            "line": 2331,
            "text": "      m_submode{submode} {}"
          },
          {
            "line": 2332,
            "text": ""
          },
          {
            "line": 2333,
            "text": "void BuildMessageFramesThread::run() {"
          },
          {
            "line": 2334,
            "text": "    auto results ="
          },
          {
            "line": 2335,
            "text": "        Varicode::buildMessageFrames(m_mycall, m_mygrid, m_selectedCall, m_text,"
          },
          {
            "line": 2336,
            "text": "                                     m_forceIdentify, m_forceData, m_submode);"
          },
          {
            "line": 2337,
            "text": ""
          },
          {
            "line": 2338,
            "text": "    // TODO: jsherer - we wouldn't normally use DecodedText.h here... but it's"
          },
          {
            "line": 2339,
            "text": "    // useful for computing the actual frames transmitted."
          },
          {
            "line": 2340,
            "text": "    QStringList textList;"
          }
        ]
      }
    },
    {
      "keyword": "unpackDataMessage",
      "path": "JS8_Main/Varicode.h",
      "line": 189,
      "context": {
        "start_line": 184,
        "end_line": 194,
        "lines": [
          {
            "line": 184,
            "text": "                                       QString *pNum, int *n);"
          },
          {
            "line": 185,
            "text": "    static QStringList unpackDirectedMessage(QString const &text,"
          },
          {
            "line": 186,
            "text": "                                             quint8 *pType);"
          },
          {
            "line": 187,
            "text": ""
          },
          {
            "line": 188,
            "text": "    static QString packDataMessage(QString const &text, int *n);"
          },
          {
            "line": 189,
            "text": "    static QString unpackDataMessage(QString const &text);"
          },
          {
            "line": 190,
            "text": ""
          },
          {
            "line": 191,
            "text": "    static QString packFastDataMessage(QString const &text, int *n);"
          },
          {
            "line": 192,
            "text": "    static QString unpackFastDataMessage(QString const &text);"
          },
          {
            "line": 193,
            "text": ""
          },
          {
            "line": 194,
            "text": "    static QList<QPair<QString, int>>"
          }
        ]
      }
    },
    {
      "keyword": "unpackFastDataMessage",
      "path": "JS8_Main/Varicode.h",
      "line": 192,
      "context": {
        "start_line": 187,
        "end_line": 197,
        "lines": [
          {
            "line": 187,
            "text": ""
          },
          {
            "line": 188,
            "text": "    static QString packDataMessage(QString const &text, int *n);"
          },
          {
            "line": 189,
            "text": "    static QString unpackDataMessage(QString const &text);"
          },
          {
            "line": 190,
            "text": ""
          },
          {
            "line": 191,
            "text": "    static QString packFastDataMessage(QString const &text, int *n);"
          },
          {
            "line": 192,
            "text": "    static QString unpackFastDataMessage(QString const &text);"
          },
          {
            "line": 193,
            "text": ""
          },
          {
            "line": 194,
            "text": "    static QList<QPair<QString, int>>"
          },
          {
            "line": 195,
            "text": "    buildMessageFrames(QString const &mycall, QString const &mygrid,"
          },
          {
            "line": 196,
            "text": "                       QString const &selectedCall, QString const &text,"
          },
          {
            "line": 197,
            "text": "                       bool forceIdentify, bool forceData, int submode,"
          }
        ]
      }
    },
    {
      "keyword": "huffDecode",
      "path": "JS8_Main/Varicode.h",
      "line": 107,
      "context": {
        "start_line": 102,
        "end_line": 112,
        "lines": [
          {
            "line": 102,
            "text": "    static QStringList parseCallsigns(QString const &input);"
          },
          {
            "line": 103,
            "text": "    static QStringList parseGrids(QString const &input);"
          },
          {
            "line": 104,
            "text": ""
          },
          {
            "line": 105,
            "text": "    static QList<QPair<int, QVector<bool>>>"
          },
          {
            "line": 106,
            "text": "    huffEncode(const QMap<QString, QString> &huff, QString const &text);"
          },
          {
            "line": 107,
            "text": "    static QString huffDecode(const QMap<QString, QString> &huff,"
          },
          {
            "line": 108,
            "text": "                              QVector<bool> const &bitvec);"
          },
          {
            "line": 109,
            "text": "    static QSet<QString> huffValidChars(const QMap<QString, QString> &huff);"
          },
          {
            "line": 110,
            "text": ""
          },
          {
            "line": 111,
            "text": "    static QVector<bool> bytesToBits(char *bitvec, int n);"
          },
          {
            "line": 112,
            "text": "    static QVector<bool> strToBits(QString const &bitvec);"
          }
        ]
      }
    },
    {
      "keyword": "defaultHuffTable",
      "path": "JS8_Main/Varicode.h",
      "line": 88,
      "context": {
        "start_line": 83,
        "end_line": 93,
        "lines": [
          {
            "line": 83,
            "text": "    static QString unescape(const QString &text);"
          },
          {
            "line": 84,
            "text": ""
          },
          {
            "line": 85,
            "text": "    static QString rstrip(const QString &str);"
          },
          {
            "line": 86,
            "text": "    static QString lstrip(const QString &str);"
          },
          {
            "line": 87,
            "text": ""
          },
          {
            "line": 88,
            "text": "    static QMap<QString, QString> defaultHuffTable();"
          },
          {
            "line": 89,
            "text": "    static QString cqString(int number);"
          },
          {
            "line": 90,
            "text": "    static QString hbString(int number);"
          },
          {
            "line": 91,
            "text": "    static bool startsWithCQ(QString text);"
          },
          {
            "line": 92,
            "text": "    static bool startsWithHB(QString text);"
          },
          {
            "line": 93,
            "text": "    static QString formatSNR(int snr);"
          }
        ]
      }
    },
    {
      "keyword": "FrameDataCompressed",
      "path": "JS8_Main/Varicode.h",
      "line": 56,
      "context": {
        "start_line": 51,
        "end_line": 61,
        "lines": [
          {
            "line": 51,
            "text": "        FrameCompound = 1,         // [001]"
          },
          {
            "line": 52,
            "text": "        FrameCompoundDirected = 2, // [010]"
          },
          {
            "line": 53,
            "text": "        FrameDirected = 3,         // [011]"
          },
          {
            "line": 54,
            "text": "        FrameData = 4, // [10X] // but this only encodes the first 2 msb bits"
          },
          {
            "line": 55,
            "text": "                       // and drops the lsb"
          },
          {
            "line": 56,
            "text": "        FrameDataCompressed = 6, // [11X] // but this only encodes the first 2"
          },
          {
            "line": 57,
            "text": "                                 // msb bits and drops the lsb"
          },
          {
            "line": 58,
            "text": "    };"
          },
          {
            "line": 59,
            "text": ""
          },
          {
            "line": 60,
            "text": "    static const quint8 FrameTypeMax = 6;"
          },
          {
            "line": 61,
            "text": ""
          }
        ]
      }
    },
    {
      "keyword": "FrameDataCompressed",
      "path": "JS8_Main/Varicode.h",
      "line": 67,
      "context": {
        "start_line": 62,
        "end_line": 72,
        "lines": [
          {
            "line": 62,
            "text": "    static QString frameTypeString(quint8 type) {"
          },
          {
            "line": 63,
            "text": "        const char *FrameTypeStrings[] = {"
          },
          {
            "line": 64,
            "text": "            \"FrameHeartbeat\",      \"FrameCompound\", \"FrameCompoundDirected\","
          },
          {
            "line": 65,
            "text": "            \"FrameDirected\",       \"FrameData\","
          },
          {
            "line": 66,
            "text": "            \"FrameUnknown\", // 5"
          },
          {
            "line": 67,
            "text": "            \"FrameDataCompressed\","
          },
          {
            "line": 68,
            "text": "        };"
          },
          {
            "line": 69,
            "text": ""
          },
          {
            "line": 70,
            "text": "        if (type > FrameTypeMax) {"
          },
          {
            "line": 71,
            "text": "            return \"FrameUnknown\";"
          },
          {
            "line": 72,
            "text": "        }"
          }
        ]
      }
    },
    {
      "keyword": "FrameData",
      "path": "JS8_Main/Varicode.h",
      "line": 54,
      "context": {
        "start_line": 49,
        "end_line": 59,
        "lines": [
          {
            "line": 49,
            "text": "        FrameUnknown = 255,        // [11111111] <- only used as a sentinel"
          },
          {
            "line": 50,
            "text": "        FrameHeartbeat = 0,        // [000]"
          },
          {
            "line": 51,
            "text": "        FrameCompound = 1,         // [001]"
          },
          {
            "line": 52,
            "text": "        FrameCompoundDirected = 2, // [010]"
          },
          {
            "line": 53,
            "text": "        FrameDirected = 3,         // [011]"
          },
          {
            "line": 54,
            "text": "        FrameData = 4, // [10X] // but this only encodes the first 2 msb bits"
          },
          {
            "line": 55,
            "text": "                       // and drops the lsb"
          },
          {
            "line": 56,
            "text": "        FrameDataCompressed = 6, // [11X] // but this only encodes the first 2"
          },
          {
            "line": 57,
            "text": "                                 // msb bits and drops the lsb"
          },
          {
            "line": 58,
            "text": "    };"
          },
          {
            "line": 59,
            "text": ""
          }
        ]
      }
    },
    {
      "keyword": "FrameData",
      "path": "JS8_Main/Varicode.h",
      "line": 56,
      "context": {
        "start_line": 51,
        "end_line": 61,
        "lines": [
          {
            "line": 51,
            "text": "        FrameCompound = 1,         // [001]"
          },
          {
            "line": 52,
            "text": "        FrameCompoundDirected = 2, // [010]"
          },
          {
            "line": 53,
            "text": "        FrameDirected = 3,         // [011]"
          },
          {
            "line": 54,
            "text": "        FrameData = 4, // [10X] // but this only encodes the first 2 msb bits"
          },
          {
            "line": 55,
            "text": "                       // and drops the lsb"
          },
          {
            "line": 56,
            "text": "        FrameDataCompressed = 6, // [11X] // but this only encodes the first 2"
          },
          {
            "line": 57,
            "text": "                                 // msb bits and drops the lsb"
          },
          {
            "line": 58,
            "text": "    };"
          },
          {
            "line": 59,
            "text": ""
          },
          {
            "line": 60,
            "text": "    static const quint8 FrameTypeMax = 6;"
          },
          {
            "line": 61,
            "text": ""
          }
        ]
      }
    },
    {
      "keyword": "FrameData",
      "path": "JS8_Main/Varicode.h",
      "line": 65,
      "context": {
        "start_line": 60,
        "end_line": 70,
        "lines": [
          {
            "line": 60,
            "text": "    static const quint8 FrameTypeMax = 6;"
          },
          {
            "line": 61,
            "text": ""
          },
          {
            "line": 62,
            "text": "    static QString frameTypeString(quint8 type) {"
          },
          {
            "line": 63,
            "text": "        const char *FrameTypeStrings[] = {"
          },
          {
            "line": 64,
            "text": "            \"FrameHeartbeat\",      \"FrameCompound\", \"FrameCompoundDirected\","
          },
          {
            "line": 65,
            "text": "            \"FrameDirected\",       \"FrameData\","
          },
          {
            "line": 66,
            "text": "            \"FrameUnknown\", // 5"
          },
          {
            "line": 67,
            "text": "            \"FrameDataCompressed\","
          },
          {
            "line": 68,
            "text": "        };"
          },
          {
            "line": 69,
            "text": ""
          },
          {
            "line": 70,
            "text": "        if (type > FrameTypeMax) {"
          }
        ]
      }
    },
    {
      "keyword": "FrameData",
      "path": "JS8_Main/Varicode.h",
      "line": 67,
      "context": {
        "start_line": 62,
        "end_line": 72,
        "lines": [
          {
            "line": 62,
            "text": "    static QString frameTypeString(quint8 type) {"
          },
          {
            "line": 63,
            "text": "        const char *FrameTypeStrings[] = {"
          },
          {
            "line": 64,
            "text": "            \"FrameHeartbeat\",      \"FrameCompound\", \"FrameCompoundDirected\","
          },
          {
            "line": 65,
            "text": "            \"FrameDirected\",       \"FrameData\","
          },
          {
            "line": 66,
            "text": "            \"FrameUnknown\", // 5"
          },
          {
            "line": 67,
            "text": "            \"FrameDataCompressed\","
          },
          {
            "line": 68,
            "text": "        };"
          },
          {
            "line": 69,
            "text": ""
          },
          {
            "line": 70,
            "text": "        if (type > FrameTypeMax) {"
          },
          {
            "line": 71,
            "text": "            return \"FrameUnknown\";"
          },
          {
            "line": 72,
            "text": "        }"
          }
        ]
      }
    },
    {
      "keyword": "JS8CallData",
      "path": "JS8_Main/Varicode.h",
      "line": 37,
      "context": {
        "start_line": 32,
        "end_line": 42,
        "lines": [
          {
            "line": 32,
            "text": "    // frame type transmitted via itype and decoded by the ft8 decoded"
          },
          {
            "line": 33,
            "text": "    enum TransmissionType {"
          },
          {
            "line": 34,
            "text": "        JS8Call = 0,      // [000] <- any other frame of the message"
          },
          {
            "line": 35,
            "text": "        JS8CallFirst = 1, // [001] <- the first frame of a message"
          },
          {
            "line": 36,
            "text": "        JS8CallLast = 2,  // [010] <- the last frame of a message"
          },
          {
            "line": 37,
            "text": "        JS8CallData = 4,  // [100] <- flagged frame (no frame type header)"
          },
          {
            "line": 38,
            "text": "    };"
          },
          {
            "line": 39,
            "text": ""
          },
          {
            "line": 40,
            "text": "    /*"
          },
          {
            "line": 41,
            "text": ""
          },
          {
            "line": 42,
            "text": "    000 = heartbeat"
          }
        ]
      }
    },
    {
      "keyword": "pack72bits",
      "path": "JS8_Main/Varicode.h",
      "line": 135,
      "context": {
        "start_line": 130,
        "end_line": 140,
        "lines": [
          {
            "line": 130,
            "text": "    static QString pack32bits(quint32 packed);"
          },
          {
            "line": 131,
            "text": ""
          },
          {
            "line": 132,
            "text": "    static quint64 unpack64bits(QString const &value);"
          },
          {
            "line": 133,
            "text": "    static QString pack64bits(quint64 packed);"
          },
          {
            "line": 134,
            "text": ""
          },
          {
            "line": 135,
            "text": "    static quint64 unpack72bits(QString const &value, quint8 *pRem);"
          },
          {
            "line": 136,
            "text": "    static QString pack72bits(quint64 value, quint8 rem);"
          },
          {
            "line": 137,
            "text": ""
          },
          {
            "line": 138,
            "text": "    static quint32 packAlphaNumeric22(QString const &value, bool isFlag);"
          },
          {
            "line": 139,
            "text": "    static QString unpackAlphaNumeric22(quint32 packed, bool *isFlag);"
          },
          {
            "line": 140,
            "text": ""
          }
        ]
      }
    },
    {
      "keyword": "pack72bits",
      "path": "JS8_Main/Varicode.h",
      "line": 136,
      "context": {
        "start_line": 131,
        "end_line": 141,
        "lines": [
          {
            "line": 131,
            "text": ""
          },
          {
            "line": 132,
            "text": "    static quint64 unpack64bits(QString const &value);"
          },
          {
            "line": 133,
            "text": "    static QString pack64bits(quint64 packed);"
          },
          {
            "line": 134,
            "text": ""
          },
          {
            "line": 135,
            "text": "    static quint64 unpack72bits(QString const &value, quint8 *pRem);"
          },
          {
            "line": 136,
            "text": "    static QString pack72bits(quint64 value, quint8 rem);"
          },
          {
            "line": 137,
            "text": ""
          },
          {
            "line": 138,
            "text": "    static quint32 packAlphaNumeric22(QString const &value, bool isFlag);"
          },
          {
            "line": 139,
            "text": "    static QString unpackAlphaNumeric22(quint32 packed, bool *isFlag);"
          },
          {
            "line": 140,
            "text": ""
          },
          {
            "line": 141,
            "text": "    static quint64 packAlphaNumeric50(QString const &value);"
          }
        ]
      }
    },
    {
      "keyword": "unpack72bits",
      "path": "JS8_Main/Varicode.h",
      "line": 135,
      "context": {
        "start_line": 130,
        "end_line": 140,
        "lines": [
          {
            "line": 130,
            "text": "    static QString pack32bits(quint32 packed);"
          },
          {
            "line": 131,
            "text": ""
          },
          {
            "line": 132,
            "text": "    static quint64 unpack64bits(QString const &value);"
          },
          {
            "line": 133,
            "text": "    static QString pack64bits(quint64 packed);"
          },
          {
            "line": 134,
            "text": ""
          },
          {
            "line": 135,
            "text": "    static quint64 unpack72bits(QString const &value, quint8 *pRem);"
          },
          {
            "line": 136,
            "text": "    static QString pack72bits(quint64 value, quint8 rem);"
          },
          {
            "line": 137,
            "text": ""
          },
          {
            "line": 138,
            "text": "    static quint32 packAlphaNumeric22(QString const &value, bool isFlag);"
          },
          {
            "line": 139,
            "text": "    static QString unpackAlphaNumeric22(quint32 packed, bool *isFlag);"
          },
          {
            "line": 140,
            "text": ""
          }
        ]
      }
    },
    {
      "keyword": "buildMessageFrames",
      "path": "JS8_Main/Varicode.h",
      "line": 16,
      "context": {
        "start_line": 11,
        "end_line": 21,
        "lines": [
          {
            "line": 11,
            "text": "#include <QThread>"
          },
          {
            "line": 12,
            "text": "#include <QVector>"
          },
          {
            "line": 13,
            "text": ""
          },
          {
            "line": 14,
            "text": "class Varicode {"
          },
          {
            "line": 15,
            "text": "  public:"
          },
          {
            "line": 16,
            "text": "    // extra information out of buildMessageFrames"
          },
          {
            "line": 17,
            "text": "    struct MessageInfo {"
          },
          {
            "line": 18,
            "text": "        QString dirTo;"
          },
          {
            "line": 19,
            "text": "        QString dirCmd;"
          },
          {
            "line": 20,
            "text": "        QString dirNum;"
          },
          {
            "line": 21,
            "text": "    };"
          }
        ]
      }
    },
    {
      "keyword": "buildMessageFrames",
      "path": "JS8_Main/Varicode.h",
      "line": 195,
      "context": {
        "start_line": 190,
        "end_line": 200,
        "lines": [
          {
            "line": 190,
            "text": ""
          },
          {
            "line": 191,
            "text": "    static QString packFastDataMessage(QString const &text, int *n);"
          },
          {
            "line": 192,
            "text": "    static QString unpackFastDataMessage(QString const &text);"
          },
          {
            "line": 193,
            "text": ""
          },
          {
            "line": 194,
            "text": "    static QList<QPair<QString, int>>"
          },
          {
            "line": 195,
            "text": "    buildMessageFrames(QString const &mycall, QString const &mygrid,"
          },
          {
            "line": 196,
            "text": "                       QString const &selectedCall, QString const &text,"
          },
          {
            "line": 197,
            "text": "                       bool forceIdentify, bool forceData, int submode,"
          },
          {
            "line": 198,
            "text": "                       MessageInfo *pInfo = nullptr);"
          },
          {
            "line": 199,
            "text": "};"
          },
          {
            "line": 200,
            "text": ""
          }
        ]
      }
    },
    {
      "keyword": "JSC::decompress",
      "path": "JS8_JSC/JSC.cpp",
      "line": 127,
      "context": {
        "start_line": 122,
        "end_line": 132,
        "lines": [
          {
            "line": 122,
            "text": " * @brief Decompresses the given bit vector into a string."
          },
          {
            "line": 123,
            "text": " *"
          },
          {
            "line": 124,
            "text": " * @param bitvec"
          },
          {
            "line": 125,
            "text": " * @return QString"
          },
          {
            "line": 126,
            "text": " */"
          },
          {
            "line": 127,
            "text": "QString JSC::decompress(Codeword const &bitvec) {"
          },
          {
            "line": 128,
            "text": "    const quint32 b = 4;"
          },
          {
            "line": 129,
            "text": "    const quint32 s = 7;"
          },
          {
            "line": 130,
            "text": "    const quint32 c = pow(2, b) - s;"
          },
          {
            "line": 131,
            "text": ""
          },
          {
            "line": 132,
            "text": "    QStringList out;"
          }
        ]
      }
    },
    {
      "keyword": "JSC::compress",
      "path": "JS8_JSC/JSC.cpp",
      "line": 71,
      "context": {
        "start_line": 66,
        "end_line": 76,
        "lines": [
          {
            "line": 66,
            "text": " * @brief Compresses the given text into a list of codeword pairs."
          },
          {
            "line": 67,
            "text": " *"
          },
          {
            "line": 68,
            "text": " * @param text"
          },
          {
            "line": 69,
            "text": " * @return QList<CodewordPair>"
          },
          {
            "line": 70,
            "text": " */"
          },
          {
            "line": 71,
            "text": "QList<CodewordPair> JSC::compress(QString text) {"
          },
          {
            "line": 72,
            "text": "    QList<CodewordPair> out;"
          },
          {
            "line": 73,
            "text": ""
          },
          {
            "line": 74,
            "text": "    const quint32 b = 4;"
          },
          {
            "line": 75,
            "text": "    const quint32 s = 7;"
          },
          {
            "line": 76,
            "text": "    const quint32 c = pow(2, 4) - s;"
          }
        ]
      }
    }
  ],
  "function_body_previews": [
    {
      "path": "JS8_Main/Varicode.cpp",
      "line": 1912,
      "pattern": "QString\\s+Varicode::unpackDataMessage\\s*\\(",
      "chars": 849,
      "context": {
        "start_line": 1909,
        "end_line": 1915,
        "lines": [
          {
            "line": 1909,
            "text": "// TODO: DEPRECATED in 2.2 (still available for decoding legacy frames, but will"
          },
          {
            "line": 1910,
            "text": "// eventually no longer be decodable) unpack data message using 70 bits"
          },
          {
            "line": 1911,
            "text": "// available flagged as data by the first 2 bits"
          },
          {
            "line": 1912,
            "text": "QString Varicode::unpackDataMessage(const QString &text) {"
          },
          {
            "line": 1913,
            "text": "    QString unpacked;"
          },
          {
            "line": 1914,
            "text": ""
          },
          {
            "line": 1915,
            "text": "    if (text.length() < 12 || text.contains(\" \")) {"
          }
        ]
      },
      "body_preview": "QString Varicode::unpackDataMessage(const QString &text) {\n    QString unpacked;\n\n    if (text.length() < 12 || text.contains(\" \")) {\n        return unpacked;\n    }\n\n    quint8 rem = 0;\n    quint64 value = Varicode::unpack72bits(text, &rem);\n    auto bits = Varicode::intToBits(value, 64) + Varicode::intToBits(rem, 8);\n\n    bool isData = bits.at(0);\n    if (!isData) {\n        return unpacked;\n    }\n\n    bits = bits.mid(1);\n\n    bool compressed = bits.at(0);\n    int n = bits.lastIndexOf(0);\n\n    // trim off the pad bits\n    bits = bits.mid(1, n - 1);\n\n    if (compressed) {\n        // partial word (s,c)-dense coding with code tables\n        unpacked = JSC::decompress(bits);\n    } else {\n        // huff decode the bits (without escapes)\n        unpacked = Varicode::huffDecode(Varicode::defaultHuffTable(), bits);\n    }\n\n    return unpacked;\n}"
    },
    {
      "path": "JS8_Main/Varicode.cpp",
      "line": 1983,
      "pattern": "QString\\s+Varicode::unpackFastDataMessage\\s*\\(",
      "chars": 976,
      "context": {
        "start_line": 1980,
        "end_line": 1986,
        "lines": [
          {
            "line": 1980,
            "text": ""
          },
          {
            "line": 1981,
            "text": "// unpack data message using the full 72 bits available (with the data flag in"
          },
          {
            "line": 1982,
            "text": "// the i3bit header)"
          },
          {
            "line": 1983,
            "text": "QString Varicode::unpackFastDataMessage(const QString &text) {"
          },
          {
            "line": 1984,
            "text": "    QString unpacked;"
          },
          {
            "line": 1985,
            "text": ""
          },
          {
            "line": 1986,
            "text": "    if (text.length() < 12 || text.contains(\" \")) {"
          }
        ]
      },
      "body_preview": "QString Varicode::unpackFastDataMessage(const QString &text) {\n    QString unpacked;\n\n    if (text.length() < 12 || text.contains(\" \")) {\n        return unpacked;\n    }\n\n    quint8 rem = 0;\n    quint64 value = Varicode::unpack72bits(text, &rem);\n    auto bits = Varicode::intToBits(value, 64) + Varicode::intToBits(rem, 8);\n\n#if JS8_FAST_DATA_CAN_USE_HUFF\n    bool compressed = bits.at(0);\n    int n = bits.lastIndexOf(0);\n\n    // trim off the pad bits\n    bits = bits.mid(1, n - 1);\n\n    if (compressed) {\n        // partial word (s,c)-dense coding with code tables\n        unpacked = JSC::decompress(bits);\n    } else {\n        // huff decode the bits (without escapes)\n        unpacked = Varicode::huffDecode(Varicode::defaultHuffTable(), bits);\n    }\n#else\n    int n = bits.lastIndexOf(0);\n\n    // trim off the pad bits\n    bits = bits.mid(0, n);\n\n    // partial word (s,c)-dense coding with code tables\n    unpacked = JSC::decompress(bits);\n#endif\n\n    return unpacked;\n}"
    },
    {
      "path": "JS8_Main/Varicode.cpp",
      "line": 1830,
      "pattern": "QString\\s+packCompressedMessage\\s*\\(",
      "chars": 1818,
      "context": {
        "start_line": 1827,
        "end_line": 1833,
        "lines": [
          {
            "line": 1827,
            "text": "    return frame;"
          },
          {
            "line": 1828,
            "text": "}"
          },
          {
            "line": 1829,
            "text": ""
          },
          {
            "line": 1830,
            "text": "QString packCompressedMessage(const QString &input, QVector<bool> prefix,"
          },
          {
            "line": 1831,
            "text": "                              int *n) {"
          },
          {
            "line": 1832,
            "text": "    static const int frameSize = 72;"
          },
          {
            "line": 1833,
            "text": ""
          }
        ]
      },
      "body_preview": "QString packCompressedMessage(const QString &input, QVector<bool> prefix,\n                              int *n) {\n    static const int frameSize = 72;\n\n    QString frame;\n\n    // [1][1][70] = 72\n    // The first bit is a flag that indicates this is a data frame, technically\n    // encoded as [100] but, since none of the other frame types start with a 1,\n    // we can drop the two zeros and use them for encoding the first two bits of\n    // the actuall data sent. boom! The second bit is a flag that indicates this\n    // is a compressed frame (dense coding) For fast modes, we don't use the\n    // prefix since it is indicated by the JS8CallData flag.\n    QVector<bool> frameBits;\n    if (!prefix.isEmpty()) {\n        frameBits << prefix;\n    }\n\n    int i = 0;\n    foreach (auto pair, JSC::compress(input)) {\n        auto bits = pair.first;\n        auto chars = pair.second;\n\n        if (frameBits.length() + bits.length() < frameSize) {\n            frameBits.append(bits);\n            i += chars;\n            continue;\n        }\n\n        break;\n    }\n\n    qCDebug(varicode_js8) << \"Compressed bits\" << frameBits.length() << \"chars\"\n                          << i;\n\n    int pad = frameSize - frameBits.length();\n    if (pad) {\n        // the way we will pad is this...\n        // set the bit after the frame to 0 and every bit after that a 1\n        // to unpad, seek from the end of the bits until you hit a zero... the\n        // rest is the actual frame.\n        for (int i = 0; i < pad; i++) {\n            frameBits.append(i == 0 ? (bool)0 : (bool)1);\n        }\n    }\n\n    quint64 value = Varicode::bitsToInt(frameBits.constBegin(), 64);\n    quint8 rem = (quint8)Varicode::bitsToInt(frameBits.constBegin() + 64, 8);\n    frame = Varicode::pack72bits(value, rem);\n\n    if (n)\n        *n = i;\n\n    return frame;\n}"
    },
    {
      "path": "JS8_Main/Varicode.cpp",
      "line": 597,
      "pattern": "QString\\s+Varicode::huffDecode\\s*\\(",
      "chars": 750,
      "context": {
        "start_line": 594,
        "end_line": 600,
        "lines": [
          {
            "line": 594,
            "text": "    return out;"
          },
          {
            "line": 595,
            "text": "}"
          },
          {
            "line": 596,
            "text": ""
          },
          {
            "line": 597,
            "text": "QString Varicode::huffDecode(QMap<QString, QString> const &huff,"
          },
          {
            "line": 598,
            "text": "                             QVector<bool> const &bitvec) {"
          },
          {
            "line": 599,
            "text": "    QString text;"
          },
          {
            "line": 600,
            "text": ""
          }
        ]
      },
      "body_preview": "QString Varicode::huffDecode(QMap<QString, QString> const &huff,\n                             QVector<bool> const &bitvec) {\n    QString text;\n\n    QString bits = Varicode::bitsToStr(bitvec);\n\n    // TODO: jsherer - this is naive...\n    while (bits.length() > 0) {\n        bool found = false;\n        foreach (auto key, huff.keys()) {\n            if (bits.startsWith(huff[key])) {\n                if (key == EOT) {\n                    text.append(\" \");\n                    found = false;\n                    break;\n                }\n                text.append(key);\n                bits = bits.mid(huff[key].length());\n                found = true;\n            }\n        }\n        if (!found) {\n            break;\n        }\n    }\n\n    return text;\n}"
    },
    {
      "path": "JS8_Main/Varicode.cpp",
      "line": 438,
      "pattern": "QMap<[^>]+>\\s+Varicode::defaultHuffTable\\s*\\(",
      "chars": 73,
      "context": {
        "start_line": 435,
        "end_line": 441,
        "lines": [
          {
            "line": 435,
            "text": "/*"
          },
          {
            "line": 436,
            "text": " * VARICODE"
          },
          {
            "line": 437,
            "text": " */"
          },
          {
            "line": 438,
            "text": "QMap<QString, QString> Varicode::defaultHuffTable() { return hufftable; }"
          },
          {
            "line": 439,
            "text": ""
          },
          {
            "line": 440,
            "text": "QString Varicode::cqString(int number) {"
          },
          {
            "line": 441,
            "text": "    if (!cqs.contains(number)) {"
          }
        ]
      },
      "body_preview": "QMap<QString, QString> Varicode::defaultHuffTable() { return hufftable; }"
    },
    {
      "path": "JS8_Main/Varicode.cpp",
      "line": 1938,
      "pattern": "\\bJSC::decompress\\s*\\(",
      "chars": 168,
      "context": {
        "start_line": 1935,
        "end_line": 1941,
        "lines": [
          {
            "line": 1935,
            "text": ""
          },
          {
            "line": 1936,
            "text": "    if (compressed) {"
          },
          {
            "line": 1937,
            "text": "        // partial word (s,c)-dense coding with code tables"
          },
          {
            "line": 1938,
            "text": "        unpacked = JSC::decompress(bits);"
          },
          {
            "line": 1939,
            "text": "    } else {"
          },
          {
            "line": 1940,
            "text": "        // huff decode the bits (without escapes)"
          },
          {
            "line": 1941,
            "text": "        unpacked = Varicode::huffDecode(Varicode::defaultHuffTable(), bits);"
          }
        ]
      },
      "body_preview": "JSC::decompress(bits);\n    } else {\n        // huff decode the bits (without escapes)\n        unpacked = Varicode::huffDecode(Varicode::defaultHuffTable(), bits);\n    }"
    },
    {
      "path": "JS8_Main/Varicode.cpp",
      "line": 2003,
      "pattern": "\\bJSC::decompress\\s*\\(",
      "chars": 168,
      "context": {
        "start_line": 2000,
        "end_line": 2006,
        "lines": [
          {
            "line": 2000,
            "text": ""
          },
          {
            "line": 2001,
            "text": "    if (compressed) {"
          },
          {
            "line": 2002,
            "text": "        // partial word (s,c)-dense coding with code tables"
          },
          {
            "line": 2003,
            "text": "        unpacked = JSC::decompress(bits);"
          },
          {
            "line": 2004,
            "text": "    } else {"
          },
          {
            "line": 2005,
            "text": "        // huff decode the bits (without escapes)"
          },
          {
            "line": 2006,
            "text": "        unpacked = Varicode::huffDecode(Varicode::defaultHuffTable(), bits);"
          }
        ]
      },
      "body_preview": "JSC::decompress(bits);\n    } else {\n        // huff decode the bits (without escapes)\n        unpacked = Varicode::huffDecode(Varicode::defaultHuffTable(), bits);\n    }"
    },
    {
      "path": "JS8_Main/Varicode.cpp",
      "line": 2015,
      "pattern": "\\bJSC::decompress\\s*\\(",
      "chars": 422,
      "context": {
        "start_line": 2012,
        "end_line": 2018,
        "lines": [
          {
            "line": 2012,
            "text": "    bits = bits.mid(0, n);"
          },
          {
            "line": 2013,
            "text": ""
          },
          {
            "line": 2014,
            "text": "    // partial word (s,c)-dense coding with code tables"
          },
          {
            "line": 2015,
            "text": "    unpacked = JSC::decompress(bits);"
          },
          {
            "line": 2016,
            "text": "#endif"
          },
          {
            "line": 2017,
            "text": ""
          },
          {
            "line": 2018,
            "text": "    return unpacked;"
          }
        ]
      },
      "body_preview": "JSC::decompress(bits);\n#endif\n\n    return unpacked;\n}\n\n// TODO: remove the dependence on providing all this data?\nQList<QPair<QString, int>>\nVaricode::buildMessageFrames(QString const &mycall, QString const &mygrid,\n                             QString const &selectedCall, QString const &text,\n                             bool forceIdentify, bool forceData, int submode,\n                             MessageInfo *pInfo) "
    },
    {
      "path": "JS8_Main/Varicode.cpp",
      "line": 1938,
      "pattern": "\\bdecompress\\s*\\(",
      "chars": 163,
      "context": {
        "start_line": 1935,
        "end_line": 1941,
        "lines": [
          {
            "line": 1935,
            "text": ""
          },
          {
            "line": 1936,
            "text": "    if (compressed) {"
          },
          {
            "line": 1937,
            "text": "        // partial word (s,c)-dense coding with code tables"
          },
          {
            "line": 1938,
            "text": "        unpacked = JSC::decompress(bits);"
          },
          {
            "line": 1939,
            "text": "    } else {"
          },
          {
            "line": 1940,
            "text": "        // huff decode the bits (without escapes)"
          },
          {
            "line": 1941,
            "text": "        unpacked = Varicode::huffDecode(Varicode::defaultHuffTable(), bits);"
          }
        ]
      },
      "body_preview": "decompress(bits);\n    } else {\n        // huff decode the bits (without escapes)\n        unpacked = Varicode::huffDecode(Varicode::defaultHuffTable(), bits);\n    }"
    },
    {
      "path": "JS8_Main/Varicode.cpp",
      "line": 2003,
      "pattern": "\\bdecompress\\s*\\(",
      "chars": 163,
      "context": {
        "start_line": 2000,
        "end_line": 2006,
        "lines": [
          {
            "line": 2000,
            "text": ""
          },
          {
            "line": 2001,
            "text": "    if (compressed) {"
          },
          {
            "line": 2002,
            "text": "        // partial word (s,c)-dense coding with code tables"
          },
          {
            "line": 2003,
            "text": "        unpacked = JSC::decompress(bits);"
          },
          {
            "line": 2004,
            "text": "    } else {"
          },
          {
            "line": 2005,
            "text": "        // huff decode the bits (without escapes)"
          },
          {
            "line": 2006,
            "text": "        unpacked = Varicode::huffDecode(Varicode::defaultHuffTable(), bits);"
          }
        ]
      },
      "body_preview": "decompress(bits);\n    } else {\n        // huff decode the bits (without escapes)\n        unpacked = Varicode::huffDecode(Varicode::defaultHuffTable(), bits);\n    }"
    },
    {
      "path": "JS8_Main/Varicode.cpp",
      "line": 2015,
      "pattern": "\\bdecompress\\s*\\(",
      "chars": 417,
      "context": {
        "start_line": 2012,
        "end_line": 2018,
        "lines": [
          {
            "line": 2012,
            "text": "    bits = bits.mid(0, n);"
          },
          {
            "line": 2013,
            "text": ""
          },
          {
            "line": 2014,
            "text": "    // partial word (s,c)-dense coding with code tables"
          },
          {
            "line": 2015,
            "text": "    unpacked = JSC::decompress(bits);"
          },
          {
            "line": 2016,
            "text": "#endif"
          },
          {
            "line": 2017,
            "text": ""
          },
          {
            "line": 2018,
            "text": "    return unpacked;"
          }
        ]
      },
      "body_preview": "decompress(bits);\n#endif\n\n    return unpacked;\n}\n\n// TODO: remove the dependence on providing all this data?\nQList<QPair<QString, int>>\nVaricode::buildMessageFrames(QString const &mycall, QString const &mygrid,\n                             QString const &selectedCall, QString const &text,\n                             bool forceIdentify, bool forceData, int submode,\n                             MessageInfo *pInfo) "
    },
    {
      "path": "JS8_Main/Varicode.cpp",
      "line": 1849,
      "pattern": "\\bcompress\\s*\\(",
      "chars": 261,
      "context": {
        "start_line": 1846,
        "end_line": 1852,
        "lines": [
          {
            "line": 1846,
            "text": "    }"
          },
          {
            "line": 1847,
            "text": ""
          },
          {
            "line": 1848,
            "text": "    int i = 0;"
          },
          {
            "line": 1849,
            "text": "    foreach (auto pair, JSC::compress(input)) {"
          },
          {
            "line": 1850,
            "text": "        auto bits = pair.first;"
          },
          {
            "line": 1851,
            "text": "        auto chars = pair.second;"
          },
          {
            "line": 1852,
            "text": ""
          }
        ]
      },
      "body_preview": "compress(input)) {\n        auto bits = pair.first;\n        auto chars = pair.second;\n\n        if (frameBits.length() + bits.length() < frameSize) {\n            frameBits.append(bits);\n            i += chars;\n            continue;\n        }\n\n        break;\n    }"
    },
    {
      "path": "JS8_JSC/JSC.cpp",
      "line": 127,
      "pattern": "\\bJSC::decompress\\s*\\(",
      "chars": 1810,
      "context": {
        "start_line": 124,
        "end_line": 130,
        "lines": [
          {
            "line": 124,
            "text": " * @param bitvec"
          },
          {
            "line": 125,
            "text": " * @return QString"
          },
          {
            "line": 126,
            "text": " */"
          },
          {
            "line": 127,
            "text": "QString JSC::decompress(Codeword const &bitvec) {"
          },
          {
            "line": 128,
            "text": "    const quint32 b = 4;"
          },
          {
            "line": 129,
            "text": "    const quint32 s = 7;"
          },
          {
            "line": 130,
            "text": "    const quint32 c = pow(2, b) - s;"
          }
        ]
      },
      "body_preview": "JSC::decompress(Codeword const &bitvec) {\n    const quint32 b = 4;\n    const quint32 s = 7;\n    const quint32 c = pow(2, b) - s;\n\n    QStringList out;\n\n    quint32 base[8];\n    base[0] = 0;\n    base[1] = s;\n    base[2] = base[1] + s * c;\n    base[3] = base[2] + s * c * c;\n    base[4] = base[3] + s * c * c * c;\n    base[5] = base[4] + s * c * c * c * c;\n    base[6] = base[5] + s * c * c * c * c * c;\n    base[7] = base[6] + s * c * c * c * c * c * c;\n\n    QList<quint64> bytes;\n    QList<quint32> separators;\n\n    int i = 0;\n    int count = bitvec.count();\n    while (i < count) {\n        auto b = bitvec.mid(i, 4);\n        if (b.length() != 4) {\n            break;\n        }\n        quint64 byte = Varicode::bitsToInt(b);\n        bytes.append(byte);\n        i += 4;\n\n        if (byte < s) {\n            if (count - i > 0 && bitvec.at(i)) {\n                separators.append(bytes.length() - 1);\n            }\n            i += 1;\n        }\n    }\n\n    quint32 start = 0;\n    while (start < (quint32)bytes.length()) {\n        quint32 k = 0;\n        quint32 j = 0;\n\n        while (start + k < (quint32)bytes.length() && bytes[start + k] >= s) {\n            j = j * c + (bytes[start + k] - s);\n            k++;\n        }\n        if (j >= JSC::size) {\n            break;\n        }\n\n        if (start + k >= (quint32)bytes.length()) {\n            break;\n        }\n        j = j * s + bytes[start + k] + base[k];\n\n        if (j >= JSC::size) {\n            break;\n        }\n\n        // map is in latin1 format, not utf-8\n        auto word = QLatin1String(JSC::map[j].str);\n\n        out.append(word);\n        if (!separators.isEmpty() && separators.first() == start + k) {\n            out.append(\" \");\n            separators.removeFirst();\n        }\n\n        start = start + (k + 1);\n    }\n\n    return out.join(\"\");\n}"
    },
    {
      "path": "JS8_JSC/JSC.cpp",
      "line": 127,
      "pattern": "\\bdecompress\\s*\\(",
      "chars": 1805,
      "context": {
        "start_line": 124,
        "end_line": 130,
        "lines": [
          {
            "line": 124,
            "text": " * @param bitvec"
          },
          {
            "line": 125,
            "text": " * @return QString"
          },
          {
            "line": 126,
            "text": " */"
          },
          {
            "line": 127,
            "text": "QString JSC::decompress(Codeword const &bitvec) {"
          },
          {
            "line": 128,
            "text": "    const quint32 b = 4;"
          },
          {
            "line": 129,
            "text": "    const quint32 s = 7;"
          },
          {
            "line": 130,
            "text": "    const quint32 c = pow(2, b) - s;"
          }
        ]
      },
      "body_preview": "decompress(Codeword const &bitvec) {\n    const quint32 b = 4;\n    const quint32 s = 7;\n    const quint32 c = pow(2, b) - s;\n\n    QStringList out;\n\n    quint32 base[8];\n    base[0] = 0;\n    base[1] = s;\n    base[2] = base[1] + s * c;\n    base[3] = base[2] + s * c * c;\n    base[4] = base[3] + s * c * c * c;\n    base[5] = base[4] + s * c * c * c * c;\n    base[6] = base[5] + s * c * c * c * c * c;\n    base[7] = base[6] + s * c * c * c * c * c * c;\n\n    QList<quint64> bytes;\n    QList<quint32> separators;\n\n    int i = 0;\n    int count = bitvec.count();\n    while (i < count) {\n        auto b = bitvec.mid(i, 4);\n        if (b.length() != 4) {\n            break;\n        }\n        quint64 byte = Varicode::bitsToInt(b);\n        bytes.append(byte);\n        i += 4;\n\n        if (byte < s) {\n            if (count - i > 0 && bitvec.at(i)) {\n                separators.append(bytes.length() - 1);\n            }\n            i += 1;\n        }\n    }\n\n    quint32 start = 0;\n    while (start < (quint32)bytes.length()) {\n        quint32 k = 0;\n        quint32 j = 0;\n\n        while (start + k < (quint32)bytes.length() && bytes[start + k] >= s) {\n            j = j * c + (bytes[start + k] - s);\n            k++;\n        }\n        if (j >= JSC::size) {\n            break;\n        }\n\n        if (start + k >= (quint32)bytes.length()) {\n            break;\n        }\n        j = j * s + bytes[start + k] + base[k];\n\n        if (j >= JSC::size) {\n            break;\n        }\n\n        // map is in latin1 format, not utf-8\n        auto word = QLatin1String(JSC::map[j].str);\n\n        out.append(word);\n        if (!separators.isEmpty() && separators.first() == start + k) {\n            out.append(\" \");\n            separators.removeFirst();\n        }\n\n        start = start + (k + 1);\n    }\n\n    return out.join(\"\");\n}"
    },
    {
      "path": "JS8_JSC/JSC.cpp",
      "line": 71,
      "pattern": "\\bcompress\\s*\\(",
      "chars": 1327,
      "context": {
        "start_line": 68,
        "end_line": 74,
        "lines": [
          {
            "line": 68,
            "text": " * @param text"
          },
          {
            "line": 69,
            "text": " * @return QList<CodewordPair>"
          },
          {
            "line": 70,
            "text": " */"
          },
          {
            "line": 71,
            "text": "QList<CodewordPair> JSC::compress(QString text) {"
          },
          {
            "line": 72,
            "text": "    QList<CodewordPair> out;"
          },
          {
            "line": 73,
            "text": ""
          },
          {
            "line": 74,
            "text": "    const quint32 b = 4;"
          }
        ]
      },
      "body_preview": "compress(QString text) {\n    QList<CodewordPair> out;\n\n    const quint32 b = 4;\n    const quint32 s = 7;\n    const quint32 c = pow(2, 4) - s;\n\n    QString space(\" \");\n\n    QStringList words = text.split(\" \", Qt::KeepEmptyParts);\n\n    for (int i = 0, len = words.length(); i < len; i++) {\n        QString w = words[i];\n\n        bool isLastWord = (i == len - 1);\n        bool ok = false;\n        bool isSpaceCharacter = false;\n\n        // if this is an empty part, it should be a space, unless its the last\n        // word.\n        if (w.isEmpty() && !isLastWord) {\n            w = space;\n            isSpaceCharacter = true;\n        }\n\n        while (!w.isEmpty()) {\n            // this does both prefix and full match lookup\n            auto index = lookup(w, &ok);\n            if (!ok) {\n                break;\n            }\n\n            auto t = JSC::map[index];\n\n            w = QString(w).mid(t.size);\n\n            bool isLast = w.isEmpty();\n            bool shouldAppendSpace = isLast && !isSpaceCharacter && !isLastWord;\n\n            out.append(\n                {codeword(index, shouldAppendSpace, b, s, c),\n                 (quint32)t.size + (shouldAppendSpace\n                                        ? 1\n                                        : 0) /* for the space that follows */});\n        }\n    }\n\n    return out;\n}"
    }
  ],
  "webftr_adapter_hint": {
    "safe_to_poll_read_only": true,
    "productive_integration": false,
    "do_not_merge_as_chat_text_yet": true,
    "step68_contract_remains_current_ui_source": true
  },
  "verdict": "jsc_source_ready_no_data_frames_in_current_fixture",
  "warnings": [
    "Step69 is research/audit only and remains RX-only.",
    "No JS8 free-text rows are released by this step.",
    "JSC::decompress must be ported with source fixtures before FrameData/FrameDataCompressed can be shown as chat text."
  ],
  "next_action": "Port JSC::decompress using the extracted source path, then wait for or inject a FrameData/FrameDataCompressed fixture to validate free text."
}