Not logged in.  Login/Logout/Register | List snippets | | Create snippet | Upload image | Upload data

294
LINES

< > BotCompany Repo | #1005603 // structure function (v10, counting tokens, new backrefs)

JavaX fragment (include)

1  
static bool structure_showTiming, structure_checkTokenCount;
2  
3  
static String structure(Object o) {
4  
  new structure_Data d;
5  
  structure_1(o, d);
6  
  long time = now();
7  
  S s = str(d.out);
8  
  if (structure_checkTokenCount) {
9  
    print("token count=" + d.n);
10  
    assertEquals("token count", l(javaTokC(s)), d.n);
11  
  }
12  
  ret s;
13  
}
14  
15  
// leave to false, unless unstructure() breaks
16  
static boolean structure_allowShortening = false;
17  
18  
static int structure_shareStringsLongerThan = 20;
19  
20  
static class structure_Data {
21  
  new StringBuilder out;
22  
  int stringSizeLimit;
23  
  new IdentityHashMap<O, Integer> seen;
24  
  new BitSet refd;
25  
  new HashMap<S, Int> strings;
26  
  new HashSet<S> concepts;
27  
  HashMap<Class, L<Field>> fieldsByClass = new HashMap;
28  
  Class conceptClass = findClass("Concept");
29  
  int n; // token count
30  
  
31  
  // append single token
32  
  structure_Data append(S token) { out.append(token); ++n; ret this; }
33  
  structure_Data append(int i) { out.append(i); ++n; ret this; }
34  
  
35  
  // append multiple tokens
36  
  structure_Data append(S token, int tokCount) { out.append(token); n += tokCount; ret this; }
37  
  
38  
  // extend last token
39  
  structure_Data app(S token) { out.append(token); ret this; }
40  
  structure_Data app(int i) { out.append(i); ret this; }
41  
}
42  
43  
static void structure_1(Object o, structure_Data d) {
44  
  StringBuilder out = d.out;
45  
  
46  
  if (o == null) { d.append("null"); ret; }
47  
  
48  
  Class c = o.getClass();
49  
  S name = c.getName();
50  
  S dynName = shortDynamicClassName(o);
51  
  bool concept = d.conceptClass != null && d.conceptClass.isInstance(o);
52  
  L<Field> lFields = d.fieldsByClass.get(c);
53  
  
54  
  if (lFields == null) {
55  
    // these are never back-referenced (for readability)
56  
    
57  
    if (o instanceof Number) {
58  
      if (o instanceof Integer) { out.append((int) o); d.n++; ret; }
59  
      if (o instanceof Long) { out.append((long) o).append("L"); d.n++; ret; }
60  
      if (o instanceof Float) { d.append("fl ", 2); quote_impl(str(o), out); ret; }
61  
      if (o instanceof Double) { d.append("d(", 3); quote_impl(str(o), out); d.append(")"); ret; }
62  
      if (o instanceof BigInteger) { out.append("bigint(").append(o).append(")"); d.n += 4; ret; }
63  
    }
64  
  
65  
    if (o instanceof Boolean) {
66  
      d.append(((Boolean) o).booleanValue() ? "t" : "f"); ret;
67  
    }
68  
      
69  
    if (o instanceof Character) {
70  
      d.append(quoteCharacter((Character) o)); ret;
71  
    }
72  
      
73  
    if (o instanceof File) {
74  
      d.append("File ").append(quote(((File) o).getPath())); ret;
75  
    }
76  
      
77  
    // referencable objects follow
78  
    
79  
    Integer ref = d.seen.get(o);
80  
    if (o instanceof S && ref == null)
81  
      ref = d.strings.get((S) o);
82  
      
83  
    if (ref != null) {
84  
      d.refd.set(ref);
85  
      d.append("t").app(ref); ret;
86  
    }
87  
    
88  
    ref = d.n; //d.seen.size()+1;
89  
    d.seen.put(o, ref);
90  
    //d.append("m").app(ref).app(" "); // marker
91  
    
92  
    if (o instanceof S) {
93  
      S s = d.stringSizeLimit != 0 ? shorten((S) o, d.stringSizeLimit) : (S) o;
94  
      if (l(s) >= structure_shareStringsLongerThan)
95  
        d.strings.put(s, ref);
96  
      quote_impl(s, out); d.n++; ret;
97  
    }
98  
      
99  
    if (o instanceof HashSet) {
100  
      d.append("hashset ");
101  
      structure_1(new ArrayList((Set) o), d);
102  
      ret;
103  
    }
104  
  
105  
    if (o instanceof TreeSet) {
106  
      d.append("treeset ");
107  
      structure_1(new ArrayList((Set) o), d);
108  
      ret;
109  
    }
110  
    
111  
    if (o instanceof Collection && neq(name, "main$Concept$RefL")) {
112  
      d.append("[");
113  
      int l = out.length();
114  
      for (Object x : (Collection) o) {
115  
        if (out.length() != l) d.append(", ");
116  
        structure_1(x, d);
117  
      }
118  
      d.append("]");
119  
      ret;
120  
    }
121  
    
122  
    if (o instanceof Map) {
123  
      if (o instanceof HashMap) d.append("hm");
124  
      d.append("{");
125  
      int l = out.length();
126  
      for (Object e : ((Map) o).entrySet()) {
127  
        if (out.length() != l) d.append(", ");
128  
        structure_1(((Map.Entry) e).getKey(), d);
129  
        d.append("=");
130  
        structure_1(((Map.Entry) e).getValue(), d);
131  
      }
132  
      d.append("}");
133  
      ret;
134  
    }
135  
    
136  
    if (c.isArray()) {
137  
      if (o instanceof byte[]) {
138  
        d.append("ba ").append(quote(bytesToHex((byte[]) o))); ret;
139  
      }
140  
  
141  
      int n = Array.getLength(o);
142  
  
143  
      if (o instanceof bool[]) {
144  
        S hex = boolArrayToHex((bool[]) o);
145  
        int i = l(hex);
146  
        while (i > 0 && hex.charAt(i-1) == '0' && hex.charAt(i-2) == '0') i -= 2;
147  
        d.append("boolarray ").append(n).app(" ").append(quote(substring(hex, 0, i))); ret;
148  
      }
149  
      
150  
      S atype = "array", sep = ", ";
151  
  
152  
      if (o instanceof int[]) {
153  
        //ret "intarray " + quote(intArrayToHex((int[]) o));
154  
        atype = "intarray";
155  
        sep = " ";
156  
      }
157  
      
158  
      d.append(atype).append("{");
159  
      for (int i = 0; i < n; i++) {
160  
        if (i != 0) d.append(sep);
161  
        structure_1(Array.get(o, i), d);
162  
      }
163  
      d.append("}"); ret;
164  
    }
165  
  
166  
    if (o instanceof Class) {
167  
      d.append("class(", 2).append(quote(((Class) o).getName())).append(")"); ret;
168  
    }
169  
      
170  
    if (o instanceof Throwable) {
171  
      d.append("exception(", 2).append(quote(((Throwable) o).getMessage())).append(")"); ret;
172  
    }
173  
      
174  
    if (o instanceof BitSet) {
175  
      BitSet bs = (BitSet) o;
176  
      d.append("bitset{", 2);
177  
      int l = out.length();
178  
      for (int i = bs.nextSetBit(0); i >= 0; i = bs.nextSetBit(i+1)) {
179  
        if (out.length() != l) d.append(", ");
180  
        d.append(i);
181  
      }
182  
      d.append("}"); ret;
183  
    }
184  
      
185  
    // Need more cases? This should cover all library classes...
186  
    if (name.startsWith("java.") || name.startsWith("javax.")) {
187  
      d.append("j ").append(quote(str(o))); ret; // Hm. this is not unstructure-able
188  
    }
189  
      
190  
    if (name.equals("main$Lisp")) {
191  
      d.append("l(", 2);
192  
      structure_1(getOpt(o, "head"), d);
193  
      L args = cast getOpt(o, "args");
194  
      if (nempty(args))
195  
        for (int i = 0; i < l(args); i++) {
196  
          d.append(", ");
197  
          O arg = args.get(i);
198  
          
199  
          // sweet shortening
200  
          if (arg != null && eq(arg.getClass().getName(), "main$Lisp") && isTrue(call(arg, "isEmpty")))
201  
            arg = get(arg, "head");
202  
            
203  
          structure_1(arg, d);
204  
        }
205  
      d.append(")"); ret;
206  
    }
207  
    
208  
    if (concept && !d.concepts.contains(dynName)) {
209  
      d.concepts.add(dynName);
210  
      d.append("c ");
211  
    }
212  
    
213  
    // serialize an object with fields.
214  
    // first, collect all fields and values in fv.
215  
    
216  
    TreeSet<Field> fields = new TreeSet<Field>(new Comparator<Field>() {
217  
      public int compare(Field a, Field b) {
218  
        ret stdcompare(a.getName(), b.getName());
219  
      }
220  
    });
221  
    
222  
    while (c != Object.class) {
223  
      for (Field field : getDeclaredFields_cached(c)) {
224  
        if ((field.getModifiers() & (Modifier.STATIC | Modifier.TRANSIENT)) != 0)
225  
          continue;
226  
        S fieldName = field.getName();
227  
        
228  
        fields.add(field);
229  
        
230  
        // put special cases here...
231  
      }
232  
        
233  
      c = c.getSuperclass();
234  
    }
235  
    
236  
    lFields = asList(fields);
237  
    
238  
    // put this$1 first
239  
    for (int i = 0; i < l(lFields); i++) {
240  
      Field f = lFields.get(i);
241  
      if (f.getName().equals("this$1")) {
242  
        lFields.remove(i);
243  
        lFields.add(0, f);
244  
        break;
245  
      }
246  
    }
247  
  
248  
    d.fieldsByClass.put(c, lFields);
249  
  }
250  
251  
  new LinkedHashMap<S, O> fv;
252  
  for (Field f : lFields) {
253  
    Object value;
254  
    try {
255  
      value = f.get(o);
256  
    } catch (Exception e) {
257  
      value = "?";
258  
    }
259  
      
260  
    if (value != null)
261  
      fv.put(f.getName(), value);
262  
  }
263  
  
264  
  String shortName = dropPrefix("main$", name);
265  
    
266  
  // Now we have fields & values. Process fieldValues if it's a DynamicObject.
267  
  
268  
  // omit field "className" if equal to class's name
269  
  if (concept && eq(fv.get("className"), shortName))
270  
    fv.remove("className");
271  
          
272  
  if (o instanceof DynamicObject) {
273  
    fv.putAll((Map) fv.get("fieldValues"));
274  
    fv.remove("fieldValues");
275  
    shortName = dynName;
276  
    fv.remove("className");
277  
  }
278  
  
279  
  S singleField = fv.size() == 1 ? first(fv.keySet()) : null;
280  
  
281  
  // Render this$1 first because unstructure needs it for constructor call.
282  
  
283  
  d.append(shortName).append("(");
284  
  int l = out.length();
285  
286  
  for (S fieldName : fv.keySet()) {
287  
    if (out.length() != l) d.append(", ");
288  
    d.append(fieldName).append("=");
289  
    structure_1(fv.get(fieldName), d);
290  
  }
291  
292  
  if (out.length() == l) { out.setLength(l-1); d.n--; } // drop "("
293  
  else d.append(")");
294  
}

Author comment

Began life as a copy of #1005596

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: #1005603
Snippet name: structure function (v10, counting tokens, new backrefs)
Eternal ID of this version: #1005603/1
Text MD5: bf5be7c6fcb52853ec93a58f4caf7015
Author: stefan
Category: javax
Type: JavaX fragment (include)
Public (visible to everyone): Yes
Archived (hidden from active list): No
Created/modified: 2016-12-01 00:25:11
Source code size: 8666 bytes / 294 lines
Pitched / IR pitched: No / No
Views / Downloads: 460 / 452
Referenced in: [show references]