blob: 09718261ff3f425a767d3c4ab5e9e08715e697f4 [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
62 Object decode(String s) throws Exception {
63 return s;
64 }
65
66 Object decode(Number s) {
67 return s.toString();
68 }
69
70 Object decode(boolean s) {
71 return Boolean.toString(s);
72 }
73
74 Object decode() {
75 return null;
76 }
77
78 /**
79 * An object can be assigned to a string. This means that the stream is
80 * interpreted as the object but stored in its complete in the string.
81 */
82 Object decodeObject(Decoder r) throws Exception {
83 return collect(r, '}');
84 }
85
86 /**
87 * An array can be assigned to a string. This means that the stream is
88 * interpreted as the array but stored in its complete in the string.
89 */
90 Object decodeArray(Decoder r) throws Exception {
91 return collect(r, ']');
92 }
93
94 /**
95 * Gather the input until you find the the closing character making sure
96 * that new blocks are are take care of.
97 * <p>
98 * This method parses the input for a complete block so that it can be
99 * stored in a string. This allows envelopes.
100 *
101 * @param isr
102 * @param c
103 * @return
104 * @throws Exception
105 */
Stuart McCullochd4826102012-06-26 16:34:24 +0000106 private Object collect(Decoder isr, @SuppressWarnings("unused") char close) throws Exception {
Stuart McCullochbb014372012-06-07 21:57:32 +0000107 boolean instring = false;
108 int level = 1;
109 StringBuilder sb = new StringBuilder();
110
111 int c = isr.current();
112 while (c > 0 && level > 0) {
113 sb.append((char) c);
114 if (instring)
115 switch (c) {
Stuart McCulloch2286f232012-06-15 13:27:53 +0000116 case '"' :
117 instring = true;
118 break;
Stuart McCullochbb014372012-06-07 21:57:32 +0000119
Stuart McCulloch2286f232012-06-15 13:27:53 +0000120 case '[' :
121 case '{' :
122 level++;
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 }
130 else
131 switch (c) {
Stuart McCulloch2286f232012-06-15 13:27:53 +0000132 case '"' :
133 instring = false;
134 break;
Stuart McCullochbb014372012-06-07 21:57:32 +0000135
Stuart McCulloch2286f232012-06-15 13:27:53 +0000136 case '\\' :
137 sb.append((char) isr.read());
138 break;
Stuart McCullochbb014372012-06-07 21:57:32 +0000139 }
140
141 c = isr.read();
142 }
143 return sb.toString();
144 }
145
146}