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

com.caucho.v5.h3.io.InRawH3Impl Maven / Gradle / Ivy

There is a newer version: 1.0.1
Show newest version
/*
 * Copyright (c) 2001-2016 Caucho Technology, Inc.  All rights reserved.
 * 
 *    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.
 *
 * @author Scott Ferguson
 */

package com.caucho.v5.h3.io;

import java.io.IOException;
import java.io.InputStream;
import java.util.Objects;

import com.caucho.v5.h3.query.PathH3Amp;
import com.caucho.v5.io.TempBuffer;
import com.caucho.v5.util.L10N;

/**
 * H3 output interface
 */
public class InRawH3Impl implements InRawH3
{
  private static final L10N L = new L10N(InRawH3Impl.class);
  
  private InputStream _is;
  
  private byte []_buffer;
  private int _offset;
  private int _length;
  
  private char []_charBuffer = new char[256];

  private TempBuffer _tBuf;
  
  public InRawH3Impl(InputStream is)
  {
    Objects.requireNonNull(is);
    _is = is;
    
    _tBuf = TempBuffer.allocate();
    _buffer = _tBuf.buffer();
    _length = 0;
  }

  @Override
  public void readNull()
  {
    int ch;
    
    switch ((ch = read())) {
    case ConstH3.NULL:
      return;
      
    default:
      throw error(L.l("Unexpected opcode 0x{0} while reading null",
                      Integer.toHexString(ch)));
    }
  }

  @Override
  public boolean readBoolean()
  {
    int ch;
    
    switch ((ch = read())) {
    case ConstH3.FALSE:
      return Boolean.FALSE;
      
    case ConstH3.TRUE:
      return Boolean.TRUE;
      
    default:
      throw error(L.l("Unexpected opcode 0x{0} while reading boolean",
                      Integer.toHexString(ch)));
    }
  }

  @Override
  public long readLong()
  {
    int ch = read();
    
    if ((ch & ConstH3.INTEGER_OPMASK) != ConstH3.INTEGER) {
      throw error(L.l("unexpected end of file while reading long"));
    }
    
    return readLong(ch);
  }
  
  private long readLong(int ch)
  {
    ch -= ConstH3.INTEGER;
    
    boolean sign = (ch & 1) == 0;
    
    if (ch <= ConstH3.INTEGER_MASK) {
      return sign ? (ch >> 1) : -(ch >> 1) - 1;
    }
    
    long value = (ch & ConstH3.INTEGER_MASK) >> 1;
    
    int shift = ConstH3.INTEGER_BITS - 2;
    
    value = readLong(value, shift);
    
    return sign ? value : -value - 1; 
  }
  
  @Override
  public long readUnsigned()
  {
    return readLong(0, 0);
  }
  
  @Override
  public float readFloat()
  {
    return (float) readDouble();
  }
  
  @Override
  public double readDouble()
  {
    int ch = read();
    
    switch (ch) {
    case 0xf3:
      return readDoubleData();
    
    case 0xf4:
      return readFloatData();
      
    default:
      throw new UnsupportedOperationException(Long.toHexString(ch));
    }
  }

  @Override
  public String readString()
  {
    int ch = read();
    
    switch (ch) {
    case 0x80: case 0x81: case 0x82: case 0x83: 
    case 0x84: case 0x85: case 0x86: case 0x87:
    case 0x88: case 0x89: case 0x8a: case 0x8b:
    case 0x8c: case 0x8d: case 0x8e: case 0x8f:
      
    case 0x90: case 0x91: case 0x92: case 0x93: 
    case 0x94: case 0x95: case 0x96: case 0x97:
    case 0x98: case 0x99: case 0x9a: case 0x9b:
    case 0x9c: case 0x9d: case 0x9e: case 0x9f:
      return readString(ch - 0x80);
      
    case 0xa0: case 0xa1: case 0xa2: case 0xa3: 
    case 0xa4: case 0xa5: case 0xa6: case 0xa7:
    case 0xa8: case 0xa9: case 0xaa: case 0xab:
    case 0xac: case 0xad: case 0xae: case 0xaf:
      
    case 0xb0: case 0xb1: case 0xb2: case 0xb3: 
    case 0xb4: case 0xb5: case 0xb6: case 0xb7:
    case 0xb8: case 0xb9: case 0xba: case 0xbb:
    case 0xbc: case 0xbd: case 0xbe: case 0xbf:
      return readString((int) readLong(ch - 0xa0, 5));
      
    default:
      throw error(L.l("Unexpected opcode 0x{0} while reading string",
                      Integer.toHexString(ch)));
    }
  }

