feat(fls): system software settings as Java loads them
readSystemSoftware adds to each node what the topology needs from its system software: a switch's SSID and learning time, a host's wireless SSID, a router's RIP switch, the manual routes and the firewall of a router or home router. All 23 corpus files match Java. - A router's firewall is one object its constructor hangs in two places; the corpus writes it under the web server's "konfig" plug-in. The places are merged. - The decoder keeps entries a constructor made in a map, reached by get(key) (installed applications), like the elements of a list. - The Java oracle loads every file twice and writes values that differ as null: what FILIUS rolls (MACs, a switch's SSID) without text search. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
@@ -53,6 +53,11 @@ export interface JavaObject {
|
||||
* result. `add`/`set` go to `calls`, in order.
|
||||
*/
|
||||
readonly presetElements: Map<number, JavaValue>;
|
||||
/**
|
||||
* The same for a map: entries its constructor made (a router's installed
|
||||
* applications), reached by `<void method="get"><string>key</string>`.
|
||||
*/
|
||||
readonly presetEntries: Map<string, JavaValue>;
|
||||
/** True when the object was not in the file but returned by a getter. */
|
||||
readonly fromGetter: boolean;
|
||||
}
|
||||
@@ -139,12 +144,21 @@ function replayList(value: JavaObject, constructed: number): (JavaValue | undefi
|
||||
return items;
|
||||
}
|
||||
|
||||
/** The entries of a map: `put` calls in order. */
|
||||
/**
|
||||
* The entries of a map: the ones its constructor made, then `put` calls in
|
||||
* order — a later `put` of the same key replaces the value in place.
|
||||
*/
|
||||
export function mapEntries(value: JavaValue | undefined): [JavaValue, JavaValue][] {
|
||||
if (!isJavaObject(value)) return [];
|
||||
return value.calls
|
||||
.filter((call) => call.method === 'put')
|
||||
.map((call) => [call.args[0] ?? null, call.args[1] ?? null] as [JavaValue, JavaValue]);
|
||||
const entries: [JavaValue, JavaValue][] = [...value.presetEntries];
|
||||
for (const call of value.calls) {
|
||||
if (call.method !== 'put') continue;
|
||||
const key = call.args[0] ?? null;
|
||||
const existing = entries.find(([entryKey]) => entryKey === key);
|
||||
if (existing === undefined) entries.push([key, call.args[1] ?? null]);
|
||||
else existing[1] = call.args[1] ?? null;
|
||||
}
|
||||
return entries;
|
||||
}
|
||||
|
||||
// ── XML tree ───────────────────────────────────────────────────────────────
|
||||
@@ -226,6 +240,7 @@ function newObject(fields: Partial<JavaObject> & { className: string }): JavaObj
|
||||
properties: new Map(),
|
||||
calls: [],
|
||||
presetElements: new Map(),
|
||||
presetEntries: new Map(),
|
||||
fromGetter: fields.fromGetter ?? false,
|
||||
};
|
||||
}
|
||||
@@ -412,6 +427,7 @@ class Decoder {
|
||||
if (isJavaObject(target)) {
|
||||
target.calls.push({ method, args });
|
||||
if (method === 'get' && args.length === 1 && typeof args[0] === 'number') return this.getIndex(target, args[0], id);
|
||||
if (method === 'get' && args.length === 1 && typeof args[0] === 'string') return this.getEntry(target, args[0], id);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
@@ -463,6 +479,18 @@ class Decoder {
|
||||
return placeholder;
|
||||
}
|
||||
|
||||
/**
|
||||
* `map.get(key)`: the value put before, else an entry the map held before
|
||||
* the file touched it — a placeholder that later reads return.
|
||||
*/
|
||||
private getEntry(target: JavaObject, key: string, id: string | undefined): JavaValue {
|
||||
const put = mapEntries(target).find(([entryKey]) => entryKey === key);
|
||||
if (put !== undefined) return put[1];
|
||||
const placeholder = newObject({ className: id?.replace(/\d+$/, '') ?? 'unknown', id, fromGetter: true });
|
||||
target.presetEntries.set(key, placeholder);
|
||||
return placeholder;
|
||||
}
|
||||
|
||||
private setIndex(target: JavaValue | undefined, index: number, value: JavaValue): JavaValue {
|
||||
if (typeof target === 'object' && target !== null && (target as JavaArray).kind === 'array') {
|
||||
(target as JavaArray).items[index] = value;
|
||||
|
||||
Reference in New Issue
Block a user