static bool structure_showTiming, structure_checkTokenCount; static String structure(Object o) { new structure_Data d; structure_1(o, d); while (nempty(d.stack)) popLast(d.stack).run(); S s = str(d.out); if (structure_checkTokenCount) { print("token count=" + d.n); assertEquals("token count", l(javaTokC(s)), d.n); } ret s; } // leave to false, unless unstructure() breaks static boolean structure_allowShortening = false; static int structure_shareStringsLongerThan = 20; static class structure_Data { new StringBuilder out; int stringSizeLimit; new IdentityHashMap<O, Integer> seen; new BitSet refd; new HashMap<S, Int> strings; new HashSet<S> concepts; HashMap<Class, L<Field>> fieldsByClass = new HashMap; Class conceptClass = findClass("Concept"); int n; // token count new L<Runnable> stack; // append single token structure_Data append(S token) { out.append(token); ++n; ret this; } structure_Data append(int i) { out.append(i); ++n; ret this; } // append multiple tokens structure_Data append(S token, int tokCount) { out.append(token); n += tokCount; ret this; } // extend last token structure_Data app(S token) { out.append(token); ret this; } structure_Data app(int i) { out.append(i); ret this; } } static void structure_1(Object o, final structure_Data d) { final StringBuilder out = d.out; if (o == null) { d.append("null"); ret; } Class c = o.getClass(); S name = c.getName(); S dynName = shortDynamicClassName(o); bool concept = d.conceptClass != null && d.conceptClass.isInstance(o); L<Field> lFields = d.fieldsByClass.get(c); if (lFields == null) { // these are never back-referenced (for readability) if (o instanceof Number) { if (o instanceof Integer) { out.append(((Int) o).intValue()); d.n++; ret; } if (o instanceof Long) { out.append(((Long) o).longValue()).append("L"); d.n++; ret; } if (o instanceof Float) { d.append("fl ", 2); quote_impl(str(o), out); ret; } if (o instanceof Double) { d.append("d(", 3); quote_impl(str(o), out); d.append(")"); ret; } if (o instanceof BigInteger) { out.append("bigint(").append(o).append(")"); d.n += 4; ret; } } if (o instanceof Boolean) { d.append(((Boolean) o).booleanValue() ? "t" : "f"); ret; } if (o instanceof Character) { d.append(quoteCharacter((Character) o)); ret; } if (o instanceof File) { d.append("File ").append(quote(((File) o).getPath())); ret; } // referencable objects follow Integer ref = d.seen.get(o); if (o instanceof S && ref == null) ref = d.strings.get((S) o); if (ref != null) { d.refd.set(ref); d.append("t").app(ref); ret; } ref = d.n; //d.seen.size()+1; d.seen.put(o, ref); //d.append("m").app(ref).app(" "); // marker if (o instanceof S) { S s = d.stringSizeLimit != 0 ? shorten((S) o, d.stringSizeLimit) : (S) o; if (l(s) >= structure_shareStringsLongerThan) d.strings.put(s, ref); quote_impl(s, out); d.n++; ret; } if (o instanceof HashSet) { d.append("hashset "); structure_1(new ArrayList((Set) o), d); ret; } if (o instanceof TreeSet) { d.append("treeset "); structure_1(new ArrayList((Set) o), d); ret; } if (o instanceof Collection && neq(name, "main$Concept$RefL")) { d.append("["); final int l = out.length(); final Iterator it = ((Collection) o).iterator(); d.stack.add(r { if (!it.hasNext()) d.append("]"); else { d.stack.add(this); if (out.length() != l) d.append(", "); structure_1(it.next(), d); } }); ret; } if (o instanceof Map) { if (o instanceof HashMap) d.append("hm"); d.append("{"); final int l = out.length(); final Iterator it = ((Map) o).entrySet().iterator(); d.stack.add(new Runnable() { bool v; Map.Entry e; public void run() { if (v) { d.append("="); v = false; d.stack.add(this); structure_1(e.getValue(), d); } else { if (!it.hasNext()) d.append("}"); else { e = (Map.Entry) it.next(); v = true; d.stack.add(this); if (out.length() != l) d.append(", "); structure_1(e.getKey(), d); } } } }); ret; } if (c.isArray()) { if (o instanceof byte[]) { d.append("ba ").append(quote(bytesToHex((byte[]) o))); ret; } int n = Array.getLength(o); if (o instanceof bool[]) { S hex = boolArrayToHex((bool[]) o); int i = l(hex); while (i > 0 && hex.charAt(i-1) == '0' && hex.charAt(i-2) == '0') i -= 2; d.append("boolarray ").append(n).app(" ").append(quote(substring(hex, 0, i))); ret; } S atype = "array", sep = ", "; if (o instanceof int[]) { //ret "intarray " + quote(intArrayToHex((int[]) o)); atype = "intarray"; sep = " "; } d.append(atype).append("{"); for (int i = 0; i < n; i++) { if (i != 0) d.append(sep); structure_1(Array.get(o, i), d); } d.append("}"); ret; } if (o instanceof Class) { d.append("class(", 2).append(quote(((Class) o).getName())).append(")"); ret; } if (o instanceof Throwable) { d.append("exception(", 2).append(quote(((Throwable) o).getMessage())).append(")"); ret; } if (o instanceof BitSet) { BitSet bs = (BitSet) o; d.append("bitset{", 2); int l = out.length(); for (int i = bs.nextSetBit(0); i >= 0; i = bs.nextSetBit(i+1)) { if (out.length() != l) d.append(", "); d.append(i); } d.append("}"); ret; } // Need more cases? This should cover all library classes... if (name.startsWith("java.") || name.startsWith("javax.")) { d.append("j ").append(quote(str(o))); ret; // Hm. this is not unstructure-able } /*if (name.equals("main$Lisp")) { fail("lisp not supported right now"); }*/ if (concept && !d.concepts.contains(dynName)) { d.concepts.add(dynName); d.append("c "); } // serialize an object with fields. // first, collect all fields and values in fv. TreeSet<Field> fields = new TreeSet<Field>(new Comparator<Field>() { public int compare(Field a, Field b) { ret stdcompare(a.getName(), b.getName()); } }); while (c != Object.class) { for (Field field : getDeclaredFields_cached(c)) { if ((field.getModifiers() & (Modifier.STATIC | Modifier.TRANSIENT)) != 0) continue; S fieldName = field.getName(); fields.add(field); // put special cases here... } c = c.getSuperclass(); } lFields = asList(fields); // Render this$1 first because unstructure needs it for constructor call. for (int i = 0; i < l(lFields); i++) { Field f = lFields.get(i); if (f.getName().equals("this$1")) { lFields.remove(i); lFields.add(0, f); break; } } d.fieldsByClass.put(c, lFields); } new LinkedHashMap<S, O> fv; for (Field f : lFields) { Object value; try { value = f.get(o); } catch (Exception e) { value = "?"; } if (value != null) fv.put(f.getName(), value); } String shortName = dropPrefix("main$", name); // Now we have fields & values. Process fieldValues if it's a DynamicObject. // omit field "className" if equal to class's name if (concept && eq(fv.get("className"), shortName)) fv.remove("className"); if (o instanceof DynamicObject) { fv.putAll((Map) fv.get("fieldValues")); fv.remove("fieldValues"); shortName = dynName; fv.remove("className"); } S singleField = fv.size() == 1 ? first(fv.keySet()) : null; d.append(shortName); final int l = out.length(); final Iterator it = fv.entrySet().iterator(); d.stack.add(r { if (!it.hasNext()) { if (out.length() != l) d.append(")"); } else { Map.Entry e = (Map.Entry) it.next(); d.append(out.length() == l ? "(" : ", "); d.append((S) e.getKey()).append("="); d.stack.add(this); structure_1(e.getValue(), d); } }); }
Began life as a copy of #1005603
download show line numbers debug dex old transpilations
Travelled to 13 computer(s): aoiabmzegqzx, bhatertpkbcr, cbybwowwnfue, cfunsshuasjs, gwrvuhgaqvyk, ishqpsrjomds, lpdgvwnxivlt, mqqgnosmbjvj, pyentgdyhuwx, pzhvpgtvlbxg, tslmcundralx, tvejysmllsmz, vouqrxazstgt
No comments. add comment
Snippet ID: | #1005656 |
Snippet name: | structure function (v11, virtual stack) |
Eternal ID of this version: | #1005656/1 |
Text MD5: | b4257bbd790e4e9634dbc85245740929 |
Author: | stefan |
Category: | javax |
Type: | JavaX fragment (include) |
Public (visible to everyone): | Yes |
Archived (hidden from active list): | No |
Created/modified: | 2016-12-13 15:29:13 |
Source code size: | 8982 bytes / 310 lines |
Pitched / IR pitched: | No / No |
Views / Downloads: | 542 / 557 |
Referenced in: | [show references] |