blob: ba62a1361585f334eeab216b7e4677203d657949 [file] [log] [blame]
Stuart McCullochbb014372012-06-07 21:57:32 +00001package aQute.lib.json;
2
3import java.io.*;
4import java.lang.reflect.*;
5import java.util.*;
6
7public class StringHandler extends Handler {
8
Stuart McCulloch2286f232012-06-15 13:27:53 +00009 @Override
10 void encode(Encoder app, Object object, Map<Object,Type> visited) throws IOException {
Stuart McCullochbb014372012-06-07 21:57:32 +000011 string(app, object.toString());
12 }
13
14 static void string(Appendable app, String s) throws IOException {
15
16 app.append('"');
17 for (int i = 0; i < s.length(); i++) {
18 char c = s.charAt(i);
19 switch (c) {
Stuart McCulloch2286f232012-06-15 13:27:53 +000020 case '"' :
21 app.append("\\\"");
22 break;
Stuart McCullochbb014372012-06-07 21:57:32 +000023
Stuart McCulloch2286f232012-06-15 13:27:53 +000024 case '\\' :
25 app.append("\\\\");
26 break;
Stuart McCullochbb014372012-06-07 21:57:32 +000027
Stuart McCulloch2286f232012-06-15 13:27:53 +000028 case '\b' :
29 app.append("\\b");
30 break;
Stuart McCullochbb014372012-06-07 21:57:32 +000031
Stuart McCulloch2286f232012-06-15 13:27:53 +000032 case '\f' :
33 app.append("\\f");
34 break;
Stuart McCullochbb014372012-06-07 21:57:32 +000035
Stuart McCulloch2286f232012-06-15 13:27:53 +000036 case '\n' :
37 app.append("\\n");
38 break;
Stuart McCullochbb014372012-06-07 21:57:32 +000039
Stuart McCulloch2286f232012-06-15 13:27:53 +000040 case '\r' :
41 app.append("\\r");
42 break;
Stuart McCullochbb014372012-06-07 21:57:32 +000043
Stuart McCulloch2286f232012-06-15 13:27:53 +000044 case '\t' :
45 app.append("\\t");
46 break;
Stuart McCullochbb014372012-06-07 21:57:32 +000047
Stuart McCulloch2286f232012-06-15 13:27:53 +000048 default :
49 if (Character.isISOControl(c)) {
50 app.append("\\u");
51 app.append("0123456789ABCDEF".charAt(0xF & (c >> 12)));
52 app.append("0123456789ABCDEF".charAt(0xF & (c >> 8)));
53 app.append("0123456789ABCDEF".charAt(0xF & (c >> 4)));
54 app.append("0123456789ABCDEF".charAt(0xF & (c >> 0)));
55 } else
56 app.append(c);
Stuart McCullochbb014372012-06-07 21:57:32 +000057 }
58 }
59 app.append('"');
60 }
61
Stuart McCullocha21b9e82012-08-02 13:26:25 +000062 @Override
63 Object decode(Decoder dec, String s) throws Exception {
Stuart McCullochbb014372012-06-07 21:57:32 +000064 return s;
65 }
66
Stuart McCullocha21b9e82012-08-02 13:26:25 +000067 @Override
68 Object decode(Decoder dec, Number s) {
Stuart McCullochbb014372012-06-07 21:57:32 +000069 return s.toString();
70 }
71
Stuart McCullocha21b9e82012-08-02 13:26:25 +000072 @Override
73 Object decode(Decoder dec, boolean s) {
Stuart McCullochbb014372012-06-07 21:57:32 +000074 return Boolean.toString(s);
75 }
76
Stuart McCullocha21b9e82012-08-02 13:26:25 +000077 @Override
78 Object decode(Decoder dec ) {
Stuart McCullochbb014372012-06-07 21:57:32 +000079 return null;
80 }
81
82 /**
83 * An object can be assigned to a string. This means that the stream is
84 * interpreted as the object but stored in its complete in the string.
85 */
86 Object decodeObject(Decoder r) throws Exception {
87 return collect(r, '}');
88 }
89
90 /**
91 * An array can be assigned to a string. This means that the stream is
92 * interpreted as the array but stored in its complete in the string.
93 */
Stuart McCullocha21b9e82012-08-02 13:26:25 +000094 @Override
Stuart McCullochbb014372012-06-07 21:57:32 +000095 Object decodeArray(Decoder r) throws Exception {
96 return collect(r, ']');
97 }
98
99 /**
100 * Gather the input until you find the the closing character making sure
101 * that new blocks are are take care of.
102 * <p>
103 * This method parses the input for a complete block so that it can be
104 * stored in a string. This allows envelopes.
105 *
106 * @param isr
107 * @param c
108 * @return
109 * @throws Exception
110 */
Stuart McCullochd4826102012-06-26 16:34:24 +0000111 private Object collect(Decoder isr, @SuppressWarnings("unused") char close) throws Exception {
Stuart McCullochbb014372012-06-07 21:57:32 +0000112 boolean instring = false;
113 int level = 1;
114 StringBuilder sb = new StringBuilder();
115
116 int c = isr.current();
117 while (c > 0 && level > 0) {
118 sb.append((char) c);
119 if (instring)
120 switch (c) {
Stuart McCulloch2286f232012-06-15 13:27:53 +0000121 case '"' :
122 instring = true;
123 break;
Stuart McCullochbb014372012-06-07 21:57:32 +0000124
Stuart McCulloch2286f232012-06-15 13:27:53 +0000125 case '[' :
126 case '{' :
127 level++;
128 break;
Stuart McCullochbb014372012-06-07 21:57:32 +0000129
Stuart McCulloch2286f232012-06-15 13:27:53 +0000130 case ']' :
131 case '}' :
132 level--;
133 break;
Stuart McCullochbb014372012-06-07 21:57:32 +0000134 }
135 else
136 switch (c) {
Stuart McCulloch2286f232012-06-15 13:27:53 +0000137 case '"' :
138 instring = false;
139 break;
Stuart McCullochbb014372012-06-07 21:57:32 +0000140
Stuart McCulloch2286f232012-06-15 13:27:53 +0000141 case '\\' :
142 sb.append((char) isr.read());
143 break;
Stuart McCullochbb014372012-06-07 21:57:32 +0000144 }
145
146 c = isr.read();
147 }
148 return sb.toString();
149 }
150
151}