Warning: session_start(): open(/var/lib/php/sessions/sess_ukog48ussf6umnjlts1usirert, O_RDWR) failed: No space left on device (28) in /var/www/tb-usercake/models/config.php on line 51
Warning: session_start(): Failed to read session data: files (path: /var/lib/php/sessions) in /var/www/tb-usercake/models/config.php on line 51
!7
cmodule FluidTextFileSpike > DynPrintLog {
srecord Entry(S header, S text, SS params) {
long targetIndex;
S actualText() { ret unquote(text); }
}
switchable int maxRefLength = 8;
long maxFileSize() {
ret rangeOfNHexNumberWithNDigits(maxRefLength);
}
transient S demoContent = autoUnindent_mls([=[
refs="at *", name="index" [[
entry 1 at abc
entry 2 at def
]]
i=abc [[hello]]
i=def [[world]]
]=]);
start-thread {
print(demoContent);
Producer p = javaTok_onReader(stringReader(demoContent));
new StringBuilder buf;
new L entries;
S t;
p.next(); // skip initial white space
while ((t = p.next()) != null) {
if (isMLS(t)) {
S header = getAndClearStringBuilder(buf);
entries.add(new Entry(header, t, parseEqualsCommaProperties(header)));
p.next(); // skip white space
} else
buf.append(t); // part of entry header
}
pnlStruct(entries);
// make a map and pessimistically assign byte indices to all entries
new Map relocationMap;
for (Entry e : entries)
mapPut(relocationMap, e.params.get("i"), e);
makeIndices(entries);
print(+relocationMap);
// rewrite references
for (Entry e : entries)
if (hasReferences(e))
e.text = replaceRefs(e, r -> lookupInRelocationMap(relocationMap, r));
// write out
long idx = 0; // index into file
for (Entry e : entries) {
assertEquals(idx, e.targetIndex);
e.params.put("i", print("ref", renderReference(e.targetIndex)));
S line = entryToString(e, idx);
print_noNewLine(line);
idx += lUtf8(line);
}
}
S lookupInRelocationMap(Map relocationMap, S ref) {
Entry e = relocationMap.get(ref);
ret e == null ? null : renderReference(e.targetIndex);
}
S renderReference(long idx) {
ret takeLast(maxRefLength, longToHex(idx));
}
void makeIndices(L entries) {
long idx = 0; // index into file
for (Entry e : entries) {
e.targetIndex = idx;
idx += pessimisticEntryLength(e);
}
}
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(l(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());
}
ret l(entryToString(e2, dummyRef()));
}
S replaceRefs(Entry e, IF1 f) {
LS tok = javaTok(e.actualText());
for (int i : jfindAll(tok, "at *")) {
S x = f.get(tok.get(i));
if (nempty(x))
tok.set(i, x);
}
ret multiLineQuote(join(tok));
}
}