| /* |
| * Copyright 2009-2010 by The Regents of the University of California |
| * 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 from |
| * |
| * 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 edu.uci.ics.hyracks.storage.am.common.tuples; |
| |
| // encodes positive integers in a variable-byte format |
| |
| public class VarLenIntEncoderDecoder { |
| public static final int ENCODE_MASK = 0x0000007F; |
| public static final byte CONTINUE_CHUNK = (byte) 0x80; |
| public static final byte DECODE_MASK = (byte) 0x7F; |
| |
| private byte[] encTmp = new byte[5]; |
| |
| private int pos; |
| private byte[] bytes; |
| |
| public void reset(byte[] bytes, int pos) { |
| this.bytes = bytes; |
| this.pos = pos; |
| } |
| |
| public int encode(int val) { |
| int origPos = 0; |
| int tmpPos = 0; |
| while (val > ENCODE_MASK) { |
| encTmp[tmpPos++] = (byte) (val & ENCODE_MASK); |
| val = val >>> 7; |
| } |
| encTmp[tmpPos++] = (byte) (val); |
| |
| // reverse order to optimize for decoding speed |
| for (int i = 0; i < tmpPos - 1; i++) { |
| bytes[pos++] = (byte) (encTmp[tmpPos - 1 - i] | CONTINUE_CHUNK); |
| } |
| bytes[pos++] = encTmp[0]; |
| |
| return pos - origPos; |
| } |
| |
| public int decode() { |
| int sum = 0; |
| while ((bytes[pos] & CONTINUE_CHUNK) == CONTINUE_CHUNK) { |
| sum = (sum + (bytes[pos] & DECODE_MASK)) << 7; |
| pos++; |
| } |
| sum += bytes[pos++]; |
| return sum; |
| } |
| |
| // calculate the number of bytes needed for encoding |
| public int getBytesRequired(int val) { |
| int byteCount = 0; |
| while (val > ENCODE_MASK) { |
| val = val >>> 7; |
| byteCount++; |
| } |
| return byteCount + 1; |
| } |
| |
| public int getPos() { |
| return pos; |
| } |
| |
| // fast encoding, slow decoding version |
| /* |
| * public void encode(int val) { while(val > ENCODE_MASK) { bytes[pos++] = |
| * (byte)(((byte)(val & ENCODE_MASK)) | CONTINUE_CHUNK); val = val >>> 7; } |
| * bytes[pos++] = (byte)(val); } |
| * |
| * public int decode() { int sum = 0; int shift = 0; while( (bytes[pos] & |
| * CONTINUE_CHUNK) == CONTINUE_CHUNK) { sum = (sum + (bytes[pos] & |
| * DECODE_MASK)) << 7 * shift++; pos++; } sum += bytes[pos++] << 7 * shift; |
| * return sum; } |
| */ |
| } |