X-Git-Url: http://git.nikiroo.be/?a=blobdiff_plain;f=src%2Fbe%2Fnikiroo%2Futils%2Fserial%2FSerialUtils.java;fp=src%2Fbe%2Fnikiroo%2Futils%2Fserial%2FSerialUtils.java;h=43aafb2f47d3ecf3edff03f5b4b2347618019b85;hb=d2219aa05bbcc5603e90aa69220fecb4a6a41f55;hp=6f851731fd034541b912d71046b0375e8ee7422b;hpb=d251f3dd38a8f9d369a7cf627185eacc4f66ece5;p=nikiroo-utils.git diff --git a/src/be/nikiroo/utils/serial/SerialUtils.java b/src/be/nikiroo/utils/serial/SerialUtils.java index 6f85173..43aafb2 100644 --- a/src/be/nikiroo/utils/serial/SerialUtils.java +++ b/src/be/nikiroo/utils/serial/SerialUtils.java @@ -1,6 +1,5 @@ package be.nikiroo.utils.serial; -import java.io.ByteArrayInputStream; import java.io.IOException; import java.io.InputStream; import java.io.NotSerializableException; @@ -21,6 +20,7 @@ import be.nikiroo.utils.Image; import be.nikiroo.utils.StringUtils; import be.nikiroo.utils.streams.Base64InputStream; import be.nikiroo.utils.streams.Base64OutputStream; +import be.nikiroo.utils.streams.BufferedInputStream; import be.nikiroo.utils.streams.NextableInputStream; import be.nikiroo.utils.streams.NextableInputStreamStep; @@ -359,7 +359,7 @@ public class SerialUtils { continue; } - write(out, "\n"); + write(out, "\n^"); write(out, field.getName()); write(out, ":"); @@ -418,26 +418,28 @@ public class SerialUtils { } else if (value instanceof Boolean) { write(out, value); } else if (value instanceof Byte) { - write(out, value); write(out, "b"); + write(out, value); } else if (value instanceof Character) { - encodeString(out, "" + value); write(out, "c"); + encodeString(out, "" + value); } else if (value instanceof Short) { - write(out, value); write(out, "s"); + write(out, value); } else if (value instanceof Integer) { + write(out, "i"); write(out, value); } else if (value instanceof Long) { + write(out, "l"); write(out, value); - write(out, "L"); } else if (value instanceof Float) { + write(out, "f"); write(out, value); - write(out, "F"); } else if (value instanceof Double) { - write(out, value); write(out, "d"); + write(out, value); } else if (value instanceof Enum) { + write(out, "E:"); String type = value.getClass().getCanonicalName(); write(out, type); write(out, "."); @@ -450,12 +452,85 @@ public class SerialUtils { return true; } + static boolean isDirectValue(BufferedInputStream encodedValue) + throws IOException { + if (CustomSerializer.isCustom(encodedValue)) { + return false; + } + + for (String fullValue : new String[] { "NULL", "null", "true", "false" }) { + if (encodedValue.is(fullValue)) { + return true; + } + } + + // TODO: Not efficient + for (String prefix : new String[] { "c\"", "\"", "b", "s", "i", "l", + "f", "d", "E:" }) { + if (encodedValue.startsWith(prefix)) { + return true; + } + } + + return false; + } + /** * Decode the data into an equivalent supported source object. *

* A supported object in this context means an object we can directly - * encode, like an Integer or a String. Custom objects and arrays are also - * considered supported, but compound objects are not supported here. + * encode, like an Integer or a String (see + * {@link SerialUtils#decode(String)}. + *

+ * Custom objects and arrays are also considered supported here, but + * compound objects are not. + *

+ * For compound objects, you should use {@link Importer}. + * + * @param encodedValue + * the encoded data, cannot be NULL + * + * @return the object (can be NULL for NULL encoded values) + * + * @throws IOException + * if the content cannot be converted + */ + static Object decode(BufferedInputStream encodedValue) throws IOException { + if (CustomSerializer.isCustom(encodedValue)) { + // custom^TYPE^ENCODED_VALUE + NextableInputStream content = new NextableInputStream(encodedValue, + new NextableInputStreamStep('^')); + try { + content.next(); + @SuppressWarnings("unused") + String custom = IOUtils.readSmallStream(content); + content.next(); + String type = IOUtils.readSmallStream(content); + content.nextAll(); + if (customTypes.containsKey(type)) { + return customTypes.get(type).decode(content); + } + content.end(); + throw new IOException("Unknown custom type: " + type); + } finally { + content.close(false); + // TODO: check what happens with thrown Exception in finally + encodedValue.end(); + } + } + + String encodedString = IOUtils.readSmallStream(encodedValue); + return decode(encodedString); + } + + /** + * Decode the data into an equivalent supported source object. + *

+ * A supported object in this context means an object we can directly + * encode, like an Integer or a String. + *

+ * For custom objects and arrays, you should use + * {@link SerialUtils#decode(InputStream)} or directly {@link Importer}. *

* For compound objects, you should use {@link Importer}. * @@ -471,48 +546,36 @@ public class SerialUtils { try { String cut = ""; if (encodedValue.length() > 1) { - cut = encodedValue.substring(0, encodedValue.length() - 1); + cut = encodedValue.substring(1); } - if (CustomSerializer.isCustom(encodedValue)) { - // custom:TYPE_NAME:"content is String-encoded" - String type = CustomSerializer.typeOf(encodedValue); - if (customTypes.containsKey(type)) { - // TODO: we should start with a stream - InputStream streamEncodedValue = new ByteArrayInputStream( - StringUtils.getBytes(encodedValue)); - try { - return customTypes.get(type).decode(streamEncodedValue); - } finally { - streamEncodedValue.close(); - } - } - throw new IOException("Unknown custom type: " + type); - } else if (encodedValue.equals("NULL") - || encodedValue.equals("null")) { + if (encodedValue.equals("NULL") || encodedValue.equals("null")) { return null; - } else if (encodedValue.endsWith("\"")) { + } else if (encodedValue.startsWith("\"")) { return decodeString(encodedValue); } else if (encodedValue.equals("true")) { return true; } else if (encodedValue.equals("false")) { return false; - } else if (encodedValue.endsWith("b")) { + } else if (encodedValue.startsWith("b")) { return Byte.parseByte(cut); - } else if (encodedValue.endsWith("c")) { + } else if (encodedValue.startsWith("c")) { return decodeString(cut).charAt(0); - } else if (encodedValue.endsWith("s")) { + } else if (encodedValue.startsWith("s")) { return Short.parseShort(cut); - } else if (encodedValue.endsWith("L")) { + } else if (encodedValue.startsWith("l")) { return Long.parseLong(cut); - } else if (encodedValue.endsWith("F")) { + } else if (encodedValue.startsWith("f")) { return Float.parseFloat(cut); - } else if (encodedValue.endsWith("d")) { + } else if (encodedValue.startsWith("d")) { return Double.parseDouble(cut); - } else if (encodedValue.endsWith(";")) { - return decodeEnum(encodedValue); + } else if (encodedValue.startsWith("i")) { + return Integer.parseInt(cut); + } else if (encodedValue.startsWith("E:")) { + cut = cut.substring(1); + return decodeEnum(cut); } else { - return Integer.parseInt(encodedValue); + throw new IOException("Unrecognized value: " + encodedValue); } } catch (Exception e) { if (e instanceof IOException) {