Libraryless. Click here for Pure Java version (5188L/34K).
sclass CleanFluidTextFile implements Runnable { srecord Entry(S text, SS params) { long targetIndex; S actualText() { ret unquote(text); } } // set by user int maxRefLength = 8; bool verbose; Reader reader; Writer writer; // set by class new L<Entry> entries; new Map<S, Entry> relocationMap; long maxFileSize() { ret rangeOfNHexNumberWithNDigits(maxRefLength); } run { read(); write(); } void read ctex { Producer<S> tokenizer = javaTok_onReader(reader); FluidTextFileEntry entry; while ((entry = readFluidTextFileEntry(tokenizer)) != null) { if (!containsKey(entry.params, "_")) // not a deletable entry entries.add(new Entry(entry.quotedContent, entry.params)); } if (verbose) pnlStruct(entries); } void write ctex { // make a map and pessimistically assign byte indices to all entries for (Entry e : entries) mapPut(relocationMap, e.params.get("i"), e); makeIndices(entries); // rewrite references for (Entry e : entries) if (hasReferences(e)) e.text = replaceRefs(e, r -> lookupInRelocationMap(r)); // write out long idx = 0; // index into file for (Entry e : entries) { assertEquals(e.targetIndex, idx); e.params.put("i", renderReference(e.targetIndex)); S line = entryToString(e, idx); if (verbose) print(quote(line)); writer.write(line); int l = lUtf8(line); if (verbose) print("Actual entry length: " + l); idx += l; } } S lookupInRelocationMap(S ref) { Entry e = relocationMap.get(ref); //print("lookupInRelocationMap: " + ref + " => " + e); ret e == null ? null : renderReference(e.targetIndex); } S renderReference(long idx) { ret takeLast(maxRefLength, longToHex(idx)); } void makeIndices(L<Entry> entries) { long idx = 0; // index into file for (Entry e : entries) { e.targetIndex = idx; int l = pessimisticEntryLength(e); idx += l; if (verbose) print("Pessimistic entry length: " + l); } } S entryToString(Entry e, long idx) { ret entryToString(e, renderReference(idx)); } S entryToString(Entry e, S idx) { SS params = litorderedmap( i := idx, l := intToHex_flexLength(lUtf8(e.text))); mapPutAll_noOverwrite(params, e.params); ret renderEqualsCommaProperties(params) + " " + e.text + "\n"; } S dummyRef() { ret rep('0', maxRefLength); } bool hasReferences(Entry e) { ret eq(e.params.get("refs"), quote("at *")); } int pessimisticEntryLength(Entry e) { Entry e2 = e; if (hasReferences(e)) { e2 = cloneObject(e); e2.text = replaceRefs(e, r -> dummyRef()); if (verbose) print("Pessimistic: rewrote text to " + quote(e2.text)); } S s = entryToString(e2, dummyRef()); if (verbose) print(quote(s)); ret lUtf8(s); } S replaceRefs(Entry e, IF1<S> f) { LS tok = javaTokWithUnifiedNumbersAndIdentifiers(e.actualText()); for (int i : jfindAll(tok, "at *")) { S x = f.get(tok.get(i+2)); if (nempty(x)) tok.set(i+2, x); } ret multiLineQuote(join(tok)); } }
download show line numbers debug dex old transpilations
Travelled to 7 computer(s): bhatertpkbcr, mqqgnosmbjvj, pyentgdyhuwx, pzhvpgtvlbxg, tvejysmllsmz, vouqrxazstgt, xrpafgyirdlv
No comments. add comment
Snippet ID: | #1027374 |
Snippet name: | CleanFluidTextFile |
Eternal ID of this version: | #1027374/19 |
Text MD5: | ffa4dfe811c003225ea49771acaee792 |
Transpilation MD5: | b13db51370e86a00e50eebeda216e009 |
Author: | stefan |
Category: | javax / io |
Type: | JavaX fragment (include) |
Public (visible to everyone): | Yes |
Archived (hidden from active list): | No |
Created/modified: | 2020-03-15 17:11:10 |
Source code size: | 3353 bytes / 130 lines |
Pitched / IR pitched: | No / No |
Views / Downloads: | 264 / 668 |
Version history: | 18 change(s) |
Referenced in: | #1034167 - Standard Classes + Interfaces (LIVE, continuation of #1003674) |