/** * Copyright 2014 National University of Ireland, Galway. * * This file is part of the SIREn project. Project and contact information: * * https://github.com/rdelbru/SIREn * * 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. */ package org.sindice.siren.analysis.filter; import java.nio.ByteBuffer; import java.nio.IntBuffer; import org.apache.lucene.util.BytesRef; import org.apache.lucene.util.IntsRef; import org.sindice.siren.util.CodecUtils; /** * An implementation of the {@link PayloadCodec} using Variable Int encoding. */ public class VIntPayloadCodec extends PayloadCodec { ByteBuffer bb = ByteBuffer.allocate(10); /** * Used in {@link #decode()} and {@link #encode()} */ BytesRef bytes = new BytesRef(); IntBuffer ib = IntBuffer.allocate(2); /** * Used in {@link #decode()} and {@link #encode()} */ IntsRef ints = new IntsRef(); int pos; @Override public IntsRef getNode() { return ints; } @Override public int getPosition() { return pos; } @Override public void decode(final BytesRef data) { // max case : 1 byte = 1 int this.ensureIntBufferSize(data.length); ib.clear(); this.setData(data.bytes, data.offset, data.length); // decode position and node final int limit = bytes.length - bytes.offset; while (bytes.offset < limit) { ib.put(CodecUtils.byteArrayToVInt(bytes)); } ib.flip(); // set position pos = ib.get(); // set node this.setNode(ib.array(), ib.position(), ib.limit() - ib.position()); } @Override public BytesRef encode(final IntsRef node, final int pos) { // max case : 1 int = 5 bytes this.ensureByteBufferSize((node.length + 1) * 5); bb.clear(); // encode position CodecUtils.vIntToByteArray(pos, bb); // encode node this.setNode(node.ints, node.offset, node.length); final int limit = ints.length - ints.offset; for (int i = ints.offset; i < limit; i++) { CodecUtils.vIntToByteArray(ints.ints[i], bb); } bb.flip(); this.setData(bb.array(), bb.position(), bb.limit()); return bytes; } private void setData(final byte[] data, final int offset, final int length) { bytes.bytes = data; bytes.length = length; bytes.offset = offset; } private void setNode(final int[] data, final int offset, final int length) { ints.ints = data; ints.length = length; ints.offset = offset; } private void ensureByteBufferSize(final int size) { if (bb.capacity() < size) { bb = ByteBuffer.allocate(size); } } private void ensureIntBufferSize(final int size) { if (ib.capacity() < size) { ib = IntBuffer.allocate(size); } } }