/**
* Copyright 2014 Duan Bingnan
*
* 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.pinus4j.serializer.io;
import java.io.UnsupportedEncodingException;
public abstract class AbstractBufferOutput implements DataOutput {
public static final int UNI_SUR_HIGH_START = 0xD800;
public static final int UNI_SUR_LOW_START = 0xDC00;
private static final long HALF_SHIFT = 10;
private static final int SURROGATE_OFFSET = Character.MIN_SUPPLEMENTARY_CODE_POINT
- (UNI_SUR_HIGH_START << HALF_SHIFT) - UNI_SUR_LOW_START;
protected int offset;
/**
* total capacity.
*/
protected int limit;
public void writeBoolean(boolean b) {
_write(b ? (byte) 1 : (byte) 0);
}
public void writeByte(byte b) {
_write(b);
}
public void writeChar(char c) {
int code = (int) c;
writeVInt(code);
}
public void writeShort(short s) {
writeVInt(Short.valueOf(s).intValue());
}
public void writeInt(int i) {
_write((byte) ((i >>> 24) & 0xFF));
_write((byte) ((i >>> 16) & 0xFF));
_write((byte) ((i >>> 8) & 0xFF));
_write((byte) ((i >>> 0) & 0xFF));
}
public void writeLong(long l) {
_write((byte) (l >>> 56));
_write((byte) (l >>> 48));
_write((byte) (l >>> 40));
_write((byte) (l >>> 32));
_write((byte) (l >>> 24));
_write((byte) (l >>> 16));
_write((byte) (l >>> 8));
_write((byte) (l >>> 0));
}
public void writeFloat(float f) {
writeVInt(Float.floatToIntBits(f));
}
public void writeDouble(double d) {
writeVLong(Double.doubleToLongBits(d));
}
public void writeVInt(int i) {
while ((i & ~0x7F) != 0) {
writeByte((byte) ((i & 0x7F) | 0x80));
i >>>= 7;
}
writeByte((byte) i);
}
public void writeVLong(long i) {
while ((i & ~0x7FL) != 0L) {
writeByte((byte) ((i & 0x7FL) | 0x80L));
i >>>= 7;
}
writeByte((byte) i);
}
public void writeUTF8(String str) {
writeUTF8(str, 0, str.length());
}
public void writeUTF8(String str, int offset, int length) {
byte[] sbyte = new byte[length * 4];
int end = offset + length;
if (end > str.length())
throw new IllegalArgumentException("offset + length > str.length()");
int count = 0;
int code = 0;
for (int i = 0; i < end; i++) {
code = (int) str.charAt(i);
if (code < 0x80) {
sbyte[count++] = (byte) code;
} else if (code < 0x800) {
sbyte[count++] = (byte) (0xC0 | ((code >> 6) & 0x1F));
sbyte[count++] = (byte) (0x80 | (code & 0x3F));
} else if (code < 0xD800 || code > 0xDFFF) {
sbyte[count++] = (byte) (0xE0 | ((code >> 12) & 0x0F));
sbyte[count++] = (byte) (0x80 | ((code >> 6) & 0x3F));
sbyte[count++] = (byte) (0x80 | (code & 0x3F));
} else {
if (code < 0xDC00 && (i < end - 1)) {
int utf32 = (int) str.charAt(i + 1);
if (utf32 >= 0xDC00 && utf32 <= 0xDFFF) {
utf32 = (code << 10) + utf32 + SURROGATE_OFFSET;
i++;
sbyte[count++] = (byte) (0xF0 | (utf32 >> 18));
sbyte[count++] = (byte) (0x80 | ((utf32 >> 12) & 0x3F));
sbyte[count++] = (byte) (0x80 | ((utf32 >> 6) & 0x3F));
sbyte[count++] = (byte) (0x80 | (utf32 & 0x3F));
continue;
}
}
sbyte[count++] = (byte) 0xEF;
sbyte[count++] = (byte) 0xBF;
sbyte[count++] = (byte) 0xBD;
}
}
writeVInt(count);
write(sbyte, 0, count);
}
public void writeGBK(String s) {
try {
byte[] b = s.getBytes("gbk");
writeVInt(b.length);
write(b, 0, b.length);
} catch (UnsupportedEncodingException e) {
throw new RuntimeException(e);
}
}
public int size() {
return this.offset;
}
public int limit() {
return this.limit;
}
public void clean() {
reset();
}
public void write(byte[] b, int offset, int length) {
int end = offset + length;
if (end > b.length)
throw new IllegalStateException("offset + length > b.length");
for (int i = offset; i < end; i++) {
_write(b[i]);
}
}
protected abstract void _write(byte b);
protected abstract void _allocMore();
}