/src/main/java/com/alibaba/fastjson/serializer/SerializeWriter.java
Java | 1536 lines | 1219 code | 209 blank | 108 comment | 297 complexity | c54abca9344236bc7a88dc6a17e7af63 MD5 | raw file
- /*
- * Copyright 1999-2101 Alibaba Group.
- *
- * 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 com.alibaba.fastjson.serializer;
- import static com.alibaba.fastjson.parser.CharTypes.replaceChars;
- import java.io.IOException;
- import java.io.OutputStream;
- import java.io.Writer;
- import java.lang.ref.SoftReference;
- import java.math.BigDecimal;
- import java.nio.charset.Charset;
- import com.alibaba.fastjson.JSON;
- import com.alibaba.fastjson.parser.CharTypes;
- import com.alibaba.fastjson.util.Base64;
- import com.alibaba.fastjson.util.IOUtils;
- /**
- * @author wenshao<szujobs@hotmail.com>
- */
- public final class SerializeWriter extends Writer {
- /**
- * The buffer where data is stored.
- */
- protected char buf[];
- /**
- * The number of chars in the buffer.
- */
- protected int count;
- private final static ThreadLocal<SoftReference<char[]>> bufLocal = new ThreadLocal<SoftReference<char[]>>();
- private int features;
- public SerializeWriter(){
- this.features = JSON.DEFAULT_GENERATE_FEATURE;
- SoftReference<char[]> ref = bufLocal.get();
- if (ref != null) {
- buf = ref.get();
- bufLocal.set(null);
- }
- if (buf == null) {
- buf = new char[1024];
- }
- }
- /**
- * Creates a new CharArrayWriter.
- */
- public SerializeWriter(SerializerFeature... features){
- SoftReference<char[]> ref = bufLocal.get();
- if (ref != null) {
- buf = ref.get();
- bufLocal.set(null);
- }
- if (buf == null) {
- buf = new char[1024];
- }
- int featuresValue = 0;
- for (SerializerFeature feature : features) {
- featuresValue |= feature.getMask();
- }
- this.features = featuresValue;
- }
- /**
- * Creates a new CharArrayWriter with the specified initial size.
- *
- * @param initialSize an int specifying the initial buffer size.
- * @exception IllegalArgumentException if initialSize is negative
- */
- public SerializeWriter(int initialSize){
- if (initialSize <= 0) {
- throw new IllegalArgumentException("Negative initial size: " + initialSize);
- }
- buf = new char[initialSize];
- }
- public void config(SerializerFeature feature, boolean state) {
- if (state) {
- features |= feature.getMask();
- } else {
- features &= ~feature.getMask();
- }
- }
- public boolean isEnabled(SerializerFeature feature) {
- return SerializerFeature.isEnabled(this.features, feature);
- }
- /**
- * Writes a character to the buffer.
- */
- public void write(int c) {
- int newcount = count + 1;
- if (newcount > buf.length) {
- expandCapacity(newcount);
- }
- buf[count] = (char) c;
- count = newcount;
- }
- public void write(char c) {
- int newcount = count + 1;
- if (newcount > buf.length) {
- expandCapacity(newcount);
- }
- buf[count] = c;
- count = newcount;
- }
- /**
- * Writes characters to the buffer.
- *
- * @param c the data to be written
- * @param off the start offset in the data
- * @param len the number of chars that are written
- */
- public void write(char c[], int off, int len) {
- if (off < 0 || off > c.length || len < 0 || off + len > c.length || off + len < 0) {
- throw new IndexOutOfBoundsException();
- } else if (len == 0) {
- return;
- }
- int newcount = count + len;
- if (newcount > buf.length) {
- expandCapacity(newcount);
- }
- System.arraycopy(c, off, buf, count, len);
- count = newcount;
- }
- public void expandCapacity(int minimumCapacity) {
- int newCapacity = (buf.length * 3) / 2 + 1;
- if (newCapacity < minimumCapacity) {
- newCapacity = minimumCapacity;
- }
- char newValue[] = new char[newCapacity];
- System.arraycopy(buf, 0, newValue, 0, count);
- buf = newValue;
- }
- /**
- * Write a portion of a string to the buffer.
- *
- * @param str String to be written from
- * @param off Offset from which to start reading characters
- * @param len Number of characters to be written
- */
- public void write(String str, int off, int len) {
- int newcount = count + len;
- if (newcount > buf.length) {
- expandCapacity(newcount);
- }
- str.getChars(off, off + len, buf, count);
- count = newcount;
- }
- /**
- * Writes the contents of the buffer to another character stream.
- *
- * @param out the output stream to write to
- * @throws IOException If an I/O error occurs.
- */
- public void writeTo(Writer out) throws IOException {
- out.write(buf, 0, count);
- }
- public void writeTo(OutputStream out, String charset) throws IOException {
- byte[] bytes = new String(buf, 0, count).getBytes(charset);
- out.write(bytes);
- }
- public void writeTo(OutputStream out, Charset charset) throws IOException {
- byte[] bytes = new String(buf, 0, count).getBytes(charset);
- out.write(bytes);
- }
- public SerializeWriter append(CharSequence csq) {
- String s = (csq == null ? "null" : csq.toString());
- write(s, 0, s.length());
- return this;
- }
- public SerializeWriter append(CharSequence csq, int start, int end) {
- String s = (csq == null ? "null" : csq).subSequence(start, end).toString();
- write(s, 0, s.length());
- return this;
- }
- /**
- * Appends the specified character to this writer.
- * <p>
- * An invocation of this method of the form <tt>out.append(c)</tt> behaves in exactly the same way as the invocation
- *
- * <pre>
- * out.write(c)
- * </pre>
- *
- * @param c The 16-bit character to append
- * @return This writer
- * @since 1.5
- */
- public SerializeWriter append(char c) {
- write(c);
- return this;
- }
- /**
- * Resets the buffer so that you can use it again without throwing away the already allocated buffer.
- */
- public void reset() {
- count = 0;
- }
- /**
- * Returns a copy of the input data.
- *
- * @return an array of chars copied from the input data.
- */
- public char[] toCharArray() {
- char[] newValue = new char[count];
- System.arraycopy(buf, 0, newValue, 0, count);
- return newValue;
- }
- public byte[] toBytes(String charsetName) {
- if (charsetName == null) {
- charsetName = "UTF-8";
- }
- Charset cs = Charset.forName(charsetName);
- SerialWriterStringEncoder encoder = new SerialWriterStringEncoder(cs);
- return encoder.encode(buf, 0, count);
- }
- /**
- * Returns the current size of the buffer.
- *
- * @return an int representing the current size of the buffer.
- */
- public int size() {
- return count;
- }
- /**
- * Converts input data to a string.
- *
- * @return the string.
- */
- public String toString() {
- return new String(buf, 0, count);
- }
- /**
- * Flush the stream.
- */
- public void flush() {
- }
- /**
- * Close the stream. This method does not release the buffer, since its contents might still be required. Note:
- * Invoking this method in this class will have no effect.
- */
- public void close() {
- if (buf.length <= 1024 * 8) {
- bufLocal.set(new SoftReference<char[]>(buf));
- }
- this.buf = null;
- }
- public void writeBooleanArray(boolean[] array) throws IOException {
- int[] sizeArray = new int[array.length];
- int totalSize = 2;
- for (int i = 0; i < array.length; ++i) {
- if (i != 0) {
- totalSize++;
- }
- boolean val = array[i];
- int size;
- if (val) {
- size = 4; // "true".length();
- } else {
- size = 5; // "false".length();
- }
- sizeArray[i] = size;
- totalSize += size;
- }
- int newcount = count + totalSize;
- if (newcount > buf.length) {
- expandCapacity(newcount);
- }
- buf[count] = '[';
- int currentSize = count + 1;
- for (int i = 0; i < array.length; ++i) {
- if (i != 0) {
- buf[currentSize++] = ',';
- }
- boolean val = array[i];
- if (val) {
- // System.arraycopy("true".toCharArray(), 0, buf, currentSize,
- // 4);
- buf[currentSize++] = 't';
- buf[currentSize++] = 'r';
- buf[currentSize++] = 'u';
- buf[currentSize++] = 'e';
- } else {
- buf[currentSize++] = 'f';
- buf[currentSize++] = 'a';
- buf[currentSize++] = 'l';
- buf[currentSize++] = 's';
- buf[currentSize++] = 'e';
- }
- }
- buf[currentSize] = ']';
- count = newcount;
- }
- public void write(String text) {
- if (text == null) {
- writeNull();
- return;
- }
- int length = text.length();
- int newcount = count + length;
- if (newcount > buf.length) {
- expandCapacity(newcount);
- }
- text.getChars(0, length, buf, count);
- count = newcount;
- return;
- }
- public void writeInt(int i) {
- if (i == Integer.MIN_VALUE) {
- write("-2147483648");
- return;
- }
- int size = (i < 0) ? IOUtils.stringSize(-i) + 1 : IOUtils.stringSize(i);
- int newcount = count + size;
- if (newcount > buf.length) {
- expandCapacity(newcount);
- }
- IOUtils.getChars(i, newcount, buf);
- count = newcount;
- }
- public void writeShortArray(short[] array) throws IOException {
- int[] sizeArray = new int[array.length];
- int totalSize = 2;
- for (int i = 0; i < array.length; ++i) {
- if (i != 0) {
- totalSize++;
- }
- short val = array[i];
- int size = IOUtils.stringSize(val);
- sizeArray[i] = size;
- totalSize += size;
- }
- int newcount = count + totalSize;
- if (newcount > buf.length) {
- expandCapacity(newcount);
- }
- buf[count] = '[';
- int currentSize = count + 1;
- for (int i = 0; i < array.length; ++i) {
- if (i != 0) {
- buf[currentSize++] = ',';
- }
- short val = array[i];
- currentSize += sizeArray[i];
- IOUtils.getChars(val, currentSize, buf);
- }
- buf[currentSize] = ']';
- count = newcount;
- }
- public void writeByteArray(byte[] bytes) {
- int bytesLen = bytes.length;
- if (bytesLen == 0) {
- write("\"\"");
- return;
- }
- final char[] CA = Base64.CA;
- int eLen = (bytesLen / 3) * 3; // Length of even 24-bits.
- int charsLen = ((bytesLen - 1) / 3 + 1) << 2; // base64 character count
- // char[] chars = new char[charsLen];
- int offset = count;
- int newcount = count + charsLen + 2;
- if (newcount > buf.length) {
- expandCapacity(newcount);
- }
- count = newcount;
- buf[offset++] = '\"';
- // Encode even 24-bits
- for (int s = 0, d = offset; s < eLen;) {
- // Copy next three bytes into lower 24 bits of int, paying attension to sign.
- int i = (bytes[s++] & 0xff) << 16 | (bytes[s++] & 0xff) << 8 | (bytes[s++] & 0xff);
- // Encode the int into four chars
- buf[d++] = CA[(i >>> 18) & 0x3f];
- buf[d++] = CA[(i >>> 12) & 0x3f];
- buf[d++] = CA[(i >>> 6) & 0x3f];
- buf[d++] = CA[i & 0x3f];
- }
- // Pad and encode last bits if source isn't even 24 bits.
- int left = bytesLen - eLen; // 0 - 2.
- if (left > 0) {
- // Prepare the int
- int i = ((bytes[eLen] & 0xff) << 10) | (left == 2 ? ((bytes[bytesLen - 1] & 0xff) << 2) : 0);
- // Set last four chars
- buf[newcount - 5] = CA[i >> 12];
- buf[newcount - 4] = CA[(i >>> 6) & 0x3f];
- buf[newcount - 3] = left == 2 ? CA[i & 0x3f] : '=';
- buf[newcount - 2] = '=';
- }
- buf[newcount - 1] = '\"';
- }
- public void writeIntArray(int[] array) {
- int[] sizeArray = new int[array.length];
- int totalSize = 2;
- for (int i = 0; i < array.length; ++i) {
- if (i != 0) {
- totalSize++;
- }
- int val = array[i];
- int size;
- if (val == Integer.MIN_VALUE) {
- size = "-2147483648".length();
- } else {
- size = (val < 0) ? IOUtils.stringSize(-val) + 1 : IOUtils.stringSize(val);
- }
- sizeArray[i] = size;
- totalSize += size;
- }
- int newcount = count + totalSize;
- if (newcount > buf.length) {
- expandCapacity(newcount);
- }
- buf[count] = '[';
- int currentSize = count + 1;
- for (int i = 0; i < array.length; ++i) {
- if (i != 0) {
- buf[currentSize++] = ',';
- }
- int val = array[i];
- if (val == Integer.MIN_VALUE) {
- System.arraycopy("-2147483648".toCharArray(), 0, buf, currentSize, sizeArray[i]);
- currentSize += sizeArray[i];
- } else {
- currentSize += sizeArray[i];
- IOUtils.getChars(val, currentSize, buf);
- }
- }
- buf[currentSize] = ']';
- count = newcount;
- }
- public void writeIntAndChar(int i, char c) {
- if (i == Integer.MIN_VALUE) {
- write("-2147483648");
- write(c);
- return;
- }
- int size = (i < 0) ? IOUtils.stringSize(-i) + 1 : IOUtils.stringSize(i);
- int newcount0 = count + size;
- int newcount1 = newcount0 + 1;
- if (newcount1 > buf.length) {
- expandCapacity(newcount1);
- }
- IOUtils.getChars(i, newcount0, buf);
- buf[newcount0] = c;
- count = newcount1;
- }
- public void writeLongAndChar(long i, char c) throws IOException {
- if (i == Long.MIN_VALUE) {
- write("-9223372036854775808");
- write(c);
- return;
- }
- int size = (i < 0) ? IOUtils.stringSize(-i) + 1 : IOUtils.stringSize(i);
- int newcount0 = count + size;
- int newcount1 = newcount0 + 1;
- if (newcount1 > buf.length) {
- expandCapacity(newcount1);
- }
- IOUtils.getChars(i, newcount0, buf);
- buf[newcount0] = c;
- count = newcount1;
- }
- public void writeLong(long i) {
- if (i == Long.MIN_VALUE) {
- write("-9223372036854775808");
- return;
- }
- int size = (i < 0) ? IOUtils.stringSize(-i) + 1 : IOUtils.stringSize(i);
- int newcount = count + size;
- if (newcount > buf.length) {
- expandCapacity(newcount);
- }
- IOUtils.getChars(i, newcount, buf);
- count = newcount;
- }
- public void writeNull() {
- int newcount = count + 4;
- if (newcount > buf.length) {
- expandCapacity(newcount);
- }
- buf[count] = 'n';
- buf[count + 1] = 'u';
- buf[count + 2] = 'l';
- buf[count + 3] = 'l';
- count = newcount;
- }
- public void writeLongArray(long[] array) {
- int[] sizeArray = new int[array.length];
- int totalSize = 2;
- for (int i = 0; i < array.length; ++i) {
- if (i != 0) {
- totalSize++;
- }
- long val = array[i];
- int size;
- if (val == Long.MIN_VALUE) {
- size = "-9223372036854775808".length();
- } else {
- size = (val < 0) ? IOUtils.stringSize(-val) + 1 : IOUtils.stringSize(val);
- }
- sizeArray[i] = size;
- totalSize += size;
- }
- int newcount = count + totalSize;
- if (newcount > buf.length) {
- expandCapacity(newcount);
- }
- buf[count] = '[';
- int currentSize = count + 1;
- for (int i = 0; i < array.length; ++i) {
- if (i != 0) {
- buf[currentSize++] = ',';
- }
- long val = array[i];
- if (val == Long.MIN_VALUE) {
- System.arraycopy("-9223372036854775808".toCharArray(), 0, buf, currentSize, sizeArray[i]);
- currentSize += sizeArray[i];
- } else {
- currentSize += sizeArray[i];
- IOUtils.getChars(val, currentSize, buf);
- }
- }
- buf[currentSize] = ']';
- count = newcount;
- }
- private void writeStringWithDoubleQuote(String text, final char seperator) {
- writeStringWithDoubleQuote(text, seperator, true);
- }
- private void writeStringWithDoubleQuote(String text, final char seperator, boolean checkSpecial) {
- // final boolean[] specicalFlags_doubleQuotes =
- // CharTypes.specicalFlags_doubleQuotes;
- // final int len_flags = specicalFlags_doubleQuotes.length;
- if (text == null) {
- writeNull();
- return;
- }
- int len = text.length();
- int newcount = count + len + 2;
- if (seperator != 0) {
- newcount++;
- }
- if (newcount > buf.length) {
- expandCapacity(newcount);
- }
- int start = count + 1;
- int end = start + len;
- buf[count] = '\"';
- text.getChars(0, len, buf, start);
- count = newcount;
- if (isEnabled(SerializerFeature.BrowserCompatible)) {
- int lastSpecialIndex = -1;
- for (int i = start; i < end; ++i) {
- char ch = buf[i];
- if (ch == '"' || ch == '/' || ch == '\\') {
- lastSpecialIndex = i;
- newcount += 1;
- continue;
- }
- if (ch == '\b' || ch == '\f' || ch == '\n' || ch == '\r' || ch == '\t') {
- lastSpecialIndex = i;
- newcount += 1;
- continue;
- }
- if (ch < 32) {
- lastSpecialIndex = i;
- newcount += 5;
- continue;
- }
- if (ch >= 127) {
- lastSpecialIndex = i;
- newcount += 5;
- continue;
- }
- }
- if (newcount > buf.length) {
- expandCapacity(newcount);
- }
- count = newcount;
- for (int i = lastSpecialIndex; i >= start; --i) {
- char ch = buf[i];
- if (ch == '\b' || ch == '\f' || ch == '\n' || ch == '\r' || ch == '\t') {
- System.arraycopy(buf, i + 1, buf, i + 2, end - i - 1);
- buf[i] = '\\';
- buf[i + 1] = replaceChars[(int) ch];
- end += 1;
- continue;
- }
- if (ch == '"' || ch == '/' || ch == '\\') {
- System.arraycopy(buf, i + 1, buf, i + 2, end - i - 1);
- buf[i] = '\\';
- buf[i + 1] = ch;
- end += 1;
- continue;
- }
- if (ch < 32) {
- System.arraycopy(buf, i + 1, buf, i + 6, end - i - 1);
- buf[i] = '\\';
- buf[i + 1] = 'u';
- buf[i + 2] = '0';
- buf[i + 3] = '0';
- buf[i + 4] = CharTypes.ASCII_CHARS[ch * 2];
- buf[i + 5] = CharTypes.ASCII_CHARS[ch * 2 + 1];
- end += 5;
- continue;
- }
- if (ch >= 127) {
- System.arraycopy(buf, i + 1, buf, i + 6, end - i - 1);
- buf[i] = '\\';
- buf[i + 1] = 'u';
- buf[i + 2] = CharTypes.digits[(ch >>> 12) & 15];
- buf[i + 3] = CharTypes.digits[(ch >>> 8) & 15];
- buf[i + 4] = CharTypes.digits[(ch >>> 4) & 15];
- buf[i + 5] = CharTypes.digits[ch & 15];
- end += 5;
- }
- }
- if (seperator != 0) {
- buf[count - 2] = '\"';
- buf[count - 1] = seperator;
- } else {
- buf[count - 1] = '\"';
- }
- return;
- }
- int specialCount = 0;
- int lastSpecialIndex = -1;
- char lastSpecial = '\0';
- if (checkSpecial) {
- for (int i = start; i < end; ++i) {
- char ch = buf[i];
- if (ch >= ']') {
- continue;
- }
- if (ch == ' ') {
- continue;
- }
- if (ch >= '0' && ch != '\\') {
- continue;
- }
- if (ch < CharTypes.specicalFlags_doubleQuotes.length
- && CharTypes.specicalFlags_doubleQuotes[ch] //
- || (ch == '\t' && isEnabled(SerializerFeature.WriteTabAsSpecial))
- || (ch == '/' && isEnabled(SerializerFeature.WriteSlashAsSpecial))) {
- specialCount++;
- lastSpecialIndex = i;
- lastSpecial = ch;
- }
- }
- }
- newcount += specialCount;
- if (newcount > buf.length) {
- expandCapacity(newcount);
- }
- count = newcount;
- if (specialCount == 1) {
- System.arraycopy(buf, lastSpecialIndex + 1, buf, lastSpecialIndex + 2, end - lastSpecialIndex - 1);
- buf[lastSpecialIndex] = '\\';
- buf[++lastSpecialIndex] = replaceChars[(int) lastSpecial];
- } else if (specialCount > 1) {
- System.arraycopy(buf, lastSpecialIndex + 1, buf, lastSpecialIndex + 2, end - lastSpecialIndex - 1);
- buf[lastSpecialIndex] = '\\';
- buf[++lastSpecialIndex] = replaceChars[(int) lastSpecial];
- end++;
- for (int i = lastSpecialIndex - 2; i >= start; --i) {
- char ch = buf[i];
- if (ch < CharTypes.specicalFlags_doubleQuotes.length
- && CharTypes.specicalFlags_doubleQuotes[ch] //
- || (ch == '\t' && isEnabled(SerializerFeature.WriteTabAsSpecial))
- || (ch == '/' && isEnabled(SerializerFeature.WriteSlashAsSpecial))) {
- System.arraycopy(buf, i + 1, buf, i + 2, end - i - 1);
- buf[i] = '\\';
- buf[i + 1] = replaceChars[(int) ch];
- end++;
- }
- }
- }
- if (seperator != 0) {
- buf[count - 2] = '\"';
- buf[count - 1] = seperator;
- } else {
- buf[count - 1] = '\"';
- }
- }
- public void writeKeyWithDoubleQuote(String text) {
- writeKeyWithDoubleQuote(text, true);
- }
- public void writeKeyWithDoubleQuote(String text, boolean checkSpecial) {
- final boolean[] specicalFlags_doubleQuotes = CharTypes.specicalFlags_doubleQuotes;
- int len = text.length();
- int newcount = count + len + 3;
- if (newcount > buf.length) {
- expandCapacity(newcount);
- }
- int start = count + 1;
- int end = start + len;
- buf[count] = '\"';
- text.getChars(0, len, buf, start);
- count = newcount;
- if (checkSpecial) {
- for (int i = start; i < end; ++i) {
- char ch = buf[i];
- if (ch < specicalFlags_doubleQuotes.length
- && specicalFlags_doubleQuotes[ch] //
- || (ch == '\t' && isEnabled(SerializerFeature.WriteTabAsSpecial))
- || (ch == '/' && isEnabled(SerializerFeature.WriteSlashAsSpecial))) {
- newcount++;
- if (newcount > buf.length) {
- expandCapacity(newcount);
- }
- count = newcount;
- System.arraycopy(buf, i + 1, buf, i + 2, end - i - 1);
- buf[i] = '\\';
- buf[++i] = replaceChars[(int) ch];
- end++;
- }
- }
- }
- buf[count - 2] = '\"';
- buf[count - 1] = ':';
- }
- public void writeFieldNull(char seperator, String name) {
- write(seperator);
- writeFieldName(name);
- writeNull();
- }
- public void writeFieldEmptyList(char seperator, String key) {
- write(seperator);
- writeFieldName(key);
- write("[]");
- }
- public void writeFieldNullString(char seperator, String name) {
- write(seperator);
- writeFieldName(name);
- if (isEnabled(SerializerFeature.WriteNullStringAsEmpty)) {
- writeString("");
- } else {
- writeNull();
- }
- }
- public void writeFieldNullBoolean(char seperator, String name) {
- write(seperator);
- writeFieldName(name);
- if (isEnabled(SerializerFeature.WriteNullBooleanAsFalse)) {
- write("false");
- } else {
- writeNull();
- }
- }
- public void writeFieldNullList(char seperator, String name) {
- write(seperator);
- writeFieldName(name);
- if (isEnabled(SerializerFeature.WriteNullListAsEmpty)) {
- write("[]");
- } else {
- writeNull();
- }
- }
- public void writeFieldNullNumber(char seperator, String name) {
- write(seperator);
- writeFieldName(name);
- if (isEnabled(SerializerFeature.WriteNullNumberAsZero)) {
- write('0');
- } else {
- writeNull();
- }
- }
- public void writeFieldValue(char seperator, String name, char value) {
- write(seperator);
- writeFieldName(name);
- if (value == 0) {
- writeString("\u0000");
- } else {
- writeString(Character.toString(value));
- }
- }
- public void writeFieldValue(char seperator, String name, boolean value) {
- char keySeperator = isEnabled(SerializerFeature.UseSingleQuotes) ? '\'' : '"';
- int intSize = value ? 4 : 5;
- int nameLen = name.length();
- int newcount = count + nameLen + 4 + intSize;
- if (newcount > buf.length) {
- expandCapacity(newcount);
- }
- int start = count;
- count = newcount;
- buf[start] = seperator;
- int nameEnd = start + nameLen + 1;
- buf[start + 1] = keySeperator;
- name.getChars(0, nameLen, buf, start + 2);
- buf[nameEnd + 1] = keySeperator;
- if (value) {
- System.arraycopy(":true".toCharArray(), 0, buf, nameEnd + 2, 5);
- } else {
- System.arraycopy(":false".toCharArray(), 0, buf, nameEnd + 2, 6);
- }
- }
- public void writeFieldValue1(char seperator, String name, boolean value) {
- write(seperator);
- writeFieldName(name);
- if (value) {
- write("true");
- } else {
- write("false");
- }
- }
- public void writeFieldValue(char seperator, String name, int value) {
- if (value == Integer.MIN_VALUE || (!isEnabled(SerializerFeature.QuoteFieldNames))) {
- writeFieldValue1(seperator, name, value);
- return;
- }
- char keySeperator = isEnabled(SerializerFeature.UseSingleQuotes) ? '\'' : '"';
- int intSize = (value < 0) ? IOUtils.stringSize(-value) + 1 : IOUtils.stringSize(value);
- int nameLen = name.length();
- int newcount = count + nameLen + 4 + intSize;
- if (newcount > buf.length) {
- expandCapacity(newcount);
- }
- int start = count;
- count = newcount;
- buf[start] = seperator;
- int nameEnd = start + nameLen + 1;
- buf[start + 1] = keySeperator;
- name.getChars(0, nameLen, buf, start + 2);
- buf[nameEnd + 1] = keySeperator;
- buf[nameEnd + 2] = ':';
- IOUtils.getChars(value, count, buf);
- }
- public void writeFieldValue1(char seperator, String name, int value) {
- write(seperator);
- writeFieldName(name);
- writeInt(value);
- }
- public void writeFieldValue(char seperator, String name, long value) {
- if (value == Long.MIN_VALUE || (!isEnabled(SerializerFeature.QuoteFieldNames))) {
- writeFieldValue1(seperator, name, value);
- return;
- }
- char keySeperator = isEnabled(SerializerFeature.UseSingleQuotes) ? '\'' : '"';
- int intSize = (value < 0) ? IOUtils.stringSize(-value) + 1 : IOUtils.stringSize(value);
- int nameLen = name.length();
- int newcount = count + nameLen + 4 + intSize;
- if (newcount > buf.length) {
- expandCapacity(newcount);
- }
- int start = count;
- count = newcount;
- buf[start] = seperator;
- int nameEnd = start + nameLen + 1;
- buf[start + 1] = keySeperator;
- name.getChars(0, nameLen, buf, start + 2);
- buf[nameEnd + 1] = keySeperator;
- buf[nameEnd + 2] = ':';
- IOUtils.getChars(value, count, buf);
- }
- public void writeFieldValue1(char seperator, String name, long value) {
- write(seperator);
- writeFieldName(name);
- writeLong(value);
- }
- public void writeFieldValue(char seperator, String name, float value) {
- write(seperator);
- writeFieldName(name);
- if (value == 0) {
- write('0');
- } else if (Float.isNaN(value)) {
- writeNull();
- } else if (Float.isInfinite(value)) {
- writeNull();
- } else {
- String text = Float.toString(value);
- if (text.endsWith(".0")) {
- text = text.substring(0, text.length() - 2);
- }
- write(text);
- }
- }
- public void writeFieldValue(char seperator, String name, double value) {
- write(seperator);
- writeFieldName(name);
- if (value == 0) {
- write('0');
- } else if (Double.isNaN(value)) {
- writeNull();
- } else if (Double.isInfinite(value)) {
- writeNull();
- } else {
- String text = Double.toString(value);
- if (text.endsWith(".0")) {
- text = text.substring(0, text.length() - 2);
- }
- write(text);
- }
- }
- public void writeFieldValue(char seperator, String name, String value) {
- if (isEnabled(SerializerFeature.QuoteFieldNames)) {
- if (isEnabled(SerializerFeature.UseSingleQuotes)) {
- write(seperator);
- writeFieldName(name);
- if (value == null) {
- writeNull();
- } else {
- writeString(value);
- }
- } else {
- if (isEnabled(SerializerFeature.BrowserCompatible)) {
- write(seperator);
- writeStringWithDoubleQuote(name, ':');
- writeStringWithDoubleQuote(value, (char) 0);
- } else {
- writeFieldValueStringWithDoubleQuote(seperator, name, value, true);
- }
- }
- } else {
- write(seperator);
- writeFieldName(name);
- if (value == null) {
- writeNull();
- } else {
- writeString(value);
- }
- }
- }
- private void writeFieldValueStringWithDoubleQuote(char seperator, String name, String value, boolean checkSpecial) {
- int nameLen = name.length();
- int valueLen;
- int newcount = count;
- if (value == null) {
- valueLen = 4;
- newcount += nameLen + 8;
- } else {
- valueLen = value.length();
- newcount += nameLen + valueLen + 6;
- }
- if (newcount > buf.length) {
- expandCapacity(newcount);
- }
- buf[count] = seperator;
- int nameStart = count + 2;
- int nameEnd = nameStart + nameLen;
- buf[count + 1] = '\"';
- name.getChars(0, nameLen, buf, nameStart);
- count = newcount;
- buf[nameEnd] = '\"';
- int index = nameEnd + 1;
- buf[index++] = ':';
- if (value == null) {
- buf[index++] = 'n';
- buf[index++] = 'u';
- buf[index++] = 'l';
- buf[index++] = 'l';
- return;
- }
- buf[index++] = '"';
- int valueStart = index;
- int valueEnd = valueStart + valueLen;
- value.getChars(0, valueLen, buf, valueStart);
- if (checkSpecial && !isEnabled(SerializerFeature.DisableCheckSpecialChar)) {
- int specialCount = 0;
- int lastSpecialIndex = -1;
- char lastSpecial = '\0';
- for (int i = valueStart; i < valueEnd; ++i) {
- char ch = buf[i];
- if (ch >= ']') {
- continue;
- }
- if (isSpecial(ch, this.features)) {
- specialCount++;
- lastSpecialIndex = i;
- lastSpecial = ch;
- }
- }
- if (specialCount > 0) {
- newcount += specialCount;
- if (newcount > buf.length) {
- expandCapacity(newcount);
- }
- count = newcount;
- }
- if (specialCount == 1) {
- System.arraycopy(buf, lastSpecialIndex + 1, buf, lastSpecialIndex + 2, valueEnd - lastSpecialIndex - 1);
- buf[lastSpecialIndex] = '\\';
- buf[++lastSpecialIndex] = replaceChars[(int) lastSpecial];
- } else if (specialCount > 1) {
- System.arraycopy(buf, lastSpecialIndex + 1, buf, lastSpecialIndex + 2, valueEnd - lastSpecialIndex - 1);
- buf[lastSpecialIndex] = '\\';
- buf[++lastSpecialIndex] = replaceChars[(int) lastSpecial];
- valueEnd++;
- for (int i = lastSpecialIndex - 2; i >= valueStart; --i) {
- char ch = buf[i];
- if (ch == '\b' || ch == '\n' || ch == '\r' || ch == '\f' || ch == '\\'
- || ch == '"' //
- || (ch == '\t' && isEnabled(SerializerFeature.WriteTabAsSpecial))
- || (ch == '/' && isEnabled(SerializerFeature.WriteSlashAsSpecial))) {
- System.arraycopy(buf, i + 1, buf, i + 2, valueEnd - i - 1);
- buf[i] = '\\';
- buf[i + 1] = replaceChars[(int) ch];
- valueEnd++;
- }
- }
- }
- }
- buf[count - 1] = '\"';
- }
- final static boolean isSpecial(char ch, int features) {
- // if (ch > ']') {
- // return false;
- // }
- if (ch == ' ') {
- return false;
- }
-
- if (ch == '/' && SerializerFeature.isEnabled(features, SerializerFeature.WriteSlashAsSpecial)) {
- return true;
- }
- if (ch > '#' && ch != '\\') {
- return false;
- }
- if (ch == '\b' || ch == '\n' || ch == '\r' || ch == '\f' || ch == '\\' || ch == '"' //
- || (ch == '\t' && SerializerFeature.isEnabled(features, SerializerFeature.WriteTabAsSpecial))){
- return true;
- }
-
- return false;
- }
- // writeStringWithSingleQuote
- public void writeFieldValue(char seperator, String name, Enum<?> value) {
- if (value == null) {
- write(seperator);
- writeFieldName(name);
- writeNull();
- return;
- }
- if (isEnabled(SerializerFeature.WriteEnumUsingToString)) {
- if (isEnabled(SerializerFeature.UseSingleQuotes)) {
- writeFieldValue(seperator, name, value.name());
- } else {
- writeFieldValueStringWithDoubleQuote(seperator, name, value.name(), false);
- return;
- }
- // writeStringWithDoubleQuote
- } else {
- writeFieldValue(seperator, name, value.ordinal());
- }
- }
- public void writeFieldValue(char seperator, String name, BigDecimal value) {
- write(seperator);
- writeFieldName(name);
- if (value == null) {
- writeNull();
- } else {
- write(value.toString());
- }
- }
- public void writeString(String text, char seperator) {
- if (isEnabled(SerializerFeature.UseSingleQuotes)) {
- writeStringWithSingleQuote(text);
- write(seperator);
- } else {
- writeStringWithDoubleQuote(text, seperator);
- }
- }
- public void writeString(String text) {
- if (isEnabled(SerializerFeature.UseSingleQuotes)) {
- writeStringWithSingleQuote(text);
- } else {
- writeStringWithDoubleQuote(text, (char) 0);
- }
- }
- private void writeStringWithSingleQuote(String text) {
- if (text == null) {
- int newcount = count + 4;
- if (newcount > buf.length) {
- expandCapacity(newcount);
- }
- "null".getChars(0, 4, buf, count);
- count = newcount;
- return;
- }
- int len = text.length();
- int newcount = count + len + 2;
- if (newcount > buf.length) {
- expandCapacity(newcount);
- }
- int start = count + 1;
- int end = start + len;
- buf[count] = '\'';
- text.getChars(0, len, buf, start);
- count = newcount;
- int specialCount = 0;
- int lastSpecialIndex = -1;
- char lastSpecial = '\0';
- for (int i = start; i < end; ++i) {
- char ch = buf[i];
- if (ch == '\b' || ch == '\n' || ch == '\r' || ch == '\f' || ch == '\\'
- || ch == '\'' //
- || (ch == '\t' && isEnabled(SerializerFeature.WriteTabAsSpecial))
- || (ch == '/' && isEnabled(SerializerFeature.WriteSlashAsSpecial))) {
- specialCount++;
- lastSpecialIndex = i;
- lastSpecial = ch;
- }
- }
- newcount += specialCount;
- if (newcount > buf.length) {
- expandCapacity(newcount);
- }
- count = newcount;
- if (specialCount == 1) {
- System.arraycopy(buf, lastSpecialIndex + 1, buf, lastSpecialIndex + 2, end - lastSpecialIndex - 1);
- buf[lastSpecialIndex] = '\\';
- buf[++lastSpecialIndex] = replaceChars[(int) lastSpecial];
- } else if (specialCount > 1) {
- System.arraycopy(buf, lastSpecialIndex + 1, buf, lastSpecialIndex + 2, end - lastSpecialIndex - 1);
- buf[lastSpecialIndex] = '\\';
- buf[++lastSpecialIndex] = replaceChars[(int) lastSpecial];
- end++;
- for (int i = lastSpecialIndex - 2; i >= start; --i) {
- char ch = buf[i];
- if (ch == '\b' || ch == '\n' || ch == '\r' || ch == '\f' || ch == '\\'
- || ch == '\'' //
- || (ch == '\t' && isEnabled(SerializerFeature.WriteTabAsSpecial))
- || (ch == '/' && isEnabled(SerializerFeature.WriteSlashAsSpecial))) {
- System.arraycopy(buf, i + 1, buf, i + 2, end - i - 1);
- buf[i] = '\\';
- buf[i + 1] = replaceChars[(int) ch];
- end++;
- }
- }
- }
- buf[count - 1] = '\'';
- }
- public void writeFieldName(String key) {
- writeFieldName(key, false);
- }
- public void writeFieldName(String key, boolean checkSpecial) {
- if (key == null) {
- write("null:");
- return;
- }
- if (isEnabled(SerializerFeature.UseSingleQuotes)) {
- if (isEnabled(SerializerFeature.QuoteFieldNames)) {
- writeKeyWithSingleQuote(key);
- } else {
- writeKeyWithSingleQuoteIfHasSpecial(key);
- }
- } else {
- if (isEnabled(SerializerFeature.QuoteFieldNames)) {
- writeKeyWithDoubleQuote(key, checkSpecial);
- } else {
- writeKeyWithDoubleQuoteIfHasSpecial(key);
- }
- }
- }
- private void writeKeyWithSingleQuote(String text) {
- final boolean[] specicalFlags_singleQuotes = CharTypes.specicalFlags_singleQuotes;
- int len = text.length();
- int newcount = count + len + 3;
- if (newcount > buf.length) {
- expandCapacity(newcount);
- }
- int start = count + 1;
- int end = start + len;
- buf[count] = '\'';
- text.getChars(0, len, buf, start);
- count = newcount;
- for (int i = start; i < end; ++i) {
- char ch = buf[i];
- if (ch < specicalFlags_singleQuotes.length
- && specicalFlags_singleQuotes[ch] //
- || (ch == '\t' && isEnabled(SerializerFeature.WriteTabAsSpecial))
- || (ch == '/' && isEnabled(SerializerFeature.WriteSlashAsSpecial))) {
- newcount++;
- if (newcount > buf.length) {
- expandCapacity(newcount);
- }
- count = newcount;
- System.arraycopy(buf, i + 1, buf, i + 2, end - i - 1);
- buf[i] = '\\';
- buf[++i] = replaceChars[(int) ch];
- end++;
- }
- }
- buf[count - 2] = '\'';
- buf[count - 1] = ':';
- }
- private void writeKeyWithDoubleQuoteIfHasSpecial(String text) {
- final boolean[] specicalFlags_doubleQuotes = CharTypes.specicalFlags_doubleQuotes;
- int len = text.length();
- int newcount = count + len + 1;
- if (newcount > buf.length) {
- expandCapacity(newcount);
- }
- int start = count;
- int end = start + len;
- text.getChars(0, len, buf, start);
- count = newcount;
- boolean hasSpecial = false;
- for (int i = start; i < end; ++i) {
- char ch = buf[i];
- if (ch < specicalFlags_doubleQuotes.length && specicalFlags_doubleQuotes[ch]) {
- if (!hasSpecial) {
- newcount += 3;
- if (newcount > buf.length) {
- expandCapacity(newcount);
- }
- count = newcount;
- System.arraycopy(buf, i + 1, buf, i + 3, end - i - 1);
- System.arraycopy(buf, 0, buf, 1, i);
- buf[start] = '"';
- buf[++i] = '\\';
- buf[++i] = replaceChars[(int) ch];
- end += 2;
- buf[count - 2] = '"';
- hasSpecial = true;
- } else {
- newcount++;
- if (newcount > buf.length) {
- expandCapacity(newcount);
- }
- count = newcount;
- System.arraycopy(buf, i + 1, buf, i + 2, end - i);
- buf[i] = '\\';
- buf[++i] = replaceChars[(int) ch];
- end++;
- }
- }
- }
- buf[count - 1] = ':';
- }
- private void writeKeyWithSingleQuoteIfHasSpecial(String text) {
- final boolean[] specicalFlags_singleQuotes = CharTypes.specicalFlags_singleQuotes;
- int len = text.length();
- int newcount = count + len + 1;
- if (newcount > buf.length) {
- expandCapacity(newcount);
- }
- int start = count;
- int end = start + len;
- text.getChars(0, len, buf, start);
- count = newcount;
- boolean hasSpecial = false;
- for (int i = start; i < end; ++i) {
- char ch = buf[i];
- if (ch < specicalFlags_singleQuotes.length && specicalFlags_singleQuotes[ch]) {
- if (!hasSpecial) {
- newcount += 3;
- if (newcount > buf.length) {
- expandCapacity(newcount);
- }
- count = newcount;
- System.arraycopy(buf, i + 1, buf, i + 3, end - i - 1);
- System.arraycopy(buf, 0, buf, 1, i);
- buf[start] = '\'';
- buf[++i] = '\\';
- buf[++i] = replaceChars[(int) ch];
- end += 2;
- buf[count - 2] = '\'';
- hasSpecial = true;
- } else {
- newcount++;
- if (newcount > buf.length) {
- expandCapacity(newcount);
- }
- count = newcount;
- System.arraycopy(buf, i + 1, buf, i + 2, end - i);
- buf[i] = '\\';
- buf[++i] = replaceChars[(int) ch];
- end++;
- }
- }
- }
- buf[newcount - 1] = ':';
- }
- }