1 | // "seen" is now default |
2 | static String structure(Object o) { |
3 | return structure(o, 0, new IdentityHashMap); |
4 | } |
5 | |
6 | static String structure_seen(Object o) { |
7 | return structure(o, 0, new IdentityHashMap); |
8 | } |
9 | |
10 | // leave to false, unless unstructure() breaks |
11 | static boolean structure_allowShortening = false; |
12 | |
13 | static String structure(Object o, int stringSizeLimit, IdentityHashMap<O, Integer> seen) { |
14 | if (o == null) return "null"; |
15 | |
16 | // these are never back-referenced (for readability) |
17 | |
18 | if (o instanceof String) |
19 | return quote(stringSizeLimit != 0 ? shorten((String) o, stringSizeLimit) : (String) o); |
20 | |
21 | if (o instanceof BigInteger) |
22 | return "bigint(" + o + ")"; |
23 | |
24 | if (o instanceof Double) |
25 | return "d(" + quote(str(o)) + ")"; |
26 | |
27 | if (o instanceof Long) |
28 | return o + "L"; |
29 | |
30 | if (o instanceof Integer) |
31 | return str(o); |
32 | |
33 | if (seen != null) { |
34 | Integer ref = seen.get(o); |
35 | if (ref != null) |
36 | return "r" + ref; |
37 | |
38 | seen.put(o, seen.size()+1); |
39 | } |
40 | |
41 | String name = o.getClass().getName(); |
42 | |
43 | StringBuilder buf = new StringBuilder(); |
44 | |
45 | if (o instanceof HashSet) |
46 | return "hashset" + structure(new ArrayList((Set) o), stringSizeLimit, seen); |
47 | |
48 | if (o instanceof TreeSet) |
49 | return "treeset" + structure(new ArrayList((Set) o), stringSizeLimit, seen); |
50 | |
51 | if (o instanceof Collection) { |
52 | for (Object x : (Collection) o) { |
53 | if (buf.length() != 0) buf.append(", "); |
54 | buf.append(structure(x, stringSizeLimit, seen)); |
55 | } |
56 | return "[" + buf + "]"; |
57 | } |
58 | |
59 | if (o instanceof Map) { |
60 | for (Object e : ((Map) o).entrySet()) { |
61 | if (buf.length() != 0) buf.append(", "); |
62 | buf.append(structure(((Map.Entry) e).getKey(), stringSizeLimit, seen)); |
63 | buf.append("="); |
64 | buf.append(structure(((Map.Entry) e).getValue(), stringSizeLimit, seen)); |
65 | } |
66 | return (o instanceof HashMap ? "hashmap" : "") + "{" + buf + "}"; |
67 | } |
68 | |
69 | if (o.getClass().isArray()) { |
70 | int n = Array.getLength(o); |
71 | for (int i = 0; i < n; i++) { |
72 | if (buf.length() != 0) buf.append(", "); |
73 | buf.append(structure(Array.get(o, i), stringSizeLimit, seen)); |
74 | } |
75 | return "array{" + buf + "}"; |
76 | } |
77 | |
78 | if (o instanceof Class) |
79 | return "class(" + quote(((Class) o).getName()) + ")"; |
80 | |
81 | if (o instanceof Throwable) |
82 | return "exception(" + quote(((Throwable) o).getMessage()) + ")"; |
83 | |
84 | // Need more cases? This should cover all library classes... |
85 | if (name.startsWith("java.") || name.startsWith("javax.")) |
86 | return String.valueOf(o); |
87 | |
88 | String shortName = o.getClass().getName().replaceAll("^main\\$", ""); |
89 | |
90 | if (shortName.equals("Lisp")) { |
91 | buf.append("l(" + structure(getOpt(o, "head"), stringSizeLimit, seen)); |
92 | L args = cast getOpt(o, "args"); |
93 | if (nempty(args)) |
94 | for (int i = 0; i < l(args); i++) { |
95 | buf.append(", "); |
96 | O arg = args.get(i); |
97 | |
98 | // sweet shortening |
99 | if (arg != null && eq(arg.getClass().getName(), "main$Lisp") && isTrue(call(arg, "isEmpty"))) |
100 | arg = get(arg, "head"); |
101 | |
102 | buf.append(structure(arg, stringSizeLimit, seen)); |
103 | } |
104 | buf.append(")"); |
105 | ret str(buf); |
106 | } |
107 | |
108 | int numFields = 0; |
109 | String fieldName = ""; |
110 | if (shortName.equals("DynamicObject")) { |
111 | shortName = (String) get(o, "className"); |
112 | Map<String, Object> fieldValues = (Map) get(o, "fieldValues"); |
113 | |
114 | for (String _fieldName : fieldValues.keySet()) { |
115 | fieldName = _fieldName; |
116 | Object value = fieldValues.get(fieldName); |
117 | if (value != null) { |
118 | if (buf.length() != 0) buf.append(", "); |
119 | buf.append(fieldName + "=" + structure(value, stringSizeLimit, seen)); |
120 | } |
121 | ++numFields; |
122 | } |
123 | } else { |
124 | // regular class |
125 | |
126 | Class c = o.getClass(); |
127 | while (c != Object.class) { |
128 | Field[] fields = c.getDeclaredFields(); |
129 | for (Field field : fields) { |
130 | if ((field.getModifiers() & Modifier.STATIC) != 0) |
131 | continue; |
132 | fieldName = field.getName(); |
133 | |
134 | // skip outer object reference |
135 | if (fieldName.indexOf("$") >= 0) continue; |
136 | |
137 | Object value; |
138 | try { |
139 | field.setAccessible(true); |
140 | value = field.get(o); |
141 | } catch (Exception e) { |
142 | value = "?"; |
143 | } |
144 | |
145 | // put special cases here... |
146 | |
147 | if (value != null) { |
148 | if (buf.length() != 0) buf.append(", "); |
149 | buf.append(fieldName + "=" + structure(value, stringSizeLimit, seen)); |
150 | } |
151 | ++numFields; |
152 | } |
153 | c = c.getSuperclass(); |
154 | } |
155 | } |
156 | |
157 | String b = buf.toString(); |
158 | |
159 | if (numFields == 1 && structure_allowShortening) |
160 | b = b.replaceAll("^" + fieldName + "=", ""); // drop field name if only one |
161 | String s = shortName; |
162 | if (buf.length() != 0) |
163 | s += "(" + b + ")"; |
164 | return s; |
165 | } |
Began life as a copy of #1001386
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: | #1002825 |
Snippet name: | structure function (v5, with new backrefs, old) |
Eternal ID of this version: | #1002825/1 |
Text MD5: | 9b3f2ddc8c396f0f40c18558f1b24a0f |
Author: | stefan |
Category: | |
Type: | JavaX fragment (include) |
Public (visible to everyone): | Yes |
Archived (hidden from active list): | No |
Created/modified: | 2016-04-26 16:46:25 |
Source code size: | 4939 bytes / 165 lines |
Pitched / IR pitched: | No / No |
Views / Downloads: | 708 / 1450 |
Referenced in: | [show references] |