com.scudata.dw.BufferWriter Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of esproc Show documentation
Show all versions of esproc Show documentation
SPL(Structured Process Language) A programming language specially for structured data computing.
package com.scudata.dw;
import java.io.*;
import java.math.*;
import java.util.Arrays;
import com.scudata.array.IArray;
import com.scudata.common.*;
import com.scudata.dm.BaseRecord;
import com.scudata.dm.DataStruct;
import com.scudata.dm.Sequence;
import com.scudata.dm.SerialBytes;
import com.scudata.util.Variant;
public class BufferWriter {
public static final int MARK0 = 0x00;
public static final int NULL = 0x00;
static final int TRUE = 0x01;
static final int FALSE = 0x02;
public static final int LONG0 = 0x03;
public static final int FLOAT0 = 0x04;
static final int DECIMAL0 = 0x05;
static final int NONE = 0x07;
public static final int MARK1 = 0x10;
public static final int INT16 = 0x10;
public static final int INT32 = 0x11;
public static final int LONG16 = 0x12;
public static final int LONG32 = 0x13;
public static final int LONG64 = 0x14;
public static final int FLOAT16 = 0x15;
public static final int FLOAT32 = 0x16;
public static final int FLOAT64 = 0x17;
public static final int INT16_SEQUENCE = 0x18;
public static final int INT32_SEQUENCE = 0x19;
public static final int LONG64_SEQUENCE = 0x1A;
public static final int FLOAT64_SEQUENCE = 0x1B;
public static final int MARK2 = 0x20;
static final int DECIMAL = 0x20;
public static final int STRING = 0x21;
static final int SEQUENCE = 0x22;
static final int TABLE = 0x23;
static final int BLOB = 0x24;
static final int RECORD = 0x25;
public static final int MARK3 = 0x30;
public static final int DATE16 = 0x30; // 2000??֮???????
public static final int DATE32 = 0x31; // 2000??֮ǰ??????
static final int TIME16 = 0x32;
static final int TIME17 = 0x33;
static final int DATETIME32 = 0x34;
static final int DATETIME33 = 0x35;
static final int DATETIME64 = 0x36;
static final int TIME32 = 0x37;
public static final int DATE24 = 0x38; // 2000??֮???????
public static final int DATE64 = 0x39; // ?????ʾ???˶?????????64λ????
public static final int SERIALBYTES = 0x40; // ?ź?
public static final int REPEAT3 = 0x70;
static final int REPEAT11 = 0x78;
static final int MAX_REPEAT3 = 7 + 2;
static final int MAX_REPEAT11 = 0x7FF + 2;
public static final int INT4 = 0x80;
public static final int INT12 = 0x90;
public static final int HEX4 = 0xA0;
public static final int DIGIT4 = 0xB0;
public static final int STRING4 = 0xC0;
public static final int STRING5 = 0xD0;
public static final int STRING4_ASSIC = 0xE0;//
public static final int STRING5_ASSIC = 0xF0;
public static final int FLOAT_SCALE0 = 0x00;
public static final int FLOAT_SCALE1 = 0x40;
public static final int FLOAT_SCALE2 = 0x80;
public static final int FLOAT_SCALE3 = 0xC0;
public static final double MINFLOAT = 0.000001;
private static final int MAX_DIGIT_LEN = 30;
public static final long BASEDATE; // 1992??֮ǰ?е????ڲ??ܱ?86400000????
static final long BASETIME;
static {
java.util.Calendar calendar = java.util.Calendar.getInstance();
calendar.set(1970, java.util.Calendar.JANUARY, 1, 0, 0, 0);
calendar.set(java.util.Calendar.MILLISECOND, 0);
BASETIME = calendar.getTimeInMillis();
calendar.set(java.util.Calendar.YEAR, 2000);
BASEDATE = calendar.getTimeInMillis();
}
static final int INIT_BUFFER_SIZE = 1024 * 64;
private byte []buf; // д??????
private int count = 0;
private StructManager structManager;
private Object repeatValue;
private int repeatCount = 0;
public BufferWriter(StructManager structManager) {
buf = new byte[INIT_BUFFER_SIZE];
this.structManager = structManager;
}
public BufferWriter(StructManager structManager, byte []buffer) {
buf = buffer;
this.structManager = structManager;
}
// ????д?????ؽ???ֽ?????
public byte[] finish() throws IOException {
if (repeatCount > 0) {
writeRepeat();
}
int len = count;
count = 0;
return Arrays.copyOf(buf, len);
}
private void enlargeBuffer() {
buf = Arrays.copyOf(buf, buf.length << 1);
}
private void enlargeBuffer(int newLen) {
buf = Arrays.copyOf(buf, Math.max(buf.length << 1, newLen));
}
public void write(int b) throws IOException {
if (count >= buf.length) {
enlargeBuffer();
}
buf[count++] = (byte)b;
}
public void write(byte b[]) throws IOException {
write(b, 0, b.length);
}
public void write(byte b[], int off, int len) throws IOException {
if (len > buf.length - count) {
enlargeBuffer(count + len);
}
System.arraycopy(b, off, buf, count, len);
count += len;
}
public void writeByte(int v) throws IOException {
if (count >= buf.length) {
enlargeBuffer();
}
buf[count++] = (byte)v;
}
public void writeBoolean(boolean v) throws IOException {
if (count >= buf.length) {
enlargeBuffer();
}
buf[count++] = v ? (byte)1 : (byte)0;
}
public void writeShort(int v) throws IOException {
write((v >>> 8) & 0xFF);
write((v >>> 0) & 0xFF);
}
public void writeChar(int v) throws IOException {
write((v >>> 8) & 0xFF);
write((v >>> 0) & 0xFF);
}
public void writeFloat(float v) throws IOException {
writeInt(Float.floatToIntBits(v));
}
public void writeBytes(String s) throws IOException {
for (char c : s.toCharArray()) {
write(c);
}
}
public void writeChars(String s) throws IOException {
for (char c : s.toCharArray()) {
writeChar(c);
}
}
public void writeUTF(String str) throws IOException {
writeString(str);
}
public void writeBytes(byte[] v) throws IOException {
if (v == null) {
writeInt(-1);
} else {
int len = v.length;
writeInt(len);
write(v, 0, len);
}
}
public void writeStrings(String[] strs) throws IOException {
if (strs == null) {
writeInt(-1);
} else {
writeInt(strs.length);
for (String str : strs) {
writeString(str);
}
}
}
// ????С?ڵ???32?????ִ?
private boolean isDigit(char []charr, int len) {
if (len > MAX_DIGIT_LEN) return false;
for (int i = 0; i < len; ++i) {
if (charr[i] < '0' || charr[i] > '9') return false;
}
return true;
}
// ????С?ڵ???32?????ִ?
private void writeDigit(char []charr, int len) throws IOException {
if (buf.length - count < MAX_DIGIT_LEN) {
enlargeBuffer();
}
byte []writeBuffer = this.buf;
int seq = count;
if (len % 2 == 0) {
writeBuffer[seq++] = (byte)(DIGIT4 | (len / 2));
for (int i = 0; i < len; ) {
int d1 = charr[i++] - '0';
int d2 = charr[i++] - '0';
writeBuffer[seq++] = (byte)((d1 << 4) | d2);
}
} else {
writeBuffer[seq++] = (byte)(DIGIT4 | (len / 2 + 1));
len--;
for (int i = 0; i < len; ) {
int d1 = charr[i++] - '0';
int d2 = charr[i++] - '0';
writeBuffer[seq++] = (byte)((d1 << 4) | d2);
}
writeBuffer[seq++] = (byte)((charr[len] - '0' << 4) | 0x0F);
}
count = seq;
}
public void writeString(String str) throws IOException {
if (str == null) {
write(NULL);
return;
}
int strlen = str.length();
if (strlen == 0) {
write(STRING4);
return;
} else if (strlen == 1) {
char c = str.charAt(0);
if (c >= '0' && c <= '9') {
write(HEX4 | (c - '0'));
return;
} else if (c >= 'A' && c <= 'F') {
write(HEX4 | (c - 'A' + 10));
return;
}
}
char[] charr = new char[strlen];
str.getChars(0, strlen, charr, 0);
if (isDigit(charr, strlen)) {
writeDigit(charr, strlen);
return;
}
int utflen = 0;
int c, count = 0;
for (int i = 0; i < strlen; i++) {
c = charr[i];
if ((c >= 0x0001) && (c <= 0x007F)) {
utflen++;
} else if (c > 0x07FF) {
utflen += 3;
} else {
utflen += 2;
}
}
byte[] bytearr = new byte[utflen];
boolean isAssicString = true;//char:01-7F
for (int i = 0; i < strlen; i++) {
c = charr[i];
if ((c >= 0x0001) && (c <= 0x007F)) {
bytearr[count++] = (byte)c;
} else if (c > 0x07FF) {
bytearr[count++] = (byte)(0xE0 | ((c >> 12) & 0x0F));
bytearr[count++] = (byte)(0x80 | ((c >> 6) & 0x3F));
bytearr[count++] = (byte)(0x80 | ((c >> 0) & 0x3F));
isAssicString = false;
} else {
bytearr[count++] = (byte)(0xC0 | ((c >> 6) & 0x1F));
bytearr[count++] = (byte)(0x80 | ((c >> 0) & 0x3F));
isAssicString = false;
}
}
if (isAssicString) {
if (utflen <= 0x1F) {
write(STRING4_ASSIC | utflen);
write(bytearr);
} else {
write(STRING);
writeInt(utflen);
write(bytearr);
}
} else {
if (utflen <= 0x1F) {
write(STRING4 | utflen);
write(bytearr);
} else {
write(STRING);
writeInt(utflen);
write(bytearr);
}
}
}
private void writeDecimal(BigDecimal bd) throws IOException {
byte []bts = bd.unscaledValue().toByteArray();
int scale = bd.scale();
if (scale == 0 && bts[0] == 0 && bts.length == 1) {
write(DECIMAL0);
} else {
write(DECIMAL);
write(scale);
write(bts.length);
write(bts);
}
}
private void writeDecimal(BigInteger bi) throws IOException {
byte []bts = bi.toByteArray();
if (bts[0] == 0 && bts.length == 1) {
write(DECIMAL0);
} else {
write(DECIMAL);
write(0);
write(bts.length);
write(bts);
}
}
private void writeDouble(double d, long v, int scale) throws IOException {
if (v <= 0x3FFF) {
int n = (int)v;
write(FLOAT16);
write((n >>> 8) | scale);
write(n & 0xFF);
} else if (v <= 0x3FFFFFFF) {
int n = (int)v;
write(FLOAT32);
write((n >>> 24) | scale);
write((n >>> 16) & 0xFF);
write((n >>> 8) & 0xFF);
write(n & 0xFF);
} else {
writeDouble64(d);
}
}
private void writeDouble64(double d) throws IOException {
write(FLOAT64);
long v = Double.doubleToLongBits(d);
writeLong64(v);
}
public void writeDouble(double d) throws IOException {
if (d > 0.0 && d <= 0x3FFFFFFF) {
double v = Math.ceil(d);
if (v - d < MINFLOAT) {
long l = (long)v;
if (l % 100 == 0) {
writeDouble(d, l / 100, 0xC0);
} else {
writeDouble(d, (long)v, 0x00);
}
} else {
double d1 = d * 100;
v = Math.ceil(d1);
if (v - d1 < MINFLOAT) {
writeDouble(d, (long)v, 0x40);
} else {
d1 = d * 10000;
v = Math.ceil(d1);
if (v - d1 < MINFLOAT) {
writeDouble(d, (long)v, 0x80);
} else {
writeDouble64(d);
}
}
}
} else if (d == 0.0) {
write(FLOAT0);
} else {
writeDouble64(d);
}
}
public void writeLong(long v) throws IOException {
if (v == 0L) {
write(LONG0);
} else if (v >= Integer.MIN_VALUE && v <= Integer.MAX_VALUE) {
int n = (int)v;
if (n >= 0) {
if (n <= 0xFFFF) {
write(LONG16);
write(n >>> 8);
write(n & 0xFF);
} else {
write(LONG32);
write(n >>> 24);
write((n >>> 16) & 0xFF);
write((n >>> 8) & 0xFF);
write(n & 0xFF);
}
} else {
write(LONG32);
write(n >>> 24);
write((n >>> 16) & 0xFF);
write((n >>> 8) & 0xFF);
write(n & 0xFF);
}
} else {
write(LONG64);
writeLong64(v);
}
}
public void writeInt32(int n) throws IOException {
write(n >>> 24);
write((n >>> 16) & 0xFF);
write((n >>> 8) & 0xFF);
write(n & 0xFF);
}
// 5?ֽڱ?ʾlong?????ļ???СҪ??1T
public void writeLong40(long v) throws IOException {
if (buf.length - count < 5) {
enlargeBuffer();
}
byte []writeBuffer = this.buf;
int seq = count;
writeBuffer[seq++] = (byte)(v >>> 32);
writeBuffer[seq++] = (byte)(v >>> 24);
writeBuffer[seq++] = (byte)(v >>> 16);
writeBuffer[seq++] = (byte)(v >>> 8);
writeBuffer[seq++] = (byte)(v >>> 0);
count = seq;
}
/* 6?ֽڱ?ʾlong?????ļ???СҪ??256T???????????ھ?????ļ???λ???ݵı??? */
public void writeLong48(long v) throws IOException {
if (buf.length - count < 6) {
enlargeBuffer();
}
byte []writeBuffer = this.buf;
int seq = count;
writeBuffer[seq++] = (byte)(v >>> 40);
writeBuffer[seq++] = (byte)(v >>> 32);
writeBuffer[seq++] = (byte)(v >>> 24);
writeBuffer[seq++] = (byte)(v >>> 16);
writeBuffer[seq++] = (byte)(v >>> 8);
writeBuffer[seq++] = (byte)(v >>> 0);
count = seq;
}
public void writeLong64(long v) throws IOException {
if (buf.length - count < 8) {
enlargeBuffer();
}
byte []writeBuffer = this.buf;
int seq = count;
writeBuffer[seq++] = (byte)(v >>> 56);
writeBuffer[seq++] = (byte)(v >>> 48);
writeBuffer[seq++] = (byte)(v >>> 40);
writeBuffer[seq++] = (byte)(v >>> 32);
writeBuffer[seq++] = (byte)(v >>> 24);
writeBuffer[seq++] = (byte)(v >>> 16);
writeBuffer[seq++] = (byte)(v >>> 8);
writeBuffer[seq++] = (byte)(v >>> 0);
count = seq;
}
public void writeInt(int n) throws IOException {
if (n >= 0) {
if (n <= 0x0F) {
write(INT4 | n);
} else if (n <= 0x0FFF) {
write(INT12 | (n >>> 8));
write(n & 0xFF);
} else if (n <= 0xFFFF) {
write(INT16);
write(n >>> 8);
write(n & 0xFF);
} else {
write(INT32);
write(n >>> 24);
write((n >>> 16) & 0xFF);
write((n >>> 8) & 0xFF);
write(n & 0xFF);
}
} else {
write(INT32);
write(n >>> 24);
write((n >>> 16) & 0xFF);
write((n >>> 8) & 0xFF);
write(n & 0xFF);
}
}
private void writeTimestamp(java.util.Date dt) throws IOException {
long t = dt.getTime();
if (t % 1000 == 0) {
long v = t / 1000;
if (v < 0) {
v = -v;
if (v <= 0xFFFFFFFFL) {
write(DATETIME33);
write((int)(v >>> 24));
write((int)(v >>> 16));
write((int)(v >>> 8));
write((int)(v >>> 0));
return;
}
} else {
if (v <= 0xFFFFFFFFL) {
write(DATETIME32);
write((int)(v >>> 24));
write((int)(v >>> 16));
write((int)(v >>> 8));
write((int)(v >>> 0));
return;
}
}
}
write(DATETIME64);
writeLong64(t);
}
private void writeDate(java.sql.Date date) throws IOException {
long v = date.getTime();
if (v >= BASEDATE) {
// ??ȷ????
int d = (int)((v - BASEDATE) / 86400000);
if (d > 0xFFFF) {
if (d > 0xFFFFFF) {
write(DATE64);
writeLong64(v);
} else {
write(DATE24);
write((d >>> 16));
write((d >>> 8) & 0xFF);
write(d & 0xFF);
}
} else {
write(DATE16);
write(d >>> 8);
write(d & 0xFF);
}
} else {
// ??ȷ????
long d = (BASEDATE - v) / 1000;
if (d > 0xFFFFFFFFL) {
write(DATE64);
writeLong64(v);
} else {
write(DATE32);
writeInt32((int)d);
}
}
}
private void writeTime(java.sql.Time time) throws IOException {
int t = (int)((time.getTime() - BASETIME) % 86400000);
if (t < 0) t += 86400000;
if (t % 1000 == 0) {
t /= 1000;
if (t > 0xFFFF) {
write(TIME17);
write((t >>> 8) & 0xFF);
write(t & 0xFF);
} else {
write(TIME16);
write(t >>> 8);
write(t & 0xFF);
}
} else {
write(TIME32);
write(t >>> 24);
write((t >>> 16) & 0xFF);
write((t >>> 8) & 0xFF);
write(t & 0xFF);
}
}
private void writeRecord(BaseRecord r) throws IOException {
DataStruct ds = r.dataStruct();
int fcount = ds.getFieldCount();
int id = structManager.getDataStructID(ds);
Object []vals = r.getFieldValues();
write(RECORD);
writeInt(id);
for (int f = 0; f < fcount; ++f) {
innerWriteObject(vals[f]);
}
}
private void writeSequence(Sequence seq) throws IOException {
IArray mems = seq.getMems();
int len = mems.size();
DataStruct ds = seq.dataStruct();
if (ds == null) {
int type = DataBlockType.getSequenceDataType(seq, 1, len);
if (type != DataBlockType.NULL && len <= 0xFFFF) {
//?Ǵ?????????
if (type == DataBlockType.INT16) {
write(INT16_SEQUENCE);
write(len >>> 8);
write(len & 0xFF);
for (int i = 1; i <= len; ++i) {
int value = (Integer)mems.get(i);
write(value >>> 8);
write(value & 0xFF);
}
} else if (type == DataBlockType.INT32) {
write(INT32_SEQUENCE);
write(len >>> 8);
write(len & 0xFF);
for (int i = 1; i <= len; ++i) {
int value = (Integer)mems.get(i);
writeInt32(value);
}
} else if (type == DataBlockType.LONG64) {
write(LONG64_SEQUENCE);
write(len >>> 8);
write(len & 0xFF);
for (int i = 1; i <= len; ++i) {
long value = (Long)mems.get(i);
writeLong64(value);
}
} else if (type == DataBlockType.DOUBLE64) {
write(FLOAT64_SEQUENCE);
write(len >>> 8);
write(len & 0xFF);
for (int i = 1; i <= len; ++i) {
double value = (Double)mems.get(i);
long v = Double.doubleToLongBits(value);
writeLong64(v);
}
} else {
//??ͨ????
write(SEQUENCE);
writeInt(len);
for (int i = 1; i <= len; ++i) {
innerWriteObject(mems.get(i));
}
}
} else {
//??ͨ????
write(SEQUENCE);
writeInt(len);
for (int i = 1; i <= len; ++i) {
innerWriteObject(mems.get(i));
}
}
} else {
int fcount = ds.getFieldCount();
int id = structManager.getDataStructID(ds);
write(TABLE);
writeInt(id);
writeInt(len);
for (int i = 1; i <= len; ++i) {
BaseRecord r = (BaseRecord)mems.get(i);
Object []vals = r.getFieldValues();
for (int f = 0; f < fcount; ++f) {
innerWriteObject(vals[f]);
}
}
}
}
private void writeRepeat() throws IOException {
int count = repeatCount;
if (count > 1) {
if (count <= MAX_REPEAT3) {
write(REPEAT3 | (count - 2));
} else {
count -= 2;
write(REPEAT11 | (count >> 8));
write(count & 0xFF);
}
}
repeatCount = 0;
innerWriteObject(repeatValue);
}
private void innerWriteObject(Object obj) throws IOException {
if (obj == null) {
write(NULL);
} else if (obj instanceof String) {
writeString((String)obj);
} else if (obj instanceof Integer) {
writeInt(((Number)obj).intValue());
} else if (obj instanceof Double) {
writeDouble(((Number)obj).doubleValue());
} else if (obj instanceof BigDecimal) {
writeDecimal((BigDecimal)obj);
} else if (obj instanceof Long) {
writeLong(((Number)obj).longValue());
} else if (obj instanceof java.sql.Date) {
writeDate((java.sql.Date)obj);
} else if (obj instanceof java.sql.Time) {
writeTime((java.sql.Time)obj);
} else if (obj instanceof java.util.Date) {
writeTimestamp((java.util.Date)obj);
} else if (obj instanceof Boolean) {
if (((Boolean)obj).booleanValue()) {
write(TRUE);
} else {
write(FALSE);
}
} else if (obj instanceof BigInteger) {
writeDecimal((BigInteger)obj);
} else if (obj instanceof Float) {
writeDouble(((Number)obj).doubleValue());
} else if (obj instanceof Number) { // Byte Short
writeInt(((Number)obj).intValue());
} else if (obj instanceof Sequence) {
writeSequence((Sequence)obj);
} else if (obj instanceof BaseRecord) {
writeRecord((BaseRecord)obj);
} else if (obj instanceof byte[]) {
write(BLOB);
writeBytes((byte[])obj);
} else if (obj instanceof SerialBytes) {
SerialBytes sb = (SerialBytes)obj;
// ???ȹ̶???16
write(SERIALBYTES);
writeLong64(sb.getValue1());
writeLong64(sb.getValue2());
} else {
throw new RQException("error type: " + obj.getClass().getName());
}
}
public void writeNone() throws IOException {
if (repeatCount > 0) {
writeRepeat();
}
write(NONE);
}
/**
* д????˷??????ж??Ƿ????һ??ֵ?ظ??????ܺ???????write?????????ã????????????writeObject?????????????????Ҫ?ȵ???flush????
* @param obj
* @throws IOException
*/
public void writeObject(Object obj) throws IOException {
if (repeatCount > 0) {
// ?????????жϣ???ֹ0??0.0?ȵ?????һ??????
if (Variant.isEquals(repeatValue, obj) &&
(obj == null || obj.getClass() == repeatValue.getClass())) {
repeatCount++;
if (repeatCount == MAX_REPEAT11) {
writeRepeat();
}
} else {
writeRepeat();
repeatCount = 1;
repeatValue = obj;
}
} else {
repeatValue = obj;
repeatCount = 1;
}
}
public void flush() throws IOException {
if (repeatCount > 0) {
writeRepeat();
}
}
//С?˷?ʽд??Short
public void writeLittleEndianShort(int v) throws IOException {
write((v >>> 0) & 0xFF);
write((v >>> 8) & 0xFF);
}
//С?˷?ʽд??int
public void writeLittleEndianInt(int n) throws IOException {
write(n & 0xFF);
write((n >>> 8) & 0xFF);
write((n >>> 16) & 0xFF);
write(n >>> 24);
}
//С?˷?ʽд??Long
public void writeLittleEndianLong(long v) throws IOException {
if (buf.length - count < 8) {
enlargeBuffer();
}
byte []writeBuffer = this.buf;
int seq = count;
writeBuffer[seq++] = (byte)(v >>> 0);
writeBuffer[seq++] = (byte)(v >>> 8);
writeBuffer[seq++] = (byte)(v >>> 16);
writeBuffer[seq++] = (byte)(v >>> 24);
writeBuffer[seq++] = (byte)(v >>> 32);
writeBuffer[seq++] = (byte)(v >>> 40);
writeBuffer[seq++] = (byte)(v >>> 48);
writeBuffer[seq++] = (byte)(v >>> 56);
count = seq;
}
public void reset() {
repeatValue = null;
repeatCount = 0;
count = 0;
}
}
© 2015 - 2024 Weber Informatics LLC | Privacy Policy