mirror of
https://github.com/Eaglercraft-TeaVM-Fork/eagler-teavm.git
synced 2025-01-08 07:54:11 -08:00
Continues implementation of metadata providers
This commit is contained in:
parent
c23f62ced7
commit
10a8e0261a
|
@ -31,10 +31,13 @@ public class SourceWriter implements Appendable {
|
|||
private NamingStrategy naming;
|
||||
private boolean lineStart;
|
||||
private boolean minified;
|
||||
private int lineWidth;
|
||||
private int pos;
|
||||
|
||||
SourceWriter(NamingStrategy naming, Appendable innerWriter) {
|
||||
SourceWriter(NamingStrategy naming, Appendable innerWriter, int lineWidth) {
|
||||
this.naming = naming;
|
||||
this.innerWriter = innerWriter;
|
||||
this.lineWidth = lineWidth;
|
||||
}
|
||||
|
||||
void setMinified(boolean minified) {
|
||||
|
@ -42,8 +45,7 @@ public class SourceWriter implements Appendable {
|
|||
}
|
||||
|
||||
public SourceWriter append(String value) throws IOException {
|
||||
appendIndent();
|
||||
innerWriter.append(value);
|
||||
append((CharSequence)value);
|
||||
return this;
|
||||
}
|
||||
|
||||
|
@ -59,23 +61,43 @@ public class SourceWriter implements Appendable {
|
|||
public SourceWriter append(char value) throws IOException {
|
||||
appendIndent();
|
||||
innerWriter.append(value);
|
||||
if (value == '\n') {
|
||||
newLine();
|
||||
} else {
|
||||
pos++;
|
||||
}
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public SourceWriter append(CharSequence csq) throws IOException {
|
||||
appendIndent();
|
||||
innerWriter.append(csq);
|
||||
append(csq, 0, csq.length());
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public SourceWriter append(CharSequence csq, int start, int end) throws IOException {
|
||||
appendIndent();
|
||||
innerWriter.append(csq, start, end);
|
||||
int last = start;
|
||||
for (int i = start; i < end; ++i) {
|
||||
if (csq.charAt(i) == '\n') {
|
||||
appendSingleLine(csq, last, i);
|
||||
newLine();
|
||||
last = i;
|
||||
}
|
||||
}
|
||||
appendSingleLine(csq, last, end);
|
||||
return this;
|
||||
}
|
||||
|
||||
private void appendSingleLine(CharSequence csq, int start, int end) throws IOException {
|
||||
if (start == end) {
|
||||
return;
|
||||
}
|
||||
appendIndent();
|
||||
pos += end - start;
|
||||
innerWriter.append(csq, start, end);
|
||||
}
|
||||
|
||||
public SourceWriter appendClass(String cls) throws NamingException, IOException {
|
||||
return append(naming.getNameFor(cls));
|
||||
}
|
||||
|
@ -109,6 +131,7 @@ public class SourceWriter implements Appendable {
|
|||
if (lineStart) {
|
||||
for (int i = 0; i < indentSize; ++i) {
|
||||
innerWriter.append(" ");
|
||||
pos += 4;
|
||||
}
|
||||
lineStart = false;
|
||||
}
|
||||
|
@ -116,13 +139,26 @@ public class SourceWriter implements Appendable {
|
|||
|
||||
public SourceWriter newLine() throws IOException{
|
||||
innerWriter.append('\n');
|
||||
pos = 0;
|
||||
lineStart = true;
|
||||
return this;
|
||||
}
|
||||
|
||||
public SourceWriter ws() throws IOException{
|
||||
if (!minified) {
|
||||
innerWriter.append(' ');
|
||||
public SourceWriter ws() throws IOException {
|
||||
if (pos >= lineWidth) {
|
||||
newLine();
|
||||
} else {
|
||||
if (!minified) {
|
||||
innerWriter.append(' ');
|
||||
pos++;
|
||||
}
|
||||
}
|
||||
return this;
|
||||
}
|
||||
|
||||
public SourceWriter tokenBoundary() throws IOException {
|
||||
if (pos >= lineWidth) {
|
||||
newLine();
|
||||
}
|
||||
return this;
|
||||
}
|
||||
|
@ -130,6 +166,7 @@ public class SourceWriter implements Appendable {
|
|||
public SourceWriter softNewLine() throws IOException{
|
||||
if (!minified) {
|
||||
innerWriter.append('\n');
|
||||
pos = 0;
|
||||
lineStart = true;
|
||||
}
|
||||
return this;
|
||||
|
|
|
@ -22,6 +22,7 @@ package org.teavm.codegen;
|
|||
public class SourceWriterBuilder {
|
||||
private NamingStrategy naming;
|
||||
private boolean minified;
|
||||
private int lineWidth = 512;
|
||||
|
||||
public SourceWriterBuilder(NamingStrategy naming) {
|
||||
this.naming = naming;
|
||||
|
@ -35,8 +36,12 @@ public class SourceWriterBuilder {
|
|||
this.minified = minified;
|
||||
}
|
||||
|
||||
public void setLineWidth(int lineWidth) {
|
||||
this.lineWidth = lineWidth;
|
||||
}
|
||||
|
||||
public SourceWriter build(Appendable innerWriter) {
|
||||
SourceWriter writer = new SourceWriter(naming, innerWriter);
|
||||
SourceWriter writer = new SourceWriter(naming, innerWriter, lineWidth);
|
||||
writer.setMinified(minified);
|
||||
return writer;
|
||||
}
|
||||
|
|
|
@ -43,6 +43,7 @@ public class Renderer implements ExprVisitor, StatementVisitor, RenderingContext
|
|||
private ClassLoader classLoader;
|
||||
private boolean minifying;
|
||||
private Map<MethodReference, InjectorHolder> injectorMap = new HashMap<>();
|
||||
private Properties properties = new Properties();
|
||||
|
||||
private static class InjectorHolder {
|
||||
public final Injector injector;
|
||||
|
@ -88,6 +89,16 @@ public class Renderer implements ExprVisitor, StatementVisitor, RenderingContext
|
|||
return classLoader;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Properties getProperties() {
|
||||
return new Properties(properties);
|
||||
}
|
||||
|
||||
public void setProperties(Properties properties) {
|
||||
this.properties.clear();
|
||||
this.properties.putAll(properties);
|
||||
}
|
||||
|
||||
public void renderRuntime() throws RenderingException {
|
||||
try {
|
||||
renderRuntimeCls();
|
||||
|
@ -483,6 +494,16 @@ public class Renderer implements ExprVisitor, StatementVisitor, RenderingContext
|
|||
public ListableClassReaderSource getClassSource() {
|
||||
return classSource;
|
||||
}
|
||||
|
||||
@Override
|
||||
public ClassLoader getClassLoader() {
|
||||
return classLoader;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Properties getProperties() {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
|
@ -15,6 +15,7 @@
|
|||
*/
|
||||
package org.teavm.javascript;
|
||||
|
||||
import java.util.Properties;
|
||||
import org.teavm.codegen.NamingStrategy;
|
||||
import org.teavm.codegen.SourceWriter;
|
||||
import org.teavm.model.ListableClassReaderSource;
|
||||
|
@ -33,4 +34,6 @@ public interface RenderingContext {
|
|||
ListableClassReaderSource getClassSource();
|
||||
|
||||
ClassLoader getClassLoader();
|
||||
|
||||
Properties getProperties();
|
||||
}
|
||||
|
|
|
@ -15,6 +15,7 @@
|
|||
*/
|
||||
package org.teavm.javascript.ni;
|
||||
|
||||
import java.util.Properties;
|
||||
import org.teavm.model.ListableClassReaderSource;
|
||||
|
||||
/**
|
||||
|
@ -25,4 +26,8 @@ public interface GeneratorContext {
|
|||
String getParameterName(int index);
|
||||
|
||||
ListableClassReaderSource getClassSource();
|
||||
|
||||
ClassLoader getClassLoader();
|
||||
|
||||
Properties getProperties();
|
||||
}
|
||||
|
|
|
@ -15,15 +15,17 @@
|
|||
*/
|
||||
package org.teavm.platform.plugin;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import org.teavm.codegen.SourceWriter;
|
||||
import org.teavm.platform.metadata.ResourceArray;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author Alexey Andreev
|
||||
*/
|
||||
class BuildTimeResourceArray<T> implements ResourceArray<T> {
|
||||
class BuildTimeResourceArray<T> implements ResourceArray<T>, ResourceWriter {
|
||||
private List<T> data = new ArrayList<>();
|
||||
|
||||
@Override
|
||||
|
@ -40,4 +42,16 @@ class BuildTimeResourceArray<T> implements ResourceArray<T> {
|
|||
public void add(T elem) {
|
||||
data.add(elem);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void write(SourceWriter writer) throws IOException {
|
||||
writer.append('[').tokenBoundary();
|
||||
for (int i = 0; i < data.size(); ++i) {
|
||||
if (i > 0) {
|
||||
writer.append(',').ws();
|
||||
}
|
||||
ResourceWriterHelper.write(writer, data.get(i));
|
||||
}
|
||||
writer.append(']').tokenBoundary();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -15,15 +15,17 @@
|
|||
*/
|
||||
package org.teavm.platform.plugin;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
import org.teavm.codegen.SourceWriter;
|
||||
import org.teavm.platform.metadata.ResourceMap;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author Alexey Andreev
|
||||
*/
|
||||
class BuildTimeResourceMap<T> implements ResourceMap<T> {
|
||||
class BuildTimeResourceMap<T> implements ResourceMap<T>, ResourceWriter {
|
||||
private Map<String, T> data = new HashMap<>();
|
||||
|
||||
@Override
|
||||
|
@ -40,4 +42,20 @@ class BuildTimeResourceMap<T> implements ResourceMap<T> {
|
|||
public void put(String key, T value) {
|
||||
data.put(key, value);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void write(SourceWriter writer) throws IOException {
|
||||
writer.append('{');
|
||||
boolean first = true;
|
||||
for (Map.Entry<String, T> entry : data.entrySet()) {
|
||||
if (!first) {
|
||||
writer.append(",").ws();
|
||||
}
|
||||
first = false;
|
||||
ResourceWriterHelper.writeString(writer, entry.getKey());
|
||||
writer.ws().append(':').ws();
|
||||
ResourceWriterHelper.write(writer, entry.getValue());
|
||||
}
|
||||
writer.append('}').tokenBoundary();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -31,6 +31,16 @@ class BuildTimeResourceProxyBuilder {
|
|||
boolean.class, Boolean.class, byte.class, Byte.class, short.class, Short.class,
|
||||
int.class, Integer.class, float.class, Float.class, double.class, Double.class,
|
||||
String.class, ResourceArray.class, ResourceMap.class));
|
||||
private static Map<Class<?>, Object> defaultValues = new HashMap<>();
|
||||
|
||||
static {
|
||||
defaultValues.put(boolean.class, false);
|
||||
defaultValues.put(byte.class, (byte)0);
|
||||
defaultValues.put(short.class, (short)0);
|
||||
defaultValues.put(int.class, 0);
|
||||
defaultValues.put(float.class, 0F);
|
||||
defaultValues.put(double.class, 0.0);
|
||||
}
|
||||
|
||||
public BuildTimeResourceProxy buildProxy(Class<?> iface) {
|
||||
BuildTimeResourceProxyFactory factory = factories.get(iface);
|
||||
|
@ -50,8 +60,8 @@ class BuildTimeResourceProxyBuilder {
|
|||
Map<String, Class<?>> getters = new HashMap<>();
|
||||
Map<String, Class<?>> setters = new HashMap<>();
|
||||
Map<Method, BuildTimeResourceMethod> methods = new HashMap<>();
|
||||
private List<Object> initialData = new ArrayList<>();
|
||||
private Map<String, Integer> propertyIndexes = new HashMap<>();
|
||||
private Object[] initialData;
|
||||
|
||||
public ProxyFactoryCreation(Class<?> iface) {
|
||||
this.rootIface = iface;
|
||||
|
@ -63,7 +73,7 @@ class BuildTimeResourceProxyBuilder {
|
|||
" that is not an interface");
|
||||
}
|
||||
scanIface(rootIface);
|
||||
return new BuildTimeResourceProxyFactory(methods, initialData.toArray(new Object[initialData.size()]));
|
||||
return new BuildTimeResourceProxyFactory(methods, initialData);
|
||||
}
|
||||
|
||||
private void scanIface(Class<?> iface) {
|
||||
|
@ -109,18 +119,18 @@ class BuildTimeResourceProxyBuilder {
|
|||
}
|
||||
|
||||
// Verify types of properties and fill default values
|
||||
initialData = new Object[propertyIndexes.size()];
|
||||
for (Map.Entry<String, Class<?>> property : getters.entrySet()) {
|
||||
String propertyName = property.getKey();
|
||||
Class<?> propertyType = property.getValue();
|
||||
if (allowedPropertyTypes.contains(propertyType)) {
|
||||
continue;
|
||||
}
|
||||
if (!propertyType.isInterface() || !propertyType.isAnnotationPresent(Resource.class)) {
|
||||
throw new IllegalArgumentException("Property " + iface.getName() + "." + propertyName +
|
||||
" has an illegal type " + propertyType.getName());
|
||||
if (!allowedPropertyTypes.contains(propertyType)) {
|
||||
if (!propertyType.isInterface() || !propertyType.isAnnotationPresent(Resource.class)) {
|
||||
throw new IllegalArgumentException("Property " + iface.getName() + "." + propertyName +
|
||||
" has an illegal type " + propertyType.getName());
|
||||
}
|
||||
}
|
||||
initialData[propertyIndexes.get(propertyName)] = defaultValues.get(propertyType);
|
||||
}
|
||||
// TODO: fill default values
|
||||
|
||||
// Scan superinterfaces
|
||||
for (Class<?> superIface : iface.getInterfaces()) {
|
||||
|
|
|
@ -0,0 +1,46 @@
|
|||
/*
|
||||
* Copyright 2014 Alexey Andreev.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.teavm.platform.plugin;
|
||||
|
||||
import org.teavm.codegen.SourceWriter;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author Alexey Andreev
|
||||
*/
|
||||
class BuildTimeResourceWriterMethod implements BuildTimeResourceMethod {
|
||||
private String[] propertyNames;
|
||||
|
||||
public BuildTimeResourceWriterMethod(String[] propertyNames) {
|
||||
this.propertyNames = propertyNames;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object invoke(BuildTimeResourceProxy proxy, Object[] args) throws Throwable {
|
||||
SourceWriter writer = (SourceWriter)args[0];
|
||||
writer.append('{');
|
||||
for (int i = 0; i < propertyNames.length; ++i) {
|
||||
if (i > 0) {
|
||||
writer.append(',').ws();
|
||||
}
|
||||
ResourceWriterHelper.writeString(writer, propertyNames[i]);
|
||||
writer.ws().append(':').ws();
|
||||
ResourceWriterHelper.write(writer, proxy.data[i]);
|
||||
}
|
||||
writer.append('}').tokenBoundary();
|
||||
return null;
|
||||
}
|
||||
}
|
|
@ -32,7 +32,7 @@ class DefaultMetadataGeneratorContext implements MetadataGeneratorContext {
|
|||
private Properties properties;
|
||||
private BuildTimeResourceProxyBuilder proxyBuilder = new BuildTimeResourceProxyBuilder();
|
||||
|
||||
private DefaultMetadataGeneratorContext(ListableClassReaderSource classSource, ClassLoader classLoader,
|
||||
public DefaultMetadataGeneratorContext(ListableClassReaderSource classSource, ClassLoader classLoader,
|
||||
Properties properties) {
|
||||
this.classSource = classSource;
|
||||
this.classLoader = classLoader;
|
||||
|
@ -56,7 +56,8 @@ class DefaultMetadataGeneratorContext implements MetadataGeneratorContext {
|
|||
|
||||
@Override
|
||||
public <T> T createResource(Class<T> resourceType) {
|
||||
return resourceType.cast(Proxy.newProxyInstance(classLoader, new Class<?>[] { resourceType },
|
||||
return resourceType.cast(Proxy.newProxyInstance(classLoader,
|
||||
new Class<?>[] { resourceType, ResourceWriter.class },
|
||||
proxyBuilder.buildProxy(resourceType)));
|
||||
}
|
||||
|
||||
|
|
|
@ -16,19 +16,23 @@
|
|||
package org.teavm.platform.plugin;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.lang.reflect.Constructor;
|
||||
import java.lang.reflect.InvocationTargetException;
|
||||
import org.teavm.codegen.SourceWriter;
|
||||
import org.teavm.javascript.ni.Generator;
|
||||
import org.teavm.javascript.ni.GeneratorContext;
|
||||
import org.teavm.model.*;
|
||||
import org.teavm.platform.metadata.MetadataGenerator;
|
||||
import org.teavm.platform.metadata.MetadataProvider;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author Alexey Andreev
|
||||
*/
|
||||
class MetadataProviderNativeGenerator implements Generator {
|
||||
public class MetadataProviderNativeGenerator implements Generator {
|
||||
@Override
|
||||
public void generate(GeneratorContext context, SourceWriter writer, MethodReference methodRef) throws IOException {
|
||||
// Validate method
|
||||
ClassReader cls = context.getClassSource().get(methodRef.getClassName());
|
||||
MethodReader method = cls.getMethod(methodRef.getDescriptor());
|
||||
AnnotationReader providerAnnot = method.getAnnotations().get(MetadataProvider.class.getName());
|
||||
|
@ -39,5 +43,43 @@ class MetadataProviderNativeGenerator implements Generator {
|
|||
throw new IllegalStateException("Method " + method.getReference() + " was marked with " +
|
||||
MetadataProvider.class.getName() + " but it is not native");
|
||||
}
|
||||
|
||||
// Find and instantiate metadata generator
|
||||
ValueType generatorType = providerAnnot.getValue("value").getJavaClass();
|
||||
String generatorClassName = ((ValueType.Object)generatorType).getClassName();
|
||||
Class<?> generatorClass;
|
||||
try {
|
||||
generatorClass = Class.forName(generatorClassName, true, context.getClassLoader());
|
||||
} catch (ClassNotFoundException e) {
|
||||
throw new RuntimeException("Can't find metadata generator class: " + generatorClassName, e);
|
||||
}
|
||||
Constructor<?> cons;
|
||||
try {
|
||||
cons = generatorClass.getConstructor();
|
||||
} catch (NoSuchMethodException e) {
|
||||
throw new RuntimeException("Metadata generator " + generatorClassName + " does not have a public " +
|
||||
"no-arg constructor", e);
|
||||
}
|
||||
MetadataGenerator generator;
|
||||
try {
|
||||
generator = (MetadataGenerator)cons.newInstance();
|
||||
} catch (IllegalAccessException | InstantiationException e) {
|
||||
throw new RuntimeException("Error instantiating metadata generator " + generatorClassName, e);
|
||||
} catch (InvocationTargetException e) {
|
||||
throw new RuntimeException("Error instantiating metadata generator " + generatorClassName,
|
||||
e.getTargetException());
|
||||
}
|
||||
DefaultMetadataGeneratorContext metadataContext = new DefaultMetadataGeneratorContext(context.getClassSource(),
|
||||
context.getClassLoader(), context.getProperties());
|
||||
|
||||
// Generate resource loader
|
||||
Object resource = generator.generateMetadata(metadataContext, methodRef);
|
||||
writer.append("if (!").appendMethodBody(methodRef).append("$$resource === undefined").append(") {")
|
||||
.indent().softNewLine();
|
||||
writer.appendMethodBody(methodRef).append("$$resource = ");
|
||||
ResourceWriterHelper.write(writer, resource);
|
||||
writer.append(';').softNewLine();
|
||||
writer.outdent().append('}').softNewLine();
|
||||
writer.append("return ").appendMethodBody(methodRef).append("$$resource;").softNewLine();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -0,0 +1,27 @@
|
|||
/*
|
||||
* Copyright 2014 Alexey Andreev.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.teavm.platform.plugin;
|
||||
|
||||
import java.io.IOException;
|
||||
import org.teavm.codegen.SourceWriter;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author Alexey Andreev
|
||||
*/
|
||||
interface ResourceWriter {
|
||||
void write(SourceWriter writer) throws IOException;
|
||||
}
|
|
@ -0,0 +1,74 @@
|
|||
/*
|
||||
* Copyright 2014 Alexey Andreev.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.teavm.platform.plugin;
|
||||
|
||||
import java.io.IOException;
|
||||
import org.teavm.codegen.SourceWriter;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author Alexey Andreev
|
||||
*/
|
||||
final class ResourceWriterHelper {
|
||||
public static void write(SourceWriter writer, Object resource) throws IOException {
|
||||
if (resource == null) {
|
||||
writer.append("null");
|
||||
} else {
|
||||
if (resource instanceof ResourceWriter) {
|
||||
((ResourceWriter)resource).write(writer);
|
||||
} else if (resource instanceof Number) {
|
||||
writer.append(resource);
|
||||
} else if (resource instanceof Boolean) {
|
||||
writer.append(resource == Boolean.TRUE ? "true" : "false");
|
||||
} else if (resource instanceof String) {
|
||||
writeString(writer, (String)resource);
|
||||
} else {
|
||||
throw new RuntimeException("Error compiling resources. Value of illegal type found: " +
|
||||
resource.getClass());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public static void writeString(SourceWriter writer, String s) throws IOException {
|
||||
writer.append('"');
|
||||
for (int i = 0; i < s.length(); ++i) {
|
||||
char c = s.charAt(i);
|
||||
switch (c) {
|
||||
case '\0':
|
||||
writer.append("\\0");
|
||||
break;
|
||||
case '\n':
|
||||
writer.append("\\n");
|
||||
break;
|
||||
case '\r':
|
||||
writer.append("\\r");
|
||||
break;
|
||||
case '\t':
|
||||
writer.append("\\t");
|
||||
break;
|
||||
default:
|
||||
if (c < 32) {
|
||||
writer.append("\\u00").append(Character.forDigit(c / 16, 16))
|
||||
.append(Character.forDigit(c % 16, 16));
|
||||
} else {
|
||||
writer.append(c);
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
writer.append('"');
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue
Block a user