All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.redkale.convert.json.JsonByteBufferWriter Maven / Gradle / Ivy

/*
 * To change this license header, choose License Headers in Project Properties.
 * To change this template file, choose Tools | Templates
 * and open the template in the editor.
 */
package org.redkale.convert.json;

import java.nio.*;
import java.nio.charset.*;
import java.util.*;
import java.util.function.*;
import org.redkale.convert.*;
import org.redkale.util.*;

/**
 * 以ByteBuffer为数据载体的JsonWriter
 *
 * 

* 详情见: https://redkale.org * * @author zhangjx */ public class JsonByteBufferWriter extends JsonWriter { protected Charset charset; private final Supplier supplier; private ByteBuffer[] buffers; private int index; protected JsonByteBufferWriter(boolean tiny, Supplier supplier) { this(tiny, null, supplier); } protected JsonByteBufferWriter(boolean tiny, Charset charset, Supplier supplier) { this.tiny = tiny; this.charset = StandardCharsets.UTF_8.equals(charset) ? null : charset; this.supplier = supplier; } @Override public JsonByteBufferWriter tiny(boolean tiny) { this.tiny = tiny; return this; } @Override protected boolean recycle() { this.index = 0; this.specify = null; this.charset = null; this.buffers = null; return false; } @Override public ByteBuffer[] toBuffers() { if (buffers == null) return new ByteBuffer[0]; for (int i = index; i < this.buffers.length; i++) { ByteBuffer buf = this.buffers[i]; if (buf.position() != 0) buf.flip(); } return this.buffers; } @Override public int count() { if (this.buffers == null) return 0; int len = 0; for (ByteBuffer buffer : buffers) { len += buffer.remaining(); } return len; } private int expand(final int byteLength) { if (this.buffers == null) { this.index = 0; this.buffers = new ByteBuffer[]{supplier.get()}; } ByteBuffer buffer = this.buffers[index]; if (!buffer.hasRemaining()) { buffer.flip(); buffer = supplier.get(); this.buffers = Utility.append(this.buffers, buffer); this.index++; } int len = buffer.remaining(); int size = 0; while (len < byteLength) { buffer = supplier.get(); this.buffers = Utility.append(this.buffers, buffer); len += buffer.remaining(); size++; } return size; } @Override public void writeTo(final char ch) { if (ch > Byte.MAX_VALUE) throw new ConvertException("writeTo char(int.value = " + (int) ch + ") must be less 127"); expand(1); this.buffers[index].put((byte) ch); } @Override public void writeTo(final char[] chs, final int start, final int len) { writeTo(-1, false, chs, start, len); } private void writeTo(int expandsize, final boolean quote, final char[] chs, final int start, final int len) { int byteLength = quote ? 2 : 0; ByteBuffer bb = null; if (charset == null) { byteLength += encodeUTF8Length(chs, start, len); } else { bb = charset.encode(CharBuffer.wrap(chs, start, len)); byteLength += bb.remaining(); } if (expandsize < 0) expandsize = expand(byteLength); if (expandsize == 0) { // 只需要一个buffer final ByteBuffer buffer = this.buffers[index]; if (quote) buffer.put((byte) '"'); if (charset == null) { //UTF-8 final int limit = start + len; for (int i = start; i < limit; i++) { char c = chs[i]; if (c < 0x80) { buffer.put((byte) c); } else if (c < 0x800) { buffer.put((byte) (0xc0 | (c >> 6))); buffer.put((byte) (0x80 | (c & 0x3f))); } else { buffer.put((byte) (0xe0 | ((c >> 12)))); buffer.put((byte) (0x80 | ((c >> 6) & 0x3f))); buffer.put((byte) (0x80 | (c & 0x3f))); } } } else { buffer.put(bb); } if (quote) buffer.put((byte) '"'); return; } ByteBuffer buffer = this.buffers[index]; if (quote) { if (!buffer.hasRemaining()) buffer = nextByteBuffer(); buffer.put((byte) '"'); } if (charset == null) { //UTF-8 final int limit = start + len; for (int i = start; i < limit; i++) { buffer = putUTF8Char(buffer, chs[i]); } } else { while (bb.hasRemaining()) { if (!buffer.hasRemaining()) buffer = nextByteBuffer(); buffer.put(bb.get()); } } if (quote) { if (!buffer.hasRemaining()) buffer = nextByteBuffer(); buffer.put((byte) '"'); } } private ByteBuffer putUTF8Char(ByteBuffer buffer, char c) { if (c < 0x80) { if (!buffer.hasRemaining()) buffer = nextByteBuffer(); buffer.put((byte) c); } else if (c < 0x800) { if (!buffer.hasRemaining()) buffer = nextByteBuffer(); buffer.put((byte) (0xc0 | (c >> 6))); if (!buffer.hasRemaining()) buffer = nextByteBuffer(); buffer.put((byte) (0x80 | (c & 0x3f))); } else { if (!buffer.hasRemaining()) buffer = nextByteBuffer(); buffer.put((byte) (0xe0 | ((c >> 12)))); if (!buffer.hasRemaining()) buffer = nextByteBuffer(); buffer.put((byte) (0x80 | ((c >> 6) & 0x3f))); if (!buffer.hasRemaining()) buffer = nextByteBuffer(); buffer.put((byte) (0x80 | (c & 0x3f))); } return buffer; } private ByteBuffer nextByteBuffer() { this.buffers[this.index].flip(); return this.buffers[++this.index]; } protected static int encodeUTF8Length(final char[] text, final int start, final int len) { char c; int size = 0; final char[] chars = text; final int limit = start + len; for (int i = start; i < limit; i++) { c = chars[i]; size += (c < 0x80 ? 1 : (c < 0x800 ? 2 : 3)); } return size; } protected static int encodeEscapeUTF8Length(final char[] text, final int start, final int len) { char c; int size = 0; final char[] chars = text; final int limit = start + len; for (int i = start; i < limit; i++) { c = chars[i]; switch (c) { case '\n': size += 2; break; case '\r': size += 2; break; case '\t': size += 2; break; case '\\': size += 2; break; case '"': size += 2; break; default: size += (c < 0x80 ? 1 : (c < 0x800 ? 2 : 3)); break; } } return size; } /** * 注意: 该String值不能为null且不会进行转义, 只用于不含需要转义字符的字符串,例如enum、double、BigInteger转换的String * * @param quote 是否写入双引号 * @param value String值 */ @Override public void writeTo(final boolean quote, final String value) { char[] chs = Utility.charArray(value); writeTo(-1, quote, chs, 0, chs.length); } @Override public void writeInt(int value) { writeTo(false, String.valueOf(value)); } @Override public void writeLong(long value) { writeTo(false, String.valueOf(value)); } @Override public void writeString(String value) { if (value == null) { writeNull(); return; } final char[] chs = Utility.charArray(value); int len = 0; for (char ch : chs) { switch (ch) { case '\n': len += 2; break; case '\r': len += 2; break; case '\t': len += 2; break; case '\\': len += 2; break; case '"': len += 2; break; default: len++; break; } } if (len == chs.length) { writeTo(-1, true, chs, 0, len); return; } int expandsize = -1; if (this.charset == null) { //UTF-8 final int byteLength = 2 + encodeEscapeUTF8Length(chs, 0, chs.length); expandsize = expand(byteLength); if (expandsize == 0) { // 只需要一个buffer final ByteBuffer buffer = this.buffers[index]; buffer.put((byte) '"'); for (char c : chs) { switch (c) { case '\n': buffer.put((byte) '\\').put((byte) 'n'); break; case '\r': buffer.put((byte) '\\').put((byte) 'r'); break; case '\t': buffer.put((byte) '\\').put((byte) 't'); break; case '\\': buffer.put((byte) '\\').put((byte) '\\'); break; case '"': buffer.put((byte) '\\').put((byte) '"'); break; default: if (c < 0x80) { buffer.put((byte) c); } else if (c < 0x800) { buffer.put((byte) (0xc0 | (c >> 6))); buffer.put((byte) (0x80 | (c & 0x3f))); } else { buffer.put((byte) (0xe0 | ((c >> 12)))); buffer.put((byte) (0x80 | ((c >> 6) & 0x3f))); buffer.put((byte) (0x80 | (c & 0x3f))); } break; } } buffer.put((byte) '"'); return; } } StringBuilder sb = new StringBuilder(len); for (char ch : chs) { switch (ch) { case '\n': sb.append("\\n"); break; case '\r': sb.append("\\r"); break; case '\t': sb.append("\\t"); break; case '\\': sb.append("\\\\"); break; case '"': sb.append("\\\""); break; default: sb.append(ch); break; } } char[] cs = Utility.charArray(sb); writeTo(expandsize, true, cs, 0, sb.length()); } @Override public String toString() { return Objects.toString(this); } }





© 2015 - 2024 Weber Informatics LLC | Privacy Policy