Package com.aerospike.client.util

Source Code of com.aerospike.client.util.Packer$BufferItem

/*******************************************************************************
* Copyright 2012-2014 by Aerospike.
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to
* deal in the Software without restriction, including without limitation the
* rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
* sell copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
* IN THE SOFTWARE.
******************************************************************************/
package com.aerospike.client.util;

import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.ObjectOutputStream;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;

import com.aerospike.client.AerospikeException;
import com.aerospike.client.Value;
import com.aerospike.client.command.Buffer;
import com.aerospike.client.command.ParticleType;

/**
* Serialize collection objects using MessagePack format specification:
*
* http://wiki.msgpack.org/display/MSGPACK/Format+specification#Formatspecification-int32
*/
public final class Packer {
 
  public static byte[] pack(Value[] val) throws AerospikeException {
    try {
      Packer packer = new Packer();
      packer.packValueArray(val);
      return packer.toByteArray();
    }
    catch (Exception e) {
      throw new AerospikeException.Serialize(e);
    }
  }

  public static byte[] pack(List<?> val) throws AerospikeException {
    try {
      Packer packer = new Packer();
      packer.packList(val);
      return packer.toByteArray();
    }
    catch (Exception e) {
      throw new AerospikeException.Serialize(e);
    }
  }
 
  public static byte[] pack(Map<?,?> val) throws AerospikeException {
    try {
      Packer packer = new Packer();
      packer.packMap(val);
      return packer.toByteArray();
    }
    catch (Exception e) {
      throw new AerospikeException.Serialize(e);
    }
  }
 
  private byte[] buffer;
  private int offset;
  private ArrayList<BufferItem> bufferList;
 
  public Packer() {
    this.buffer = ThreadLocalData.getBuffer();
  }
 
  public void packValueArray(Value[] values) throws IOException {
    packArrayBegin(values.length);
    for (Value value : values) {
      value.pack(this);
    }
  }
 
  public void packList(List<?> list) throws IOException {
    packArrayBegin(list.size());
    for (Object obj : list) {
      packObject(obj);
    }
  }

  private void packArrayBegin(int size) {
        if (size < 16) {
          packByte(0x90 | size);
        }
        else if (size < 65536) {
          packShort(0xdc, size);
        } else {
          packInt(0xdd, size);
        }
    }

  public void packMap(Map<?,?> map) throws IOException {
    packMapBegin(map.size());
    for (Entry<?,?> entry : map.entrySet()) {
      packObject(entry.getKey());
      packObject(entry.getValue());
    }
  }

  private void packMapBegin(int size) {
        if (size < 16) {
          packByte(0x80 | size);
        } else if (size < 65536) {
          packShort(0xde, size);
        } else {
          packInt(0xdf, size);
        }
    }

  public void packBytes(byte[] b) {
      packByteArrayBegin(b.length + 1);
      packByte(ParticleType.BLOB);
      packByteArray(b, 0, b.length);
    }
 
  public void packBytes(byte[] b, int offset, int length) {
      packByteArrayBegin(length + 1);
      packByte(ParticleType.BLOB);
      packByteArray(b, offset, length);
  }
 
  public void packBlob(Object val) throws IOException {
    ByteArrayOutputStream bstream = new ByteArrayOutputStream();
    ObjectOutputStream ostream = new ObjectOutputStream(bstream);
    ostream.writeObject(val);
    ostream.close();
    byte[] bytes = bstream.toByteArray();
   
        packByteArrayBegin(bytes.length + 1);
      packByte(ParticleType.JBLOB);
      packByteArray(bytes, 0, bytes.length);
  }

  private void packByteArrayBegin(int len) {
        if (len < 32) {
            packByte(0xa0 | len);
        } else if (len < 65536) {
          packShort(0xda, len);
        } else {
          packInt(0xdb, len);
        }
    }

  private void packObject(Object obj) throws IOException {
    if (obj == null) {
      packNil();
      return;
    }
   
    if (obj instanceof Value) {
      Value value = (Value) obj;
      value.pack(this);
      return;
    }
   
    if (obj instanceof byte[]) {
      packBytes((byte[]) obj);
      return;
    }
   
    if (obj instanceof String) {
      packString((String) obj);
      return;
    }
   
    if (obj instanceof Integer) {
      packInt((Integer) obj);
      return;
    }
   
    if (obj instanceof Long) {
      packLong((Long) obj);
      return;
    }

    if (obj instanceof List<?>) {
      packList((List<?>) obj);
      return;
    }
   
    if (obj instanceof Map<?,?>) {
      packMap((Map<?,?>) obj);
      return;
    }
   
    packBlob(obj);
  }

