+ // 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);
+ encodedValue.end();
+ }
+ }
+
+ String encodedString = IOUtils.readSmallStream(encodedValue);
+ return decode(encodedString);
+ }
+
+ /**
+ * Decode the data into an equivalent supported source object.
+ * <p>
+ * A supported object in this context means an object we can directly
+ * encode, like an Integer or a String.
+ * <p>
+ * For custom objects and arrays, you should use
+ * {@link SerialUtils#decode(InputStream)} or directly {@link Importer}.
+ * <p>
+ * 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(String encodedValue) throws IOException {
+ try {
+ String cut = "";
+ if (encodedValue.length() > 1) {
+ cut = encodedValue.substring(1);
+ }
+
+ if (encodedValue.equals("NULL") || encodedValue.equals("null")) {
+ return null;
+ } else if (encodedValue.startsWith("\"")) {
+ return decodeString(encodedValue);
+ } else if (encodedValue.equals("true")) {
+ return true;
+ } else if (encodedValue.equals("false")) {
+ return false;
+ } else if (encodedValue.startsWith("b")) {
+ return Byte.parseByte(cut);
+ } else if (encodedValue.startsWith("c")) {
+ return decodeString(cut).charAt(0);
+ } else if (encodedValue.startsWith("s")) {
+ return Short.parseShort(cut);
+ } else if (encodedValue.startsWith("l")) {
+ return Long.parseLong(cut);
+ } else if (encodedValue.startsWith("f")) {
+ return Float.parseFloat(cut);
+ } else if (encodedValue.startsWith("d")) {
+ return Double.parseDouble(cut);
+ } else if (encodedValue.startsWith("i")) {
+ return Integer.parseInt(cut);
+ } else if (encodedValue.startsWith("E:")) {
+ cut = cut.substring(1);
+ return decodeEnum(cut);