/* * This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ package com.github.geophile.erdo.util; /* * Stores erdo ids in order (because a KeyArray is in key order). Compressed using run-length encoding. * E.g. 0 0 0 0 0 1 1 2 3 3 3 3 -> * erdoId startPosision * 0 0 * 1 5 * 2 7 * 3 8 * count = 12 */ import java.nio.BufferOverflowException; import java.nio.ByteBuffer; import java.util.Arrays; public class ErdoIdArray implements Transferrable { // Object interface @Override public String toString() { StringBuilder buffer = new StringBuilder(); buffer.append('['); for (int i = 0; i < nErdoIds; i++) { if (i > 0) { buffer.append(", "); } buffer.append(startPosition[i]); buffer.append(": "); buffer.append(erdoIds[i]); } buffer.append(", "); buffer.append(count); buffer.append(": --"); buffer.append(']'); return buffer.toString(); } // Transferrable interface public void writeTo(ByteBuffer buffer) throws BufferOverflowException { buffer.putInt(count); buffer.putInt(nErdoIds); for (int i = 0; i < nErdoIds; i++) { buffer.putInt(erdoIds[i]); buffer.putInt(startPosition[i]); } } public void readFrom(ByteBuffer buffer) { count = buffer.getInt(); nErdoIds = buffer.getInt(); erdoIds = new int[nErdoIds]; startPosition = new int[nErdoIds]; for (int i = 0; i < nErdoIds; i++) { erdoIds[i] = buffer.getInt(); startPosition[i] = buffer.getInt(); } } public int recordCount() { // The number of INT_SIZEd records in the serialized representation return nErdoIds * 2 + 2; } // ErdoIdArray interface public void append(int erdoId) { if (nErdoIds == 0 || erdoIds[nErdoIds - 1] != erdoId) { if (nErdoIds == erdoIds.length) { int newLength = erdoIds.length * 2; erdoIds = Arrays.copyOf(erdoIds, newLength); startPosition = Arrays.copyOf(startPosition, newLength); } erdoIds[nErdoIds] = erdoId; startPosition[nErdoIds] = count; nErdoIds++; } count++; } public int at(int position) { if (position < 0 || position >= count) { throw new IndexOutOfBoundsException(Integer.toString(position)); } if (nErdoIds == 1) { return erdoIds[0]; } else { for (int i = nErdoIds - 1; i >= 0; i--) { if (position >= startPosition[i]) { return erdoIds[i]; } } assert false; return -1; } } public void removeLast() { assert count > 0; count--; if (startPosition[nErdoIds - 1] == count) { nErdoIds--; } } public int size() { return count; } public int serializedSize() { return INT_SIZE * recordCount(); } // Class state private static final int INITIAL_SIZE = 10; private static final int INT_SIZE = 4; // Object state // erdoId[i] runs from startPosition[i] to startPosition[i+1], (or to the end of the key array for the last erdoId). private int[] erdoIds = new int[INITIAL_SIZE]; private int[] startPosition = new int[INITIAL_SIZE]; private int nErdoIds = 0; private int count = 0; }