  public void packLong(long val) { 
      if (val >= 0L) {    
          if (val < 128L) {
            packByte((int)val);
            return;
          }
         
          if (val < 256L) {          
            packByte(0xcc, (int)val);
            return;
          }
         
          if (val < 65536L) {
            packShort(0xcd, (int)val);
            return;
          }
         
          if (val < 4294967296L) {
            packInt(0xce, (int)val);
            return;
          }
          packLong(0xcf, val);
      }
      else {     
          if (val >= -32) {
            packByte(0xe0 | ((int)val + 32));
            return;
          }
         
          if (val >= Byte.MIN_VALUE) {
                packByte(0xd0, (int)val);
                return;
          }
         
          if (val >= Short.MIN_VALUE) {
                packShort(0xd1, (int)val);
                return;
          }
         
          if (val >= Integer.MIN_VALUE) {
            packInt(0xd2, (int)val);
                return;
          }
          packLong(0xd3, val);
      }
    }
   
    public void packInt(int val) {
      if (val >= 0) {    
          if (val < 128) {
            packByte(val);
            return;
          }
         
          if (val < 256) {          
            packByte(0xcc, val);
            return;
          }
         
          if (val < 65536) {
            packShort(0xcd, val);
            return;
          }
          packInt(0xce, val);
      }
      else {     
          if (val >= -32) {
            packByte(0xe0 | (val + 32));
            return;
          }
         
          if (val >= Byte.MIN_VALUE) {
                packByte(0xd0, val);
                return;
          }
         
          if (val >= Short.MIN_VALUE) {
                packShort(0xd1, val);
                return;
          }     
          packInt(0xd2, val);
      }
    }

  public void packString(String val) {      
        int size = Buffer.estimateSizeUtf8(val) + 1;
        packByteArrayBegin(size);
     
        if (offset + size > buffer.length) {
        resize(size);
      }
      buffer[offset++] = (byte)ParticleType.STRING;
      offset += Buffer.stringToUtf8(val, buffer, offset);
  }

  private void packByteArray(byte[] src, int srcOffset, int srcLength) {
         if (offset + srcLength > buffer.length) {
        resize(srcLength);
      }
     System.arraycopy(src, srcOffset, buffer, offset, srcLength);
    offset += srcLength;
    }

    private void packLong(int type, long val) {
      if (offset + 9 > buffer.length) {
        resize(9);
      }
      buffer[offset++] = (byte)type;
      Buffer.longToBytes(val, buffer, offset);
      offset += 8;
    }

    private void packInt(int type, int val) {
      if (offset + 5 > buffer.length) {
        resize(5);
      }
      buffer[offset++] = (byte)type;
      Buffer.intToBytes(val, buffer, offset);
      offset += 4;
    }
   
    private void packShort(int type, int val) {
      if (offset + 3 > buffer.length) {
        resize(3);
      }
      buffer[offset++] = (byte)type;
      Buffer.shortToBytes(val, buffer, offset);
      offset += 2;
    }

    private void packByte(int type, int val) {
      if (offset + 2 > buffer.length) {
        resize(2);
      }
      buffer[offset++] = (byte)type;
      buffer[offset++] = (byte)val;
    }

    public void packNil() {
      if (offset >= buffer.length) {
        resize(1);
      }
      buffer[offset++] = (byte)0xc0;
    }

    private void packByte(int val) {
      if (offset >= buffer.length) {
        resize(1);
      }
      buffer[offset++] = (byte)val;
    }
   
    private void resize(int size) {
      if (bufferList == null) {
        bufferList = new ArrayList<BufferItem>();
      }
      bufferList.add(new BufferItem(buffer, offset));
     
      if (size < buffer.length) {
        size = buffer.length;
      }
      buffer = new byte[size];       
      offset = 0;
    }
   
    public byte[] toByteArray() {
      if (bufferList != null) {
          int size = offset;         
        for (BufferItem item : bufferList) {
          size += item.length;
        }
         
        byte[] target = new byte[size];
        size = 0;
        for (BufferItem item : bufferList) {
              System.arraycopy(item.buffer, 0, target, size, item.length);
          size += item.length;
        }

        System.arraycopy(buffer, 0, target, size, offset);
          return target;
      }
      else {
          byte[] target = new byte[offset];
          System.arraycopy(buffer, 0, target, 0, offset);
          return target;
      }
  }
   
    private static final class BufferItem {
      private byte[] buffer;
      private int length;
     
      private BufferItem(byte[] buffer, int length) {
        this.buffer = buffer;
        this.length = length;
      }
    }
}
TOP

Related Classes of com.aerospike.client.util.Packer$BufferItem

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.