X-Git-Url: https://git.gag.com/?p=fw%2Faltos;a=blobdiff_plain;f=altoslib%2FAltosJson.java;h=ce50b872f13c6c4bc9b68ccd9dcff4b352396171;hp=6ae7e7dc99de1278f8529bbc64d7d4553d5b8589;hb=da914cd72411af8c36af05b13c11b9093c8a378c;hpb=93de1d7ec841c55f5a1a63d34b422780a6fbe3c3 diff --git a/altoslib/AltosJson.java b/altoslib/AltosJson.java index 6ae7e7dc..ce50b872 100644 --- a/altoslib/AltosJson.java +++ b/altoslib/AltosJson.java @@ -3,7 +3,8 @@ * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; version 2 of the License. + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. * * This program is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of @@ -24,39 +25,39 @@ import java.lang.*; import java.lang.reflect.*; class JsonUtil { - StringBuffer quote(StringBuffer result, String a) { - result.append("\""); + Writer quote(Writer writer, String a) throws IOException { + writer.append("\""); for (int i = 0; i < a.length(); i++) { char c = a.charAt(i); switch (c) { case '"': case '\\': - result.append('\\').append(c); + writer.append('\\').append(c); break; case '\n': - result.append("\\n"); + writer.append("\\n"); break; default: - result.append(c); + writer.append(c); break; } } - result.append("\""); - return result; + writer.append("\""); + return writer; } - StringBuffer append(StringBuffer result, AltosJson value, int indent, boolean pretty) { + Writer append(Writer result, AltosJson value, int indent, boolean pretty) throws IOException { value.append(result, indent, pretty); return result; } - StringBuffer append(StringBuffer result, String string) { + Writer append(Writer result, String string) throws IOException { result.append(string); return result; } - StringBuffer indent(StringBuffer result, int indent) { + Writer indent(Writer result, int indent) throws IOException { result.append("\n"); for (int i = 0; i < indent; i++) result.append("\t"); @@ -79,7 +80,7 @@ class JsonUtil { class JsonHash extends JsonUtil { Hashtable hash; - void append_hash(StringBuffer result, int indent, boolean pretty) { + void append_hash(Writer result, int indent, boolean pretty) throws IOException { boolean first = true; result.append("{"); @@ -124,7 +125,7 @@ class JsonHash extends JsonUtil { class JsonArray extends JsonUtil { ArrayList array; - void append_array(StringBuffer result, int indent, boolean pretty) { + void append_array(Writer result, int indent, boolean pretty) throws IOException { boolean first = true; append(result, "["); @@ -184,6 +185,7 @@ class JsonToken { static final int _colon = 9; static final int _end = 10; static final int _error = 11; + static final int _none = 12; static String token_name(int token) { switch (token) { @@ -244,7 +246,7 @@ class JsonToken { this.sval = sval; } - JsonToken(int token, StringBuffer bval) { + JsonToken(int token, Writer bval) { this(token, bval.toString()); } } @@ -253,11 +255,11 @@ class JsonToken { * Lexer for json */ class JsonLexer extends JsonUtil { - StringReader f; - int line; - int ungot = -2; - StringBuffer pending_token; - JsonToken token; + InputStream f; + int line; + int ungot = -2; + StringBuffer pending_token; + private JsonToken token; static class keyword { String word; @@ -280,6 +282,9 @@ class JsonLexer extends JsonUtil { static keyword[] keywords = { new keyword("true", new JsonToken(JsonToken._boolean, true)), new keyword("false", new JsonToken(JsonToken._boolean, false)), + new keyword("NegInfinity", new JsonToken(JsonToken._double, Double.NEGATIVE_INFINITY)), + new keyword("Infinity", new JsonToken(JsonToken._double, Double.POSITIVE_INFINITY)), + new keyword("NaN", new JsonToken(JsonToken._double, Double.NaN)) }; static JsonToken keyword(String word) { @@ -378,7 +383,7 @@ class JsonLexer extends JsonUtil { return new JsonToken(JsonToken._long, lval); } case '"': - StringBuffer bval = new StringBuffer(); + Writer bval = new StringWriter(); for (;;) { c = ch(); if (c == '"') @@ -396,7 +401,7 @@ class JsonLexer extends JsonUtil { break; } } - bval.appendCodePoint(c); + bval.write(c); } return new JsonToken(JsonToken._string, bval); default: @@ -420,11 +425,17 @@ class JsonLexer extends JsonUtil { } void next() { - token = lex(); + token = null; + } + + JsonToken token() { + if (token == null) + token = lex(); + return token; } JsonToken expect(int e) { - JsonToken t = token; + JsonToken t = token(); if (t.token != e) throw new IllegalArgumentException(String.format("got \"%s\" while expecting \"%s\"", token.token_name(), @@ -434,7 +445,13 @@ class JsonLexer extends JsonUtil { } JsonLexer(String s) { - f = new StringReader(s); + f = new AltosStringInputStream(s); + line = 1; + token = null; + } + + JsonLexer(InputStream f) { + this.f = f; line = 1; token = null; } @@ -460,7 +477,7 @@ class JsonParse { lexer.next(); for (;;) { /* Allow for empty hashes */ - if (lexer.token.token == JsonToken._cc) { + if (lexer.token().token == JsonToken._cc) { lexer.next(); return hash; } @@ -471,7 +488,7 @@ class JsonParse { AltosJson value = value(); hash.put(key, value); - switch (lexer.token.token) { + switch (lexer.token().token) { case JsonToken._comma: lexer.next(); break; @@ -479,7 +496,7 @@ class JsonParse { lexer.next(); return hash; default: - parse_error("got %s expect \",\" or \"}\"", lexer.token.token_name()); + parse_error("got %s expect \",\" or \"}\"", lexer.token().token_name()); return null; } } @@ -492,14 +509,14 @@ class JsonParse { lexer.next(); for (int i = 0;; i++) { /* Allow for empty arrays */ - if (lexer.token.token == JsonToken._cs) { + if (lexer.token().token == JsonToken._cs) { lexer.next(); return array; } AltosJson value = value(); array.put(i, value); - switch (lexer.token.token) { + switch (lexer.token().token) { case JsonToken._comma: lexer.next(); break; @@ -507,7 +524,7 @@ class JsonParse { lexer.next(); return array; default: - parse_error("got %s expect \",\" or \"]\"", lexer.token.token_name()); + parse_error("got %s expect \",\" or \"]\"", lexer.token().token_name()); return null; } } @@ -517,29 +534,29 @@ class JsonParse { * identify the next object in the input */ AltosJson value() { - switch (lexer.token.token) { + switch (lexer.token().token) { case JsonToken._oc: return new AltosJson(hash()); case JsonToken._os: return new AltosJson(array()); case JsonToken._double: - double dval = lexer.token.dval; + double dval = lexer.token().dval; lexer.next(); return new AltosJson(dval); case JsonToken._long: - long lval = lexer.token.lval; + long lval = lexer.token().lval; lexer.next(); return new AltosJson(lval); case JsonToken._string: - String sval = lexer.token.sval; + String sval = lexer.token().sval; lexer.next(); return new AltosJson(sval); case JsonToken._boolean: - boolean bval = lexer.token.bval; + boolean bval = lexer.token().bval; lexer.next(); return new AltosJson(bval); default: - parse_error("Unexpected token \"%s\"", lexer.token.token_name()); + parse_error("Unexpected token \"%s\"", lexer.token().token_name()); } return null; } @@ -552,6 +569,10 @@ class JsonParse { JsonParse(String s) { lexer = new JsonLexer(s); } + + JsonParse(InputStream f) { + lexer = new JsonLexer(f); + } } public class AltosJson extends JsonUtil { @@ -574,7 +595,7 @@ public class AltosJson extends JsonUtil { /* Generate string representation of the value */ - StringBuffer append(StringBuffer result, int indent, boolean pretty) { + Writer append(Writer result, int indent, boolean pretty) throws IOException { switch (type) { case type_hash: hash.append_hash(result, indent, pretty); @@ -583,10 +604,19 @@ public class AltosJson extends JsonUtil { array.append_array(result, indent, pretty); break; case type_double: - String dval = nf_json.format(d_number); - if (dval.equals("-0")) - dval = "0"; - result.append(dval); + if (Double.isInfinite(d_number)) { + if (d_number < 0) + result.append("NegInfinity"); + else + result.append("Infinity"); + } else if (Double.isNaN(d_number)) { + result.append("NaN"); + } else { + String dval = nf_json.format(d_number); + if (dval.equals("-0")) + dval = "0"; + result.append(dval); + } break; case type_long: result.append(new Long(l_number).toString()); @@ -602,9 +632,13 @@ public class AltosJson extends JsonUtil { } private String toString(int indent, boolean pretty) { - StringBuffer result = new StringBuffer(); - append(result, indent, pretty); - return result.toString(); + try { + Writer result = new StringWriter(); + append(result, indent, pretty); + return result.toString(); + } catch (Exception e) { + return null; + } } public String toString() { @@ -615,6 +649,14 @@ public class AltosJson extends JsonUtil { return toString(0, true); } + public void write(Writer w, int indent, boolean pretty) throws IOException { + append(w, indent, pretty); + } + + public void write(Writer w) throws IOException { + write(w, 0, true); + } + /* Parse string representation to a value */ @@ -628,6 +670,16 @@ public class AltosJson extends JsonUtil { } } + public static AltosJson fromInputStream(InputStream f) { + JsonParse parse = new JsonParse(f); + try { + return parse.parse(); + } catch (IllegalArgumentException ie) { + System.out.printf("json:\n%s\n", ie.getMessage()); + return null; + } + } + /* Accessor functions */ private boolean assert_type(boolean setting, int type, int other_type, String error) { @@ -1000,7 +1052,32 @@ public class AltosJson extends JsonUtil { assert_array(false); Class element_class = c.getComponentType(); - if (element_class == Double.TYPE) { + if (element_class == Boolean.TYPE) { + boolean[] array = (boolean[]) Array.newInstance(element_class, size()); + for (int i = 0; i < array.length; i++) + array[i] = (Boolean) get(i).make(element_class); + ret = array; + } else if (element_class == Byte.TYPE) { + byte[] array = (byte[]) Array.newInstance(element_class, size()); + for (int i = 0; i < array.length; i++) + array[i] = (Byte) get(i).make(element_class); + ret = array; + } else if (element_class == Character.TYPE) { + char[] array = (char[]) Array.newInstance(element_class, size()); + for (int i = 0; i < array.length; i++) + array[i] = (Character) get(i).make(element_class); + ret = array; + } else if (element_class == Integer.TYPE) { + int[] array = (int[]) Array.newInstance(element_class, size()); + for (int i = 0; i < array.length; i++) + array[i] = (Integer) get(i).make(element_class); + ret = array; + } else if (element_class == Long.TYPE) { + long[] array = (long[]) Array.newInstance(element_class, size()); + for (int i = 0; i < array.length; i++) + array[i] = (Long) get(i).make(element_class); + ret = array; + } else if (element_class == Double.TYPE) { double[] array = (double[]) Array.newInstance(element_class, size()); for (int i = 0; i < array.length; i++) array[i] = (Double) get(i).make(element_class); @@ -1026,11 +1103,10 @@ public class AltosJson extends JsonUtil { } else { object = c.newInstance(); } - for (; c != null; c = c.getSuperclass()) { + for (; c != Object.class; c = c.getSuperclass()) { for (Field field : c.getDeclaredFields()) { String fieldName = field.getName(); Class fieldClass = field.getType(); - String className = fieldClass.getName(); if (Modifier.isStatic(field.getModifiers())) continue; @@ -1044,17 +1120,27 @@ public class AltosJson extends JsonUtil { field.set(object, val); } } catch (IllegalAccessException ie) { + System.out.printf("%s:%s %s\n", + c.getName(), fieldName, ie.toString()); } } } ret = object; } catch (InvocationTargetException ie) { + System.out.printf("%s: %s\n", + c.getName(), ie.toString()); ret = null; } catch (NoSuchMethodException ie) { + System.out.printf("%s: %s\n", + c.getName(), ie.toString()); ret = null; } catch (InstantiationException ie) { + System.out.printf("%s: %s\n", + c.getName(), ie.toString()); ret = null; } catch (IllegalAccessException ie) { + System.out.printf("%s: %s\n", + c.getName(), ie.toString()); ret = null; } } @@ -1162,11 +1248,13 @@ public class AltosJson extends JsonUtil { } } else { assert_hash(true); - for (Class c = object.getClass(); c != null; c = c.getSuperclass()) { + for (Class c = object.getClass(); c != Object.class; c = c.getSuperclass()) { for (Field field : c.getDeclaredFields()) { String fieldName = field.getName(); - Class fieldClass = field.getType(); - String className = fieldClass.getName(); + + /* XXX hack to allow fields to be not converted */ + if (fieldName.startsWith("__")) + continue; /* Skip static fields */ if (Modifier.isStatic(field.getModifiers())) @@ -1189,6 +1277,8 @@ public class AltosJson extends JsonUtil { put(fieldName, json); } } catch (IllegalAccessException ie) { + System.out.printf("%s:%s %s\n", + c.getName(), fieldName, ie.toString()); } } }