/*
* Copyright amoeba.meidusa.com
*
* This program is free software; you can redistribute it and/or modify it under the terms of
* the GNU AFFERO GENERAL PUBLIC LICENSE as published by the Free Software Foundation; either version 3 of the License,
* or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
* See the GNU AFFERO GENERAL PUBLIC LICENSE for more details.
* You should have received a copy of the GNU AFFERO GENERAL PUBLIC LICENSE along with this program;
* if not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
package com.meidusa.amoeba.mongodb.packet;
import java.io.IOException;
import java.io.UnsupportedEncodingException;
import org.bson.BSONDecoder;
import org.bson.BSONEncoder;
import org.bson.BSONObject;
import org.bson.io.BasicOutputBuffer;
import com.meidusa.amoeba.net.packet.AbstractPacketBuffer;
/**
*
* @author Struct
*
*/
public class MongodbPacketBuffer extends AbstractPacketBuffer {
static ThreadLocal<BSONDecoder> DECODER = new ThreadLocal<BSONDecoder>(){
public BSONDecoder initialValue(){
return new BSONDecoder();
}
};
static ThreadLocal<BSONEncoder> ENCODER = new ThreadLocal<BSONEncoder>(){
public BSONEncoder initialValue(){
return new BSONEncoder();
}
};
public MongodbPacketBuffer(byte[] buf) {
super(buf);
}
public MongodbPacketBuffer(int size) {
super(size);
}
public int readInt() {
byte[] b = this.buffer; // a little bit optimization
return (b[this.position++] & 0xff)
| ((b[this.position++] & 0xff) << 8)
| ((b[this.position++] & 0xff) << 16)
| ((b[this.position++] & 0xff) << 24);
}
public void writeInt(int x) {
ensureCapacity(4);
writeByte((byte) (0xFF & x ));
writeByte((byte) (0xFF & (x >> 8)));
writeByte((byte) (0xFF & (x >> 16)));
writeByte((byte) (0xFF & (x >> 24)));
}
public void writeInt(int pos, int x) {
final int save = getPosition();
setPosition(pos);
writeInt(x);
setPosition(save);
}
public long readLong() {
byte[] b = this.buffer; // a little bit optimization
return (b[this.position++] & 0xffL)
| ((b[this.position++] & 0xffL) << 8)
| ((b[this.position++] & 0xffL) << 16)
| ((b[this.position++] & 0xffL) << 24)
| ((b[this.position++] & 0xffL) << 32)
| ((b[this.position++] & 0xffL) << 40)
| ((b[this.position++] & 0xffL) << 48)
| ((b[this.position++] & 0xffL) << 56);
}
public void writeLong(long x) {
ensureCapacity(8);
writeByte((byte) (0xFFL & (x >> 0)));
writeByte((byte) (0xFFL & (x >> 8)));
writeByte((byte) (0xFFL & (x >> 16)));
writeByte((byte) (0xFFL & (x >> 24)));
writeByte((byte) (0xFFL & (x >> 32)));
writeByte((byte) (0xFFL & (x >> 40)));
writeByte((byte) (0xFFL & (x >> 48)));
writeByte((byte) (0xFFL & (x >> 56)));
}
public void writeCString(String content) throws UnsupportedEncodingException{
byte[] ab = content.getBytes("utf-8");
ensureCapacity(ab.length+1);
writeBytes(ab, 0, ab.length);
writeByte((byte)0);
}
public String readCString(){
byte[] b = this.buffer; // a little bit optimization
int save = this.position;
while(this.position<b.length){
if(b[position++] == (byte)0){
try {
return new String(b,save,this.position-save-1,"UTF-8");
} catch (UnsupportedEncodingException e) {
return new String(b,save,this.position-save-1);
}
}else{
continue;
}
}
return null;
}
public void writeDouble(double x) {
writeLong(Double.doubleToRawLongBits(x));
}
public double readDouble() {
long value = readLong();
return Double.longBitsToDouble(value);
}
public BSONObject readBSONObject(){
try {
return DECODER.get().readObject(this.asInputStream());
} catch (IOException e) {
e.printStackTrace();
}
return null;
}
public void writeBSONObject(BSONObject object){
BasicOutputBuffer buffer = new BasicOutputBuffer();
ENCODER.get().set(buffer);
ENCODER.get().encode(object);
try {
buffer.pipe(this.asOutputStream());
} catch (IOException e) {
e.printStackTrace();
}
}
static int POSITION = 12;
public static int getOPMessageType(byte[] message){
byte[] b = message; // a little bit optimization
return (b[POSITION] & 0xff) | ((b[POSITION+1] & 0xff) << 8)
| ((b[POSITION+2] & 0xff) << 16)
| ((b[POSITION+3] & 0xff) << 24);
}
public static int getRequestId(byte[] message){
byte[] b = message; // a little bit optimization
return (b[4] & 0xff) | ((b[4+1] & 0xff) << 8)
| ((b[4+2] & 0xff) << 16)
| ((b[4+3] & 0xff) << 24);
}
public static int getResponseId(byte[] message){
byte[] b = message; // a little bit optimization
return (b[8] & 0xff) | ((b[8+1] & 0xff) << 8)
| ((b[8+2] & 0xff) << 16)
| ((b[8+3] & 0xff) << 24);
}
}