  @Override
  public byte []readBinary()
  {
    int ch = read();
    
    switch (ch) {
    case 0xc0: case 0xc1: case 0xc2: case 0xc3: 
    case 0xc4: case 0xc5: case 0xc6: case 0xc7:
    {
      byte []data = new byte[ch - 0xc0];
      readBinaryData(data, 0, data.length);
      return data;
    }
    
    case 0xc8: case 0xc9: case 0xca: case 0xcb:
    case 0xcc: case 0xcd: case 0xce: case 0xcf:
    {
      byte []data = new byte[(int) readLong(ch - 0xc8, 3)];
      readBinaryData(data, 0, data.length);
      return data;
    }
      
    default:
      throw error(L.l("Unexpected opcode 0x{0} while reading binary",
                      Integer.toHexString(ch)));
    }
  }

  @Override
  public Object readObject(InH3Amp inAmp)
  {
    int ch = read();
    
    switch (ch) {
    case 0x00: case 0x01: case 0x02: case 0x03: 
    case 0x04: case 0x05: case 0x06: case 0x07:
    case 0x08: case 0x09: case 0x0a: case 0x0b:
    case 0x0c: case 0x0d: case 0x0e: case 0x0f:
      
    case 0x10: case 0x11: case 0x12: case 0x13: 
    case 0x14: case 0x15: case 0x16: case 0x17:
    case 0x18: case 0x19: case 0x1a: case 0x1b:
    case 0x1c: case 0x1d: case 0x1e: case 0x1f:
      
    case 0x20: case 0x21: case 0x22: case 0x23: 
    case 0x24: case 0x25: case 0x26: case 0x27:
    case 0x28: case 0x29: case 0x2a: case 0x2b:
    case 0x2c: case 0x2d: case 0x2e: case 0x2f:
      
    case 0x30: case 0x31: case 0x32: case 0x33: 
    case 0x34: case 0x35: case 0x36: case 0x37:
    case 0x38: case 0x39: case 0x3a: case 0x3b:
    case 0x3c: case 0x3d: case 0x3e: case 0x3f:
      
    case 0x40: case 0x41: case 0x42: case 0x43: 
    case 0x44: case 0x45: case 0x46: case 0x47:
    case 0x48: case 0x49: case 0x4a: case 0x4b:
    case 0x4c: case 0x4d: case 0x4e: case 0x4f:
      
    case 0x50: case 0x51: case 0x52: case 0x53: 
    case 0x54: case 0x55: case 0x56: case 0x57:
    case 0x58: case 0x59: case 0x5a: case 0x5b:
    case 0x5c: case 0x5d: case 0x5e: case 0x5f:
      
    case 0x60: case 0x61: case 0x62: case 0x63: 
    case 0x64: case 0x65: case 0x66: case 0x67:
    case 0x68: case 0x69: case 0x6a: case 0x6b:
    case 0x6c: case 0x6d: case 0x6e: case 0x6f:
      
    case 0x70: case 0x71: case 0x72: case 0x73: 
    case 0x74: case 0x75: case 0x76: case 0x77:
    case 0x78: case 0x79: case 0x7a: case 0x7b:
    case 0x7c: case 0x7d: case 0x7e: case 0x7f:
      return readLong(ch);
      
    case 0x80: case 0x81: case 0x82: case 0x83: 
    case 0x84: case 0x85: case 0x86: case 0x87:
    case 0x88: case 0x89: case 0x8a: case 0x8b:
    case 0x8c: case 0x8d: case 0x8e: case 0x8f:
      
    case 0x90: case 0x91: case 0x92: case 0x93: 
    case 0x94: case 0x95: case 0x96: case 0x97:
    case 0x98: case 0x99: case 0x9a: case 0x9b:
    case 0x9c: case 0x9d: case 0x9e: case 0x9f:
      return readString(ch - 0x80);
      
    case 0xa0: case 0xa1: case 0xa2: case 0xa3: 
    case 0xa4: case 0xa5: case 0xa6: case 0xa7:
    case 0xa8: case 0xa9: case 0xaa: case 0xab:
    case 0xac: case 0xad: case 0xae: case 0xaf:
      
    case 0xb0: case 0xb1: case 0xb2: case 0xb3: 
    case 0xb4: case 0xb5: case 0xb6: case 0xb7:
    case 0xb8: case 0xb9: case 0xba: case 0xbb:
    case 0xbc: case 0xbd: case 0xbe: case 0xbf:
      return readString((int) readLong(ch - 0xa0, 5));
      
    case 0xc0: case 0xc1: case 0xc2: case 0xc3: 
    case 0xc4: case 0xc5: case 0xc6: case 0xc7:
    {
      byte []data = new byte[ch - 0xc0];
      readBinaryData(data, 0, data.length);
      return data;
    }
    
    case 0xc8: case 0xc9: case 0xca: case 0xcb:
    case 0xcc: case 0xcd: case 0xce: case 0xcf:
    {
      byte []data = new byte[(int) readLong(ch - 0xc8, 3)];
      readBinaryData(data, 0, data.length);
      return data;
    }
      
    case 0xd0:
      readDefinition(inAmp);
      
      return readObject(inAmp);
      
    case 0xd1: case 0xd2: case 0xd3: 
    case 0xd4: case 0xd5: case 0xd6: case 0xd7:
    case 0xd8: case 0xd9: case 0xda: case 0xdb:
    case 0xdc: case 0xdd: case 0xde: case 0xdf:
    {
      int id = ch - 0xd0;
      
      return inAmp.serializer(id).readObject(this, inAmp);
    }
      
    case 0xe0: case 0xe1: case 0xe2: case 0xe3: 
    case 0xe4: case 0xe5: case 0xe6: case 0xe7:
    case 0xe8: case 0xe9: case 0xea: case 0xeb:
    case 0xec: case 0xed: case 0xee: case 0xef:
    {
      int id = (int) readLong(ch - 0xe0, 4);
      
      return inAmp.serializer(id).readObject(this, inAmp);
    }
    
    case 0xf0:
      return null;
      
    case 0xf1:
      return Boolean.FALSE;
      
    case 0xf2:
      return Boolean.TRUE;
      
    case 0xf3:
      return readDoubleData();
      
    case 0xf4:
      return readFloatData();
      
    default:
      throw error(L.l("Unexpected opcode 0x{0} while reading object",
                      Integer.toHexString(ch)));
    }
  }
  
