| /* |
| * Copyright 2009-2012 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; |
| |
| import java.util.Arrays; |
| |
| import edu.uci.ics.hyracks.dataflow.common.data.accessors.ITupleReference; |
| |
| /** |
| * WARNING: getFieldData(), getFieldStart() and getFieldLength() are log and not constant time. |
| */ |
| public class ConcatenatingTupleReference implements ITupleReference { |
| |
| private final ITupleReference[] tuples; |
| private final int[] fieldCounts; |
| private int numTuples; |
| private int totalFieldCount; |
| |
| public ConcatenatingTupleReference(int maxTuples) { |
| tuples = new ITupleReference[maxTuples]; |
| fieldCounts = new int[maxTuples]; |
| reset(); |
| } |
| |
| public void reset() { |
| numTuples = 0; |
| totalFieldCount = 0; |
| } |
| |
| public void addTuple(ITupleReference tuple) { |
| tuples[numTuples] = tuple; |
| totalFieldCount += tuple.getFieldCount(); |
| if (numTuples > 0) { |
| fieldCounts[numTuples] = fieldCounts[numTuples - 1] + tuple.getFieldCount(); |
| } else { |
| fieldCounts[numTuples] = tuple.getFieldCount(); |
| } |
| ++numTuples; |
| } |
| |
| public void removeLastTuple() { |
| if (numTuples > 0) { |
| ITupleReference lastTuple = tuples[--numTuples]; |
| totalFieldCount -= lastTuple.getFieldCount(); |
| } |
| } |
| |
| public int getNumTuples() { |
| return numTuples; |
| } |
| |
| public boolean hasMaxTuples() { |
| return numTuples == tuples.length; |
| } |
| |
| @Override |
| public int getFieldCount() { |
| return totalFieldCount; |
| } |
| |
| @Override |
| public byte[] getFieldData(int fIdx) { |
| int tupleIndex = getTupleIndex(fIdx); |
| int fieldIndex = getFieldIndex(tupleIndex, fIdx); |
| return tuples[tupleIndex].getFieldData(fieldIndex); |
| } |
| |
| @Override |
| public int getFieldStart(int fIdx) { |
| int tupleIndex = getTupleIndex(fIdx); |
| int fieldIndex = getFieldIndex(tupleIndex, fIdx); |
| return tuples[tupleIndex].getFieldStart(fieldIndex); |
| } |
| |
| @Override |
| public int getFieldLength(int fIdx) { |
| int tupleIndex = getTupleIndex(fIdx); |
| int fieldIndex = getFieldIndex(tupleIndex, fIdx); |
| return tuples[tupleIndex].getFieldLength(fieldIndex); |
| } |
| |
| private int getTupleIndex(int fIdx) { |
| int tupleIndex = Arrays.binarySearch(fieldCounts, 0, numTuples - 1, fIdx); |
| if (tupleIndex < 0) { |
| tupleIndex = -tupleIndex - 1; |
| } else { |
| ++tupleIndex; |
| } |
| return tupleIndex; |
| } |
| |
| private int getFieldIndex(int tupleIndex, int fIdx) { |
| int fieldIndex = -1; |
| if (tupleIndex > 0) { |
| fieldIndex = fIdx - fieldCounts[tupleIndex - 1]; |
| } else { |
| fieldIndex = fIdx; |
| } |
| return fieldIndex; |
| } |
| } |