sclass LineCompReader { new LS literals; new LPair pairs; new LinkedHashMap> versions; *(BufferedReader reader) ctex { S s = reader.readLine(); new Matches m; if (!startsWith(s, "LINECOMP ", m)) fail("Not a LINECOMP file"); int nLiterals = parseInt(m.rest()); for i to nLiterals: literals.add(assertNotNull(reader.readLine())); while licensed { s = reader.readLine(); if (s == null || contains(s, "=")) break; pairs.add(assertNotNull(listToPair(parseInts(splitAtSpace(s))))); } while (contains(s, "=")) { int i = indexOf(s, '='); versions.put(takeFirst(s, i), parseInts(splitAtSpace(substring(s, i+1)))); s = reader.readLine(); } } Set versions() { ret keys(versions); } S textForVersion(S version) { L encoded = versions.get(version); if (encoded == null) null; new LS buf; for (int idx : encoded) decode(idx, buf); ret lines_rtrim(buf); } void decode(int idx, LS buf) { if (idx < l(literals)) buf.add(literals.get(idx)); else { Pair p = pairs.get(idx-l(literals)); decode(p.a, buf); decode(p.b, buf); } } }