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

310
LINES

< > BotCompany Repo | #1005656 // structure function (v11, virtual stack)

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

Author comment

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: 446 / 460
Referenced in: [show references]