  private float readFloatData()
  {
    int value = ((read() << 24)
        | (read() << 16)
        | (read() << 8)
        | (read()));
    
    return Float.intBitsToFloat(value);
  }
  
  private double readDoubleData()
  {
    long value = (((long) read() << 56)
        | ((long) read() << 48)
        | ((long) read() << 40)
        | ((long) read() << 32)
        | (read() << 24)
        | (read() << 16)
        | (read() << 8)
        | (read()));
    
    return Double.longBitsToDouble(value);
  }
  
  public boolean wasNull()
  {
    return _offset > 0 && _buffer[_offset - 1] == ConstH3.NULL;
  }

  /**
   * Scan for a query.
   */
  @Override
  public void scan(InH3Amp in, PathH3Amp path, Object[] values)
  {
    int ch = read();
    
    switch (ch) {
    case 0xd0:
      readDefinition(in);
      scan(in, path, values);
      return;
      
    case 0xd1: case 0xd2: case 0xd3: 
    case 0xd4: case 0xd5: case 0xd6: case 0xd7:
    case 0xd8: case 0xd9: case 0xda: case 0xdb:
    case 0xdc: case 0xdd: case 0xde: case 0xdf:
    {
      int id = ch - 0xd0;

      in.serializer(id).scan(this, path, in, values);
      return;
    }
      
    case 0xe0: case 0xe1: case 0xe2: case 0xe3: 
    case 0xe4: case 0xe5: case 0xe6: case 0xe7:
    case 0xe8: case 0xe9: case 0xea: case 0xeb:
    case 0xec: case 0xed: case 0xee: case 0xef:
    {
      int id = (int) readLong(ch - 0xe0, 4);
      
      in.serializer(id).scan(this, path, in, values);
      return;
    }
      
    default:
      throw error(L.l("Unexpected opcode 0x{0} while scanning for {1}",
                      Integer.toHexString(ch), path));
    }
  }

