import java.util.*;
import java.util.zip.*;
import java.util.List;
import java.util.regex.*;
import java.util.concurrent.*;
import java.util.concurrent.atomic.*;
import javax.swing.*;
import javax.swing.event.*;
import javax.swing.text.*;
import javax.swing.table.*;
import java.io.*;
import java.net.*;
import java.lang.reflect.*;
import java.lang.ref.*;
import java.lang.management.*;
import java.security.*;
import java.security.spec.*;
import java.awt.*;
import java.awt.event.*;
import java.awt.image.*;
import javax.imageio.*;
import java.math.*;
public class main {
static class A {
String a;
public boolean equals(Object o) { return stdEq2(this, o); }
public int hashCode() { return stdHash2(this); }
}
static class B extends A {
String b;
public boolean equals(Object o) { return stdEq2(this, o); }
public int hashCode() { return stdHash2(this); }
}
static int n = 200000;
public static void main(String[] args) throws Exception {
List l = new ArrayList();
for (int i = 0; i < n; i++) {
l.add(nu(A.class, "a" , "AAA"));
l.add(nu(B.class, "a" , "ABC", "b" , "DEF"));
}
structure_showTiming = true;
String s = structure(l);
print("Have " + l(s) + " chars (" + n*2 + " objects)");
l = null;
for (int i = 0; i < 6; i++) { // give Server VM time to optimize
{ long _startTime_0 = now(); try {
unstructure(s);
} finally { _startTime_0 = now()-_startTime_0; saveTiming(_startTime_0); } }
print("\n==\n");
}
print("OK");
killVM();
}
static volatile StringBuffer local_log = new StringBuffer(); // not redirected
static volatile StringBuffer print_log = local_log; // might be redirected, e.g. to main bot
// in bytes - will cut to half that
static volatile int print_log_max = 1024*1024;
static volatile int local_log_max = 100*1024;
//static int print_maxLineLength = 0; // 0 = unset
static boolean print_silent; // total mute if set
static void print() {
print("");
}
// slightly overblown signature to return original object...
static A print(A o) {
ping();
if (print_silent) return o;
String s = String.valueOf(o) + "\n";
print_noNewLine(s);
return o;
}
static void print_noNewLine(String s) {
// TODO if (print_maxLineLength != 0)
StringBuffer loc = local_log;
StringBuffer buf = print_log;
int loc_max = print_log_max;
if (buf != loc && buf != null) {
print_append(buf, s, print_log_max);
loc_max = local_log_max;
}
if (loc != null)
print_append(loc, s, loc_max);
System.out.print(s);
}
static void print(long l) {
print(String.valueOf(l));
}
static void print(char c) {
print(String.valueOf(c));
}
static void print_append(StringBuffer buf, String s, int max) {
synchronized(buf) {
buf.append(s);
max /= 2;
if (buf.length() > max) try {
int newLength = max/2;
int ofs = buf.length()-newLength;
String newString = buf.substring(ofs);
buf.setLength(0);
buf.append("[...] ").append(newString);
} catch (Exception e) {
buf.setLength(0);
}
}
}
static void killVM() {
cleanKillVM();
}
static A nu(Class c, Object... values) {
A a = nuObject(c);
setOptAll(a, values);
return a;
}
static Object unstructure(String text) {
return unstructure(text, false);
}
static Object unstructure(String text, final boolean allDynamic) {
return unstructure(text, allDynamic, null);
}
static int structure_internStringsLongerThan = 50;
// classFinder: func(name) -> class (optional)
static Object unstructure(String text, final boolean allDynamic,
final Object classFinder) {
if (text == null) return null;
final List tok = javaTokC(text);
final boolean debug = unstructure_debug;
class X {
int i = 0;
HashMap refs = new HashMap();
HashMap tokrefs = new HashMap();
HashSet concepts = new HashSet();
HashMap classesMap = new HashMap();
Object parse() {
String t = tok.get(i);
int refID = 0;
if (structure_isMarker(t, 0, l(t))) {
refID = parseInt(t.substring(1));
i++;
}
// if (debug) print("parse: " + quote(t));
int tokIndex = i;
Object o = parse_inner(refID, tokIndex);
if (refID != 0)
refs.put(refID, o);
if (o != null)
tokrefs.put(tokIndex, o);
return o;
}
Object parse_inner(int refID, int tokIndex) {
String t = tok.get(i);
// if (debug) print("parse_inner: " + quote(t));
Class c = classesMap.get(t);
if (c == null) {
if (t.startsWith("\"")) {
String s = internIfLongerThan(unquote(tok.get(i)), structure_internStringsLongerThan);
i++;
return s;
}
if (t.startsWith("'"))
return unquoteCharacter(tok.get(i++));
if (t.equals("bigint"))
return parseBigInt();
if (t.equals("d"))
return parseDouble();
if (t.equals("fl"))
return parseFloat();
if (t.equals("false") || t.equals("f")) {
i++; return false;
}
if (t.equals("true") || t.equals("t")) {
i++; return true;
}
if (t.equals("-")) {
t = tok.get(i+1);
i += 2;
return isLongConstant(t) ? (Object) (-parseLong(t)) : (Object) (-parseInt(t));
}
if (isInteger(t) || isLongConstant(t)) {
i++;
//if (debug) print("isLongConstant " + quote(t) + " => " + isLongConstant(t));
if (isLongConstant(t)) return parseLong(t);
long l = parseLong(t);
boolean isInt = l == (int) l;
if (debug)
print("l=" + l + ", isInt: " + isInt);
return isInt ? (Object) new Integer((int) l) : (Object) new Long(l);
}
if (t.equals("File")) {
File f = new File(unquote(tok.get(i+1)));
i += 2;
return f;
}
if (t.startsWith("r") && isInteger(t.substring(1))) {
i++;
int ref = Integer.parseInt(t.substring(1));
Object o = refs.get(ref);
if (o == null)
print("Warning: unsatisfied back reference " + ref);
return o;
}
if (t.startsWith("t") && isInteger(t.substring(1))) {
i++;
int ref = Integer.parseInt(t.substring(1));
Object o = tokrefs.get(ref);
if (o == null)
print("Warning: unsatisfied token reference " + ref);
return o;
}
if (t.equals("hashset"))
return parseHashSet();
if (t.equals("treeset"))
return parseTreeSet();
if (eqOneOf(t, "hashmap", "hm"))
return parseHashMap();
if (t.equals("{"))
return parseMap();
if (t.equals("["))
return parseList();
if (t.equals("bitset"))
return parseBitSet();
if (t.equals("array") || t.equals("intarray"))
return parseArray();
if (t.equals("ba")) {
String hex = unquote(tok.get(i+1));
i += 2;
return hexToBytes(hex);
}
if (t.equals("boolarray")) {
int n = parseInt(tok.get(i+1));
String hex = unquote(tok.get(i+2));
i += 6;
return boolArrayFromBytes(hexToBytes(hex), n);
}
if (t.equals("class"))
return parseClass();
if (t.equals("l"))
return parseLisp();
if (t.equals("null")) {
i++; return null;
}
/* in dev.
if (!allDynamic && t.equals("run")) {
S snippetID = unquote(t.get(i+1));
i += 2;
run(
}
*/
if (eq(t, "c")) {
consume("c");
t = tok.get(i);
assertTrue(isJavaIdentifier(t));
concepts.add(t);
}
}
if (c == null && !isJavaIdentifier(t))
throw new RuntimeException("Unknown token " + (i+1) + ": " + t);
// any other class name
if (c == null) {
// First, find class
if (allDynamic) c = null;
else if (classFinder != null)
c = (Class) callF(classFinder, t);
else
c = findClass(t);
if (c != null)
classesMap.put(t, c);
}
// Check if it has an outer reference
i++;
boolean hasOuter = eq(get(tok, i), "(") && eq(get(tok, i+1), "this$1");
DynamicObject dO = null;
Object o = null;
if (c != null)
o = hasOuter ? nuStubInnerObject(c) : nuEmptyObject(c);
else {
if (concepts.contains(t) && (c = findClass("Concept")) != null)
o = dO = (DynamicObject) nuEmptyObject(c);
else
dO = new DynamicObject();
dO.className = t;
if (debug) print("Made dynamic object " + t + " " + shortClassName(dO));
}
// Save in references list early because contents of object
// might link back to main object
if (refID != 0)
refs.put(refID, o != null ? o : dO);
tokrefs.put(tokIndex, o != null ? o : dO);
// NOW parse the fields!
Map fields = new TreeMap();
if (i < tok.size() && tok.get(i).equals("(")) {
consume("(");
while (!tok.get(i).equals(")")) {
String key = unquote(tok.get(i));
i++;
consume("=");
Object value = parse();
fields.put(key, value);
if (tok.get(i).equals(",")) i++;
}
consume(")");
}
if (o != null)
if (dO != null) {
if (debug)
printStructure("setOptAllDyn", fields);
setOptAllDyn(dO, fields);
} else
setOptAll(o, fields);
else for (String field : keys(fields))
dO.fieldValues.put(field.intern(), fields.get(field));
if (o != null)
pcallOpt_noArgs(o, "_doneLoading");
return o != null ? o : dO;
}
Object parseSet(Set set) {
set.addAll((List) parseList());
return set;
}
Object parseLisp() {
consume("l");
consume("(");
ArrayList list = new ArrayList();
while (!tok.get(i).equals(")")) {
list.add(parse());
if (tok.get(i).equals(",")) i++;
}
consume(")");
return newObject("main$Lisp", (String) list.get(0), subList(list, 1));
}
Object parseBitSet() {
consume("bitset");
consume("{");
BitSet bs = new BitSet();
while (!tok.get(i).equals("}")) {
bs.set((Integer) parse());
if (tok.get(i).equals(",")) i++;
}
consume("}");
return bs;
}
Object parseList() {
consume("[");
ArrayList list = new ArrayList();
while (!tok.get(i).equals("]")) {
Object o = parse();
//if (debug) print("List element type: " + getClassName(o));
list.add(o);
if (tok.get(i).equals(",")) i++;
}
consume("]");
return list;
}
Object parseArray() {
String type = tok.get(i);
i++;
consume("{");
List list = new ArrayList();
while (!tok.get(i).equals("}")) {
list.add(parse());
if (tok.get(i).equals(",")) i++;
}
consume("}");
if (type.equals("intarray"))
return toIntArray(list);
return list.toArray();
}
Object parseClass() {
consume("class");
consume("(");
String name = tok.get(i);
i++;
consume(")");
Class c = allDynamic ? null : findClass(name);
if (c != null) return c;
DynamicObject dO = new DynamicObject();
dO.className = "java.lang.Class";
dO.fieldValues.put("name", name);
return dO;
}
Object parseBigInt() {
consume("bigint");
consume("(");
String val = tok.get(i);
i++;
if (eq(val, "-")) {
val = "-" + tok.get(i);
i++;
}
consume(")");
return new BigInteger(val);
}
Object parseDouble() {
consume("d");
consume("(");
String val = unquote(tok.get(i));
i++;
consume(")");
return Double.parseDouble(val);
}
Object parseFloat() {
consume("fl");
String val;
if (eq(tok.get(i), "(")) {
consume("(");
val = unquote(tok.get(i));
i++;
consume(")");
} else {
val = unquote(tok.get(i));
i++;
}
return Float.parseFloat(val);
}
Object parseHashMap() {
i++;
return parseMap(new HashMap());
}
Object parseHashSet() {
consume("hashset");
return parseSet(new HashSet());
}
Object parseTreeSet() {
consume("treeset");
return parseSet(new TreeSet());
}
Object parseMap() {
return parseMap(new TreeMap());
}
Object parseMap(Map map) {
consume("{");
while (!tok.get(i).equals("}")) {
Object key = parse();
consume("=");
Object value = parse();
map.put(key, value);
if (tok.get(i).equals(",")) i++;
}
consume("}");
return map;
}
void consume(String s) {
if (!tok.get(i).equals(s)) {
String prevToken = i-1 >= 0 ? tok.get(i-1) : "";
String nextTokens = join(tok.subList(i, Math.min(i+2, tok.size())));
throw fail(quote(s) + " expected: " + prevToken + " " + nextTokens + " (" + i + "/" + tok.size() + ")");
}
i++;
}
}
return new X().parse();
}
static boolean unstructure_debug;
static int l(Object[] a) { return a == null ? 0 : a.length; }
static int l(boolean[] a) { return a == null ? 0 : a.length; }
static int l(byte[] a) { return a == null ? 0 : a.length; }
static int l(int[] a) { return a == null ? 0 : a.length; }
static int l(float[] a) { return a == null ? 0 : a.length; }
static int l(char[] a) { return a == null ? 0 : a.length; }
static int l(Collection c) { return c == null ? 0 : c.size(); }
static int l(Map m) { return m == null ? 0 : m.size(); }
static int l(CharSequence s) { return s == null ? 0 : s.length(); }
static int l(Object o) {
return l((List) o); // incomplete
}
static boolean structure_showTiming, structure_checkTokenCount;
static String structure(Object o) {
structure_Data d = new structure_Data();
structure_1(o, d);
long time = now();
String s = str(d.out);
if (structure_checkTokenCount) {
print("token count=" + d.n);
assertEquals("token count", l(javaTokC(s)), d.n);
}
/*int nOrig = l(s);
d.out = null;
s = structure_2(s, d.refd);
if (structure_showTiming)
done_always("structure_2 (" + nOrig + " => " + l(s) + ")", time);*/
return s;
}
// leave to false, unless unstructure() breaks
static boolean structure_allowShortening = false;
static int structure_shareStringsLongerThan = 20;
static class structure_Data {
StringBuilder out = new StringBuilder();
int stringSizeLimit;
IdentityHashMap