Files
react-native/ReactAndroid/src/main/java/com/facebook/react/bridge/JsonWriter.java
T
Emily Janzer 06bf7b1f00 Adding @CountEnum to simple enums in xplat/js
Summary: Using The Count to transform enums to ints in production builds: https://our.intern.facebook.com/intern/wiki/Android-java-transforms/the-count/

Reviewed By: achen1

Differential Revision: D9614432

fbshipit-source-id: 1b1a197ad8f4962712d6006ab07b3beb3eaf2432
2018-09-04 18:18:05 -07:00

220 lines
4.7 KiB
Java

/**
* Copyright (c) 2015-present, Facebook, Inc.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*/
package com.facebook.react.bridge;
import java.io.Closeable;
import java.io.IOException;
import java.io.Writer;
import java.util.ArrayDeque;
import java.util.Deque;
import com.facebook.thecount.api.CountEnum;
/**
* Simple Json generator that does no validation.
*/
public class JsonWriter implements Closeable {
private final Writer mWriter;
private final Deque<Scope> mScopes;
public JsonWriter(Writer writer) {
mWriter = writer;
mScopes = new ArrayDeque<>();
}
public JsonWriter beginArray() throws IOException {
open(Scope.EMPTY_ARRAY, '[');
return this;
}
public JsonWriter endArray() throws IOException {
close(']');
return this;
}
public JsonWriter beginObject() throws IOException {
open(Scope.EMPTY_OBJECT, '{');
return this;
}
public JsonWriter endObject() throws IOException {
close('}');
return this;
}
public JsonWriter name(String name) throws IOException {
if (name == null) {
throw new NullPointerException("name can not be null");
}
beforeName();
string(name);
mWriter.write(':');
return this;
}
public JsonWriter value(String value) throws IOException {
if (value == null) {
return nullValue();
}
beforeValue();
string(value);
return this;
}
public JsonWriter nullValue() throws IOException {
beforeValue();
mWriter.write("null");
return this;
}
public JsonWriter rawValue(String json) throws IOException {
beforeValue();
mWriter.write(json);
return this;
}
public JsonWriter value(boolean value) throws IOException {
beforeValue();
mWriter.write(value ? "true" : "false");
return this;
}
public JsonWriter value(double value) throws IOException {
beforeValue();
mWriter.append(Double.toString(value));
return this;
}
public JsonWriter value(long value) throws IOException {
beforeValue();
mWriter.write(Long.toString(value));
return this;
}
public JsonWriter value(Number value) throws IOException {
if (value == null) {
return nullValue();
}
beforeValue();
mWriter.append(value.toString());
return this;
}
@Override
public void close() throws IOException {
mWriter.close();
}
private void beforeValue() throws IOException {
Scope scope = mScopes.peek();
switch (scope) {
case EMPTY_ARRAY:
replace(Scope.ARRAY);
break;
case EMPTY_OBJECT:
throw new IllegalArgumentException(Scope.EMPTY_OBJECT.name());
case ARRAY:
mWriter.write(',');
break;
case OBJECT:
break;
default:
throw new IllegalStateException("Unknown scope: " + scope);
}
}
private void beforeName() throws IOException {
Scope scope = mScopes.peek();
switch (scope) {
case EMPTY_ARRAY:
case ARRAY:
throw new IllegalStateException("name not allowed in array");
case EMPTY_OBJECT:
replace(Scope.OBJECT);
break;
case OBJECT:
mWriter.write(',');
break;
default:
throw new IllegalStateException("Unknown scope: " + scope);
}
}
private void open(Scope scope, char bracket) throws IOException {
mScopes.push(scope);
mWriter.write(bracket);
}
private void close(char bracket) throws IOException {
mScopes.pop();
mWriter.write(bracket);
}
private void string(String string) throws IOException {
mWriter.write('"');
for (int i = 0, length = string.length(); i < length; i++) {
char c = string.charAt(i);
switch (c) {
case '\t':
mWriter.write("\\t");
break;
case '\b':
mWriter.write("\\b");
break;
case '\n':
mWriter.write("\\n");
break;
case '\r':
mWriter.write("\\r");
break;
case '\f':
mWriter.write("\\f");
break;
case '"':
case '\\':
mWriter.write('\\');
mWriter.write(c);
break;
case '\u2028':
case '\u2029':
mWriter.write(String.format("\\u%04x", (int) c));
break;
default:
if (c <= 0x1F) {
mWriter.write(String.format("\\u%04x", (int) c));
} else {
mWriter.write(c);
}
break;
}
}
mWriter.write('"');
}
private void replace(Scope scope) {
mScopes.pop();
mScopes.push(scope);
}
@CountEnum
private enum Scope {
EMPTY_OBJECT,
OBJECT,
EMPTY_ARRAY,
ARRAY
}
}