Skip to content

Commit 1483bb8

Browse files
committed
Write numbers without using substring.
Another attempt to simplify how numbers are written to avoid object creation. Try to group related methods together to relate numberToString() with writeNumber(), and related.
1 parent c0e9764 commit 1483bb8

2 files changed

Lines changed: 137 additions & 66 deletions

File tree

‎JSONObject.java‎

Lines changed: 93 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -451,20 +451,7 @@ public static String doubleToString(double d) {
451451
// Shave off trailing zeros and decimal point, if possible.
452452

453453
String string = Double.toString(d);
454-
if (string.indexOf('.') > 0 && string.indexOf('e') < 0
455-
&& string.indexOf('E') < 0) {
456-
int len = string.length();
457-
while ((len > 0) && (string.charAt(len - 1) == '0')) {
458-
len--;
459-
}
460-
if ((len > 0) && (string.charAt(len - 1) == '.')) {
461-
len--;
462-
}
463-
if (len < string.length()) {
464-
string = string.substring(0, len);
465-
}
466-
}
467-
return string;
454+
return stripNumberDigits(string);
468455
}
469456

470457
/**
@@ -852,6 +839,97 @@ public static String numberToString(Number number) throws JSONException {
852839
// Shave off trailing zeros and decimal point, if possible.
853840

854841
String string = number.toString();
842+
return stripNumberDigits(string);
843+
}
844+
845+
/**
846+
* Write the given double to the given Appendable.
847+
*
848+
* @param writer
849+
* The Appendable to which the double value is written
850+
* @param d
851+
* A double
852+
* @param <T> subtype of Appendable, returned to the caller
853+
* @return the given Appendable
854+
* @throws JSONException there was a problem writing the double
855+
*/
856+
public static <T extends Appendable> T writeDouble(T writer, double d) throws JSONException {
857+
if (Double.isInfinite(d) || Double.isNaN(d)) {
858+
try {
859+
writer.append("null");
860+
return writer;
861+
} catch (IOException e) {
862+
throw new JSONException(e);
863+
}
864+
}
865+
866+
String string = Double.toString(d);
867+
writeNumberDigits(writer, string);
868+
return writer;
869+
}
870+
871+
/**
872+
* Write the given number to the given Appendable.
873+
*
874+
* @param writer
875+
* The Appendable to which the number value is written
876+
* @param number
877+
* A Number
878+
* @param <T> subtype of Appendable, returned to the caller
879+
* @return the given Appendable
880+
* @throws JSONException there was a problem writing the number
881+
*/
882+
public static <T extends Appendable> T writeNumber(T writer, Number number) throws JSONException {
883+
if (number == null) {
884+
throw new JSONException("Null pointer");
885+
}
886+
testValidity(number);
887+
888+
// Shave off trailing zeros and decimal point, if possible.
889+
890+
String string = number.toString();
891+
writeNumberDigits(writer, string);
892+
return writer;
893+
}
894+
895+
/**
896+
* Write a number value, trimming any trailing zero digits from a real number.
897+
* If all zeros appear immediately after a decimal, the decimal is omitted
898+
* as well.
899+
*
900+
* @param writer the Appendable to which the digits will be written
901+
* @param string the string of digits
902+
*/
903+
private static void writeNumberDigits(Appendable writer, String string) throws JSONException {
904+
try {
905+
if (string.indexOf('.') > 0 && string.indexOf('e') < 0
906+
&& string.indexOf('E') < 0) {
907+
int len = string.length();
908+
while ((len > 0) && (string.charAt(len - 1) == '0')) {
909+
len--;
910+
}
911+
if ((len > 0) && (string.charAt(len - 1) == '.')) {
912+
len--;
913+
}
914+
if (len < string.length()) {
915+
writer.append(string, 0, len);
916+
return;
917+
}
918+
}
919+
writer.append(string);
920+
} catch (IOException e) {
921+
throw new JSONException(e);
922+
}
923+
}
924+
925+
/**
926+
* Trim any trailing zero digits from a real number. If all zeros appear
927+
* immediately after a decimal, omit the decimal as well.
928+
*
929+
* @param string the string of digits
930+
* @return the string, with trailing digits stripped if possible
931+
*/
932+
private static String stripNumberDigits(String string) {
855933
if (string.indexOf('.') > 0 && string.indexOf('e') < 0
856934
&& string.indexOf('E') < 0) {
857935
int len = string.length();
@@ -1900,7 +1978,7 @@ static final <T extends Appendable> T writeValue(T writer, Object value,
19001978
} else if (value.getClass().isArray()) {
19011979
new JSONArray(value).write(writer, indentFactor, indent);
19021980
} else if (value instanceof Number) {
1903-
writer.append(numberToString((Number) value));
1981+
writeNumber(writer, (Number) value);
19041982
} else if (value instanceof Boolean) {
19051983
writer.append(value.toString());
19061984
} else if (value instanceof JSONString) {

‎JSONWriter.java‎

Lines changed: 44 additions & 51 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,6 @@
44

55
import java.io.Closeable;
66
import java.io.IOException;
7-
import java.util.Map;
87
import java.util.HashSet;
98
import java.util.Map.Entry;
109
import java.util.Set;
@@ -106,15 +105,10 @@ public JSONWriter(Appendable w) {
106105
}
107106

108107
/**
109-
* Append a JSON-encoded value.
110-
* @param string A string value.
111-
* @return this
112-
* @throws JSONException If the value is out of sequence.
108+
* Prepare for the next value to be written. Append a comma if required,
109+
* assert and advance the mode as needed.
113110
*/
114-
private JSONWriter append(String string) throws JSONException {
115-
if (string == null) {
116-
throw new JSONException("Null pointer");
117-
}
111+
private void prepValue() throws JSONException {
118112
try {
119113
switch (this.mode) {
120114
case 'a':
@@ -128,38 +122,7 @@ private JSONWriter append(String string) throws JSONException {
128122
default:
129123
throw new JSONException("Value out of sequence.");
130124
}
131-
this.writer.append(string);
132125
this.comma = true;
133-
return this;
134-
} catch (IOException e) {
135-
throw new JSONException(e);
136-
}
137-
}
138-
139-
/**
140-
* Append a value, converting it into a JSON string.
141-
*
142-
* @param val A value.
143-
* @return this
144-
* @throws JSONException If the value is out of sequence.
145-
*/
146-
private JSONWriter appendValue(Object val) throws JSONException {
147-
try {
148-
switch (this.mode) {
149-
case 'a':
150-
if (this.comma) {
151-
this.writer.append(',');
152-
}
153-
break;
154-
case 'o':
155-
this.mode = 'k';
156-
break;
157-
default:
158-
throw new JSONException("Value out of sequence.");
159-
}
160-
JSONObject.writeValue(this.writer, val);
161-
this.comma = true;
162-
return this;
163126
} catch (IOException e) {
164127
throw new JSONException(e);
165128
}
@@ -177,7 +140,12 @@ private JSONWriter appendValue(Object val) throws JSONException {
177140
public JSONWriter array() throws JSONException {
178141
if (this.mode == 'i' || this.mode == 'o' || this.mode == 'a') {
179142
this.push(false);
180-
this.append("[");
143+
try {
144+
this.prepValue();
145+
this.writer.append('[');
146+
} catch (IOException e) {
147+
throw new JSONException(e);
148+
}
181149
this.comma = false;
182150
return this;
183151
}
@@ -274,7 +242,12 @@ public JSONWriter object() throws JSONException {
274242
this.mode = 'o';
275243
}
276244
if (this.mode == 'o' || this.mode == 'a') {
277-
this.append("{");
245+
try {
246+
this.prepValue();
247+
this.writer.append('{');
248+
} catch (IOException e) {
249+
throw new JSONException(e);
250+
}
278251
this.push(true);
279252
this.comma = false;
280253
return this;
@@ -324,7 +297,14 @@ private void push(boolean obj) throws JSONException {
324297
* @throws JSONException
325298
*/
326299
public JSONWriter value(boolean b) throws JSONException {
327-
return this.append(Boolean.toString(b));
300+
String string = Boolean.toString(b);
301+
try {
302+
this.prepValue();
303+
this.writer.append(string);
304+
return this;
305+
} catch (IOException e) {
306+
throw new JSONException(e);
307+
}
328308
}
329309

330310
/**
@@ -334,7 +314,9 @@ public JSONWriter value(boolean b) throws JSONException {
334314
* @throws JSONException If the number is not finite.
335315
*/
336316
public JSONWriter value(double d) throws JSONException {
337-
return this.append(JSONObject.numberToString(d));
317+
this.prepValue();
318+
JSONObject.writeDouble(this.writer, d);
319+
return this;
338320
}
339321

340322
/**
@@ -344,33 +326,43 @@ public JSONWriter value(double d) throws JSONException {
344326
* @throws JSONException
345327
*/
346328
public JSONWriter value(long l) throws JSONException {
347-
return this.append(Long.toString(l));
329+
String string = Long.toString(l);
330+
try {
331+
this.prepValue();
332+
this.writer.append(string);
333+
return this;
334+
} catch (IOException e) {
335+
throw new JSONException(e);
336+
}
348337
}
349338

350339

351340
/**
352341
* Append an object value.
353-
* @param object The object to append. It can be null, or a Boolean, Number,
342+
* @param object The object to appendString. It can be null, or a Boolean, Number,
354343
* String, JSONObject, or JSONArray, or an object that implements JSONString.
355344
* @return this
356345
* @throws JSONException If the value is out of sequence.
357346
*/
358347
public JSONWriter value(Object object) throws JSONException {
359-
return this.appendValue(object);
348+
this.prepValue();
349+
JSONObject.writeValue(this.writer, object);
350+
return this;
360351
}
361352

362353
/**
363354
* Append a sequence of values into an array.
364355
*
365-
* @param values The objects to append. They can be null, or a Boolean, Number,
356+
* @param values The objects to appendString. They can be null, or a Boolean, Number,
366357
* String, JSONObject, or JSONArray, or an object that implements JSONString.
367358
* @return this
368359
* @throws JSONException If a value is out of place. For example, a value
369360
* occurs where a key is expected.
370361
*/
371362
public JSONWriter values(Iterable<?> values) throws JSONException {
372363
for(Object obj : values) {
373-
this.appendValue(obj);
364+
this.prepValue();
365+
JSONObject.writeValue(this.writer, obj);
374366
}
375367
return this;
376368
}
@@ -380,7 +372,7 @@ public JSONWriter values(Iterable<?> values) throws JSONException {
380372
* The key will be associated with the corresponding value. In an
381373
* object, every value must be associated with a key.
382374
*
383-
* @param kvPairs The objects to append. The values can be null, or a Boolean,
375+
* @param kvPairs The objects to appendString. The values can be null, or a Boolean,
384376
* Number, String, JSONObject, or JSONArray, or an object that implements
385377
* JSONString.
386378
* @return this
@@ -390,7 +382,8 @@ public JSONWriter values(Iterable<?> values) throws JSONException {
390382
public JSONWriter entries(Iterable<Entry<String, ?>> kvPairs) throws JSONException {
391383
for(Entry<String, ?> entry : kvPairs) {
392384
this.key(entry.getKey());
393-
this.appendValue(entry.getValue());
385+
this.prepValue();
386+
JSONObject.writeValue(this.writer, entry.getValue());
394387
}
395388
return this;
396389
}

0 commit comments

Comments
 (0)