  /**
   * Skip based on queries.
   */
  @Override
  public void skip(InH3Amp in)
  {
    int ch = read();
    
    switch (ch) {
    case 0x00: case 0x01: case 0x02: case 0x03: 
    case 0x04: case 0x05: case 0x06: case 0x07:
    case 0x08: case 0x09: case 0x0a: case 0x0b:
    case 0x0c: case 0x0d: case 0x0e: case 0x0f:
      
    case 0x10: case 0x11: case 0x12: case 0x13: 
    case 0x14: case 0x15: case 0x16: case 0x17:
    case 0x18: case 0x19: case 0x1a: case 0x1b:
    case 0x1c: case 0x1d: case 0x1e: case 0x1f:
      
    case 0x20: case 0x21: case 0x22: case 0x23: 
    case 0x24: case 0x25: case 0x26: case 0x27:
    case 0x28: case 0x29: case 0x2a: case 0x2b:
    case 0x2c: case 0x2d: case 0x2e: case 0x2f:
      
    case 0x30: case 0x31: case 0x32: case 0x33: 
    case 0x34: case 0x35: case 0x36: case 0x37:
    case 0x38: case 0x39: case 0x3a: case 0x3b:
    case 0x3c: case 0x3d: case 0x3e: case 0x3f:
      return;
      
    case 0x40: case 0x41: case 0x42: case 0x43: 
    case 0x44: case 0x45: case 0x46: case 0x47:
    case 0x48: case 0x49: case 0x4a: case 0x4b:
    case 0x4c: case 0x4d: case 0x4e: case 0x4f:
      
    case 0x50: case 0x51: case 0x52: case 0x53: 
    case 0x54: case 0x55: case 0x56: case 0x57:
    case 0x58: case 0x59: case 0x5a: case 0x5b:
    case 0x5c: case 0x5d: case 0x5e: case 0x5f:
      
    case 0x60: case 0x61: case 0x62: case 0x63: 
    case 0x64: case 0x65: case 0x66: case 0x67:
    case 0x68: case 0x69: case 0x6a: case 0x6b:
    case 0x6c: case 0x6d: case 0x6e: case 0x6f:
      
    case 0x70: case 0x71: case 0x72: case 0x73: 
    case 0x74: case 0x75: case 0x76: case 0x77:
    case 0x78: case 0x79: case 0x7a: case 0x7b:
    case 0x7c: case 0x7d: case 0x7e: case 0x7f:
      readLong(0,0);
      return;
      
    case 0x80: case 0x81: case 0x82: case 0x83: 
    case 0x84: case 0x85: case 0x86: case 0x87:
    case 0x88: case 0x89: case 0x8a: case 0x8b:
    case 0x8c: case 0x8d: case 0x8e: case 0x8f:
      
    case 0x90: case 0x91: case 0x92: case 0x93: 
    case 0x94: case 0x95: case 0x96: case 0x97:
    case 0x98: case 0x99: case 0x9a: case 0x9b:
    case 0x9c: case 0x9d: case 0x9e: case 0x9f:
      skipString(ch - 0x80);
      return;
      
    case 0xa0: case 0xa1: case 0xa2: case 0xa3: 
    case 0xa4: case 0xa5: case 0xa6: case 0xa7:
    case 0xa8: case 0xa9: case 0xaa: case 0xab:
    case 0xac: case 0xad: case 0xae: case 0xaf:
      
    case 0xb0: case 0xb1: case 0xb2: case 0xb3: 
    case 0xb4: case 0xb5: case 0xb6: case 0xb7:
    case 0xb8: case 0xb9: case 0xba: case 0xbb:
    case 0xbc: case 0xbd: case 0xbe: case 0xbf:
      skipString((int) readLong(ch - 0xa0, 5));
      return;
      
    case 0xc0: case 0xc1: case 0xc2: case 0xc3: 
    case 0xc4: case 0xc5: case 0xc6: case 0xc7:
      skip(ch - 0xc0);
      return;
      
    case 0xc8: case 0xc9: case 0xca: case 0xcb:
    case 0xcc: case 0xcd: case 0xce: case 0xcf:
      skip((int) readLong(ch - 0xc8, 3));
      return;
      
    case 0xd0:
      readDefinition(in);
      skip(in);
      return;
      
    case 0xd1: case 0xd2: case 0xd3: 
    case 0xd4: case 0xd5: case 0xd6: case 0xd7:
    case 0xd8: case 0xd9: case 0xda: case 0xdb:
    case 0xdc: case 0xdd: case 0xde: case 0xdf:
    {
      int id = ch - 0xd0;
      
      in.serializer(id).skip(this, in);
      return;
    }
      
    case 0xe0: case 0xe1: case 0xe2: case 0xe3: 
    case 0xe4: case 0xe5: case 0xe6: case 0xe7:
    case 0xe8: case 0xe9: case 0xea: case 0xeb:
    case 0xec: case 0xed: case 0xee: case 0xef:
    {
      int id = (int) readLong(ch - 0xe0, 4);
      
      in.serializer(id).skip(this, in);
    }
    
    case 0xf0: case 0xf1: case 0xf2:
      return;
      
    case 0xf3:
      skip(8);
      return;
      
    case 0xf4:
      skip(4);
      return;
      
    default:
      throw error(L.l("Unexpected opcode 0x{0} while skipping",
                      Integer.toHexString(ch)));
    }
  }

  /**
   * Define object
   */
  private void readDefinition(InH3Amp inAmp)
  {
    int id = (int) readUnsigned();

    String name = readString();
    
    int type = (int) readUnsigned();
    
    int fields = (int) readUnsigned();
    
    FieldInfoH3 []fieldInfo = new FieldInfoH3[fields];
    
    for (int i = 0; i < fields; i++) {
      fieldInfo[i] = readFieldInfo();
    }
    
    ClassInfoH3 info = new ClassInfoH3(name, fieldInfo);
    
    inAmp.define(id, info);
  }
  
  private FieldInfoH3 readFieldInfo()
  {
    String name = readString();
    
    int type = (int) readUnsigned();
    
    if (type != 1) {
      throw error(L.l("unknown field type {0} for field {1}", 
                      type, name));
    }
    
    return new FieldInfoH3(name);
  }
  
  private String readString(int strlen)
  {
    readString(_charBuffer, strlen);
    
    return new String(_charBuffer, 0, strlen);
  }
  
  private long readLong(long value, int shift)
  {
    while (true) {
      int ch = read();

      if (ch < 0) {
        throw error(L.l("unexpected end of file while reading long"));
      }
      else if (ch < 0x80) {
        value += ((long) ch << shift);
        
        return value;
      }
      else {
        value += ((ch & 0x7fL) << shift);
        shift += 7;
      }
    }
  }
  
  private void readString(char []cBuf, int strlen)
  {
    byte []bBuf = _buffer;
    
    int i = 0;
    while (i < strlen) {
      int offset = _offset;
      int length = _length;
      
      while (i < strlen && offset + 2 < length) {
        int ch = bBuf[offset++] & 0xff;
        
        if (ch < 0x80) {
          cBuf[i++] = (char) ch;
        }
        else if ((ch & 0xe0) == 0xc0) {
          int ch2 = bBuf[offset++] & 0xff;
          
          cBuf[i++] = (char) (((ch & 0x1f) << 6) + (ch2 & 0x3f));
        }
        else if ((ch & 0xf0) == 0xe0) {
          int ch2 = bBuf[offset++] & 0xff;
          int ch3 = bBuf[offset++] & 0xff;
          
          cBuf[i++] = (char) (((ch & 0xf) << 12)
              + ((ch2 & 0x3f) << 6)
              + (ch3 & 0x3f));
        }
        else {
          throw error(L.l("invalid UTF-8 char 0x{0}", Integer.toHexString(ch)));
        }
      }
      
      _offset = offset;
      _length = length;
      
      if (i < strlen) {
        int ch = read();
        
        if ((ch & 0xf80) == 0) {
          cBuf[i++] = (char) ch;
        }
        else if ((ch & 0xfe0) == 0xc0) {
          int ch2 = read();
          
          cBuf[i++] = (char) (((ch & 0x1f) << 6) + (ch2 & 0x3f));
        }
        else if ((ch & 0xff0) == 0xe0) {
          int ch2 = read();
          int ch3 = read();
          
          cBuf[i++] = (char) (((ch & 0xf) << 12)
              + ((ch2 & 0x3f) << 6)
              + (ch3 & 0x3f));
        }
      }
    }
  }
  
  private void skipString(int strlen)
  {
    int i = 0;
    while (i < strlen) {
      byte []bBuf = _buffer;
      int offset = _offset;
      int length = _length;
      
      for (; i < strlen && offset + 2 < length; i++) {
        int ch = bBuf[offset++] & 0xff;
        
        if (ch < 0x80) {
        }
        else if ((ch & 0xe0) == 0xc0) {
          offset++;
        }
        else if ((ch & 0xf0) == 0xe0) {
          offset += 2;
        }
        else {
          throw error(L.l("invalid UTF-8 char 0x{0}", Integer.toHexString(ch)));
        }
      }
      
      _offset = offset;
      _length = length;
      
      if (i < strlen) {
        i++;
        int ch = read();
        
        if ((ch & 0xf80) == 0) {
        }
        else if ((ch & 0xfe0) == 0xc0) {
          read();
        }
        else if ((ch & 0xff0) == 0xe0) {
          read();
          read();
        }
        else {
          throw error(L.l("invalid UTF-8 char 0x{0}", Integer.toHexString(ch)));
        }
      }
    }
  }
  
  private RuntimeException error(String msg)
  {
    return new H3ExceptionIn(msg);
  }

  @Override
  public void close()
  {
    // TODO Auto-generated method stub
    
  }
  
  private void skip(int len)
  {
    while (true) {
      int offset = _offset;
      int length = _length;
    
      int sublen = Math.min(len, length - offset);
    
      _offset = offset + sublen;
      len -= sublen;
      
      if (len <= 0) {
        return;
      }
      else if (! fill()) {
        return;
      }
    }
  }
  
  private void readBinaryData(byte []tBuffer, int tOffset, int tLength)
  {
    while (true) {
      int offset = _offset;
      int length = _length;
    
      int sublen = Math.min(tLength, length - offset);
    
      System.arraycopy(_buffer, offset, tBuffer, tOffset, sublen);
      
      _offset = offset + sublen;
      tLength -= sublen;
      
      if (tLength <= 0) {
        return;
      }
      else if (! fill()) {
        throw error(L.l("Unexpected end of file while reading binary"));
      }
    }
  }
  
  private int read()
  {
    try {
      byte []buffer = _buffer;
      int offset = _offset;
      int length = _length;

      if (offset < length) {
        int value = buffer[offset] & 0xff;
        _offset = offset + 1;
        return value;
      }

      _length = _is.read(buffer, 0, buffer.length);

      if (_length > 0) {
        _offset = 1;
        
        return _buffer[0] & 0xff;
      }
      else {
        return -1;
      }
    } catch (IOException e) {
      throw new H3ExceptionIn(e);
    }
  }
  private boolean fill()
  {
    try {
      _length = _is.read(_buffer, 0, _buffer.length);
      _offset = 0;
    
      return _length > 0;
    } catch (IOException e) {
      throw new H3ExceptionIn(e);
    }
  }
}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy