22
33import java .io .IOException ;
44import java .io .Writer ;
5+ import java .util .BitSet ;
56
67/*
78Copyright (c) 2006 JSON.org
@@ -50,35 +51,33 @@ of this software and associated documentation files (the "Software"), to deal
5051 * <p>
5152 * The first method called must be <code>array</code> or <code>object</code>.
5253 * There are no methods for adding commas or colons. JSONWriter adds them for
53- * you. Objects and arrays can be nested up to 200 levels deep.
54+ * you.
5455 * <p>
5556 * This can sometimes be easier than using a JSONObject to build a string.
5657 * @author JSON.org
5758 * @version 2015-12-09
5859 */
5960public class JSONWriter {
60- private static final int maxdepth = 200 ;
61-
62- /**
63- * The comma flag determines if a comma should be output before the next
64- * value.
65- */
66- private boolean comma ;
67-
6861 /**
6962 * The current mode. Values:
7063 * 'a' (array),
71- * 'd' (done),
72- * 'i' (initial),
73- * 'k' (key),
74- * 'o' (object).
64+ * 'A' (array after first element),
65+ * 'i' (initial/done),
66+ * 'k' (object: key),
67+ * 'o' (object: value),
68+ * 'K' (object: key after first element).
69+ *
70+ * The stack top is completely determined by the mode: it is empty in modes
71+ * 'i', 'd', true (object) in modes 'k', 'o', 'K', and false (array) in
72+ * modes 'a', 'A'.
7573 */
7674 protected char mode ;
7775
7876 /**
79- * The object/array stack.
77+ * The object/array stack. Stored as a BitSet, where objects are true and
78+ * arrays are false.
8079 */
81- private final char stack [] ;
80+ private final BitSet stack ;
8281
8382 /**
8483 * The stack top index. A value of 0 indicates that the stack is empty.
@@ -94,9 +93,8 @@ public class JSONWriter {
9493 * Make a fresh JSONWriter. It can be used to build one JSON text.
9594 */
9695 public JSONWriter (Writer w ) {
97- comma = false ;
9896 mode = 'i' ;
99- stack = new char [ maxdepth ] ;
97+ stack = new BitSet () ;
10098 top = 0 ;
10199 writer = w ;
102100 }
@@ -111,22 +109,35 @@ private JSONWriter append(String string) throws JSONException {
111109 if (string == null ) {
112110 throw new JSONException ("Null pointer" );
113111 }
114- if (mode == 'o' || mode == 'a' ) {
115- try {
116- if (comma && mode == 'a' ) {
117- writer .write (',' );
118- }
119- writer .write (string );
120- } catch (IOException e ) {
121- throw new JSONException (e );
122- }
123- if (mode == 'o' ) {
124- mode = 'k' ;
112+ if (mode == 'd' ) {
113+ throw new JSONException ("Value out of sequence." );
114+ }
115+ try {
116+ if (mode == 'A' || mode == 'K' ) {
117+ writer .write (',' );
118+ } else if (mode == 'o' ) {
119+ writer .write (':' );
125120 }
126- comma = true ;
127- return this ;
121+ writer .write (string );
122+ } catch (IOException e ) {
123+ throw new JSONException (e );
124+ }
125+ switch (mode ) {
126+ case 'a' :
127+ mode = 'A' ;
128+ break ;
129+ case 'k' :
130+ case 'K' :
131+ mode = 'o' ;
132+ break ;
133+ case 'o' :
134+ mode = 'K' ;
135+ break ;
136+ case 'i' :
137+ mode = 'd' ;
138+ break ;
128139 }
129- throw new JSONException ( "Value out of sequence." ) ;
140+ return this ;
130141 }
131142
132143 /**
@@ -139,10 +150,9 @@ private JSONWriter append(String string) throws JSONException {
139150 * outermost array or object).
140151 */
141152 public JSONWriter array () throws JSONException {
142- if (mode == 'i' || mode == 'o' || mode == 'a' ) {
143- push ('a' );
153+ if (mode == 'i' || mode == 'o' || mode == 'a' || mode == 'A' ) {
144154 append ("[" );
145- comma = false ;
155+ push ( false ) ;
146156 return this ;
147157 }
148158 throw new JSONException ("Misplaced array." );
@@ -155,19 +165,13 @@ public JSONWriter array() throws JSONException {
155165 * @return this
156166 * @throws JSONException If unbalanced.
157167 */
158- private JSONWriter end (char mode , char c ) throws JSONException {
159- if (this .mode != mode ) {
160- throw new JSONException (mode == 'a'
161- ? "Misplaced endArray."
162- : "Misplaced endObject." );
163- }
164- pop (mode );
168+ private JSONWriter end (char c ) throws JSONException {
169+ pop ();
165170 try {
166171 writer .write (c );
167172 } catch (IOException e ) {
168173 throw new JSONException (e );
169174 }
170- comma = true ;
171175 return this ;
172176 }
173177
@@ -178,7 +182,10 @@ private JSONWriter end(char mode, char c) throws JSONException {
178182 * @throws JSONException If incorrectly nested.
179183 */
180184 public JSONWriter endArray () throws JSONException {
181- return end ('a' , ']' );
185+ if (mode != 'a' && mode != 'A' ) {
186+ throw new JSONException ("Misplaced endArray." );
187+ }
188+ return end (']' );
182189 }
183190
184191 /**
@@ -188,7 +195,10 @@ public JSONWriter endArray() throws JSONException {
188195 * @throws JSONException If incorrectly nested.
189196 */
190197 public JSONWriter endObject () throws JSONException {
191- return end ('k' , '}' );
198+ if (mode != 'k' && mode != 'K' ) {
199+ throw new JSONException ("Misplaced endObject." );
200+ }
201+ return end ('}' );
192202 }
193203
194204 /**
@@ -200,16 +210,18 @@ public JSONWriter endObject() throws JSONException {
200210 public JSONWriter end () throws JSONException {
201211 char bracket ;
202212 switch (mode ) {
203- case 'a' :
213+ case 'a' :
214+ case 'A' :
204215 bracket = ']' ;
205216 break ;
206- case 'o' :
217+ case 'k' :
218+ case 'K' :
207219 bracket = '}' ;
208220 break ;
209221 default :
210222 throw new JSONException ("Misplaced end." );
211223 }
212- return end (mode , bracket );
224+ return end (bracket );
213225 }
214226
215227 /**
@@ -224,19 +236,8 @@ public JSONWriter key(String string) throws JSONException {
224236 if (string == null ) {
225237 throw new JSONException ("Null key." );
226238 }
227- if (mode == 'k' ) {
228- try {
229- if (comma ) {
230- writer .write (',' );
231- }
232- writer .write (JSONObject .quote (string ));
233- writer .write (':' );
234- comma = false ;
235- mode = 'o' ;
236- return this ;
237- } catch (IOException e ) {
238- throw new JSONException (e );
239- }
239+ if (mode == 'k' || mode == 'K' ) {
240+ return append (JSONObject .quote (string ));
240241 }
241242 throw new JSONException ("Misplaced key." );
242243 }
@@ -252,13 +253,9 @@ public JSONWriter key(String string) throws JSONException {
252253 * outermost array or object).
253254 */
254255 public JSONWriter object () throws JSONException {
255- if (mode == 'i' ) {
256- mode = 'o' ;
257- }
258- if (mode == 'o' || mode == 'a' ) {
256+ if (mode == 'i' || mode == 'o' || mode == 'a' || mode == 'A' ) {
259257 append ("{" );
260- push ('k' );
261- comma = false ;
258+ push (true );
262259 return this ;
263260 }
264261 throw new JSONException ("Misplaced object." );
@@ -268,33 +265,24 @@ public JSONWriter object() throws JSONException {
268265
269266 /**
270267 * Pop an array or object scope.
271- * @param c The scope to close.
272268 * @throws JSONException If nesting is wrong.
273269 */
274- private void pop (char c ) throws JSONException {
270+ private void pop () throws JSONException {
275271 if (top <= 0 ) {
276272 throw new JSONException ("Nesting error." );
277273 }
278- char m = stack [top - 1 ];
279- if (m != c ) {
280- throw new JSONException ("Nesting error." );
281- }
282- top -= 1 ;
283- mode = top == 0 ? 'd' : stack [top - 1 ];
274+ top --;
275+ mode = top == 0 ? 'd' : stack .get (top - 1 ) ? 'K' : 'A' ;
284276 }
285277
286278 /**
287279 * Push an array or object scope.
288- * @param jo The scope to open.
280+ * @param b The scope to open.
289281 * @throws JSONException If nesting is too deep.
290282 */
291- private void push (char jo ) throws JSONException {
292- if (top >= maxdepth ) {
293- throw new JSONException ("Nesting too deep." );
294- }
295- stack [top ] = jo ;
296- mode = jo ;
297- top += 1 ;
283+ private void push (boolean b ) throws JSONException {
284+ stack .set (top ++, b );
285+ mode = b ? 'k' : 'a' ;
298286 }
299287
300288
0 commit comments