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

354
LINES

< > BotCompany Repo | #1005964 // structure function (v12, to stream)

JavaX fragment (include)

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

Author comment

Began life as a copy of #1005656

download  show line numbers  debug dex  old transpilations   

Travelled to 15 computer(s): aoiabmzegqzx, bhatertpkbcr, cbybwowwnfue, cfunsshuasjs, gwrvuhgaqvyk, ishqpsrjomds, lpdgvwnxivlt, mqqgnosmbjvj, onxytkatvevr, pyentgdyhuwx, pzhvpgtvlbxg, sawdedvomwva, tslmcundralx, tvejysmllsmz, vouqrxazstgt

No comments. add comment

Snippet ID: #1005964
Snippet name: structure function (v12, to stream)
Eternal ID of this version: #1005964/8
Text MD5: cfd57cd284c7b4ad93bbd567aca39475
Author: stefan
Category: javax
Type: JavaX fragment (include)
Public (visible to everyone): Yes
Archived (hidden from active list): No
Created/modified: 2017-07-31 20:33:32
Source code size: 10075 bytes / 354 lines
Pitched / IR pitched: No / No
Views / Downloads: 484 / 612
Version history: 7 change(s)
Referenced in: [show references]