/******************************************************************************* * Copyright (c) 2007, 2010 Association for Decentralized Information Management * in Industry THTH ry. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-v10.html * * Contributors: * VTT Technical Research Centre of Finland - initial API and implementation *******************************************************************************/ package org.simantics.db.impl; import org.simantics.db.exception.DatabaseException; import org.simantics.db.impl.ClusterI.Procedure; import org.simantics.db.service.Bytes; interface TableFactoryI { TableType newTable(int size); boolean isEqual(TableType t1, int t1Start, int size, TableType t2, int t2Start); } class ByteFactory implements TableFactoryI { @Override public byte[] newTable(int size) { return new byte[size]; } @Override public boolean isEqual(byte[] t1, int start, int size, byte[] t2, int start2) { for (int i=0; i { @Override public int[] newTable(int size) { return new int[size]; } @Override public boolean isEqual(int[] t1, int start, int size, int[] t2, int start2) { for (int i=0; i { @Override public long[] newTable(int size) { return new long[size]; } @Override public boolean isEqual(long[] t1, int start, int size, long[] t2, int start2) { for (int i=0; i { private static final int INITIAL_SIZE = 100; // Initial size of the table. Must be greater or equal than header_size; private static final int INCREMENT_SIZE = 1000; // Minimum increment size of the table. protected static final int ZERO_SHIFT = 1; // Indexes are guaranteed not to be zero. final private TableHeader header; final private TableFactoryI factory; final private TableSizeListener sizeListener; public int offset; // Offset of table in containing array. public TableType table; protected Table(TableFactoryI factory, TableSizeListener sizeListener, int[] header, int headerBase) { this.factory = factory; this.sizeListener = sizeListener; this.header = new TableHeader(header, headerBase); this.offset = -ZERO_SHIFT; newTable(INITIAL_SIZE); this.header.setSize(0); this.header.setCount(0); this.header.setOffset(offset); } // final int size(Object bytes) { // if(bytes instanceof byte[]) return ((byte[])bytes).length; // if(bytes instanceof int[]) return ((int[])bytes).length; // if(bytes instanceof long[]) return ((long[])bytes).length; // return 0; // } protected Table(TableFactoryI factory, TableSizeListener sizeListener, int[] header, int headerBase, TableType bytes) { // System.out.println("Table size=" + size(bytes) + " header = " + Arrays.toString(Arrays.copyOfRange(header, headerBase, headerBase + 4))); this.factory = factory; this.sizeListener = sizeListener; this.header = new TableHeader(header, headerBase); offset = this.header.getOffset(); this.table = bytes; } /** * Create and initialize this with a new table. * * @param capacity of the table. How many elements the table can hold without allocating new space. * @param size of the table. How many elements have been used. * @param count of how many segments has been have been allocated. * @return old table. */ final protected TableType createNewTable(int capacity, int size, int count) { TableType t = table; this.offset = -ZERO_SHIFT; newTable(capacity); sizeListener.resized(); header.setSize(size); header.setCount(count); header.setOffset(offset); return t; } public final int getTableCapacity() { return header.getCapacity(); } public final int getTableSize() { return header.getSize(); } public final int getTableCount() { return header.getCount(); } protected int convertRealIndexToTableIndex(int realIndex) { return realIndex - offset; } protected final int checkIndexAndGetRealIndex(int index, int size) { if (index < ZERO_SHIFT) throw new IllegalArgumentException("Underflow, index=" + index); if ((size > 0 && index - ZERO_SHIFT + size > header.getSize())) throw new IllegalArgumentException("Overflow, index=" + index + " size=" + size); return index + offset; } protected final int checkIndexAndGetRealIndexEx(int index, int size) { if (index < ZERO_SHIFT || size < 1) throw new IllegalArgumentException("Underflow, index=" + index + " size=" + size); if (index - ZERO_SHIFT + size < header.getSize()) return index + offset; else if (index - ZERO_SHIFT + size == header.getSize()) return -1; else throw new IllegalArgumentException("Underflow, index=" + index + " size=" + size); } final protected void getCopy(int index, byte[] to, int start, int size) { int realIndex = checkIndexAndGetRealIndex(index, size); if (size < 0) throw new IllegalArgumentException("Illgal table size " + size); System.arraycopy(table, realIndex, to, start, size); } final protected void getCopy(int index, char[] to, int start, int size) { // int realIndex = checkIndexAndGetRealIndex(index, size); // if (size < 0) // throw new IllegalArgumentException("Illgal table size " + size); byte[] bs = (byte[])table; start += index+offset+1; for(int i=0;i header.getCapacity()) realloc(newSize); header.setSize(newSize); header.setCount(header.getCount()+1); return ZERO_SHIFT + oldSize; } final protected void deleteOldElement(int index, int size) { checkIndexAndGetRealIndex(index, size); header.setCount(header.getCount()-1); } final protected TableHeader getHeader() { return header; } final protected int getTableBase() { return offset + ZERO_SHIFT; } final protected TableType getTable() { return table; } final protected int getExtra(int index) { return header.getExtra(index); } final protected void setExtra(int index, int value) { header.setExtra(index, value); } final private void realloc(int newSize) { int realCapacity = newSize + Math.max(INCREMENT_SIZE, newSize/10); TableType oldTable = table; newTable(realCapacity); sizeListener.resized(); int oldBase = getTableBase(); offset = -ZERO_SHIFT; header.setOffset(offset); int oldSize = header.getSize(); // If zero can cause ArrayIndexOutOfBoundsException because oldBase // (index) can be out of bounds in this case and it is checked even // if olsSize is zero (i.e. number of copied bytes is zero). if (oldSize > 0) { System.arraycopy(oldTable, oldBase, table, 0, oldSize); } } final private void newTable(int capacity) { table = factory.newTable(capacity); header.setCapacity(capacity); } public int store(T _ret, int retPos) { int off = retPos; if(table instanceof byte[]) { System.arraycopy(table, getTableBase(), _ret, retPos, getHeader().getSize()); retPos += getHeader().getSize(); } else if(table instanceof int[]) { int[] t = (int[])table; int[] ret = (int[])_ret; for(int i=getTableBase();i int storeBytes(byte[] _ret, int off, int retPos) { //int off = retPos; if(table instanceof byte[]) { System.arraycopy(table, getTableBase(), _ret, retPos, getHeader().getSize()); retPos += getHeader().getSize(); } else if(table instanceof int[]) { int[] t = (int[])table; for(int i=getTableBase();i boolean foreach(int setIndex, Procedure procedure, final Context context, final ClusterSupport support, Modifier modifier) throws DatabaseException; }