1 /*******************************************************************************
\r
2 * Copyright (c) 2007, 2010 Association for Decentralized Information Management
\r
3 * in Industry THTH ry.
\r
4 * All rights reserved. This program and the accompanying materials
\r
5 * are made available under the terms of the Eclipse Public License v1.0
\r
6 * which accompanies this distribution, and is available at
\r
7 * http://www.eclipse.org/legal/epl-v10.html
\r
10 * VTT Technical Research Centre of Finland - initial API and implementation
\r
11 *******************************************************************************/
\r
12 package org.simantics.db.impl;
\r
14 import org.simantics.db.exception.DatabaseException;
\r
15 import org.simantics.db.impl.ClusterI.Procedure;
\r
16 import org.simantics.db.service.Bytes;
\r
18 interface TableFactoryI<TableType> {
\r
19 TableType newTable(int size);
\r
20 boolean isEqual(TableType t1, int t1Start, int size, TableType t2, int t2Start);
\r
23 class ByteFactory implements TableFactoryI<byte[]> {
\r
25 public byte[] newTable(int size) {
\r
26 return new byte[size];
\r
30 public boolean isEqual(byte[] t1, int start, int size, byte[] t2, int start2) {
\r
31 for (int i=0; i<size; ++i)
\r
32 if (t1[start + i] != t2[start2 + i])
\r
38 class IntFactory implements TableFactoryI<int[]> {
\r
40 public int[] newTable(int size) {
\r
41 return new int[size];
\r
45 public boolean isEqual(int[] t1, int start, int size, int[] t2, int start2) {
\r
46 for (int i=0; i<size; ++i)
\r
47 if (t1[start + i] != t2[start2 + i])
\r
53 class LongFactory implements TableFactoryI<long[]> {
\r
55 public long[] newTable(int size) {
\r
56 return new long[size];
\r
60 public boolean isEqual(long[] t1, int start, int size, long[] t2, int start2) {
\r
61 for (int i=0; i<size; ++i)
\r
62 if (t1[start + i] != t2[start2 + i])
\r
68 public abstract class Table<TableType> {
\r
69 private static final int INITIAL_SIZE = 100; // Initial size of the table. Must be greater or equal than header_size;
\r
70 private static final int INCREMENT_SIZE = 1000; // Minimum increment size of the table.
\r
71 protected static final int ZERO_SHIFT = 1; // Indexes are guaranteed not to be zero.
\r
72 final private TableHeader header;
\r
73 final private TableFactoryI<TableType> factory;
\r
74 final private TableSizeListener sizeListener;
\r
75 public int offset; // Offset of table in containing array.
\r
76 public TableType table;
\r
77 protected Table(TableFactoryI<TableType> factory, TableSizeListener sizeListener, int[] header, int headerBase) {
\r
78 this.factory = factory;
\r
79 this.sizeListener = sizeListener;
\r
80 this.header = new TableHeader(header, headerBase);
\r
81 this.offset = -ZERO_SHIFT;
\r
82 newTable(INITIAL_SIZE);
\r
83 this.header.setSize(0);
\r
84 this.header.setCount(0);
\r
85 this.header.setOffset(offset);
\r
88 // final int size(Object bytes) {
\r
89 // if(bytes instanceof byte[]) return ((byte[])bytes).length;
\r
90 // if(bytes instanceof int[]) return ((int[])bytes).length;
\r
91 // if(bytes instanceof long[]) return ((long[])bytes).length;
\r
95 protected Table(TableFactoryI<TableType> factory, TableSizeListener sizeListener, int[] header, int headerBase, TableType bytes) {
\r
96 // System.out.println("Table size=" + size(bytes) + " header = " + Arrays.toString(Arrays.copyOfRange(header, headerBase, headerBase + 4)));
\r
97 this.factory = factory;
\r
98 this.sizeListener = sizeListener;
\r
99 this.header = new TableHeader(header, headerBase);
\r
100 offset = this.header.getOffset();
\r
101 this.table = bytes;
\r
104 * Create and initialize this with a new table.
\r
106 * @param capacity of the table. How many elements the table can hold without allocating new space.
\r
107 * @param size of the table. How many elements have been used.
\r
108 * @param count of how many segments has been have been allocated.
\r
109 * @return old table.
\r
111 final protected TableType createNewTable(int capacity, int size, int count) {
\r
112 TableType t = table;
\r
113 this.offset = -ZERO_SHIFT;
\r
114 newTable(capacity);
\r
115 sizeListener.resized();
\r
116 header.setSize(size);
\r
117 header.setCount(count);
\r
118 header.setOffset(offset);
\r
121 public final int getTableCapacity() {
\r
122 return header.getCapacity();
\r
124 public final int getTableSize() {
\r
125 return header.getSize();
\r
127 public final int getTableCount() {
\r
128 return header.getCount();
\r
130 protected int convertRealIndexToTableIndex(int realIndex) {
\r
131 return realIndex - offset;
\r
133 protected final int checkIndexAndGetRealIndex(int index, int size) {
\r
134 if (index < ZERO_SHIFT)
\r
135 throw new IllegalArgumentException("Underflow, index=" + index);
\r
136 if ((size > 0 && index - ZERO_SHIFT + size > header.getSize()))
\r
137 throw new IllegalArgumentException("Overflow, index=" + index + " size=" + size);
\r
138 return index + offset;
\r
140 protected final int checkIndexAndGetRealIndexEx(int index, int size) {
\r
141 if (index < ZERO_SHIFT || size < 1)
\r
142 throw new IllegalArgumentException("Underflow, index=" + index + " size=" + size);
\r
143 if (index - ZERO_SHIFT + size < header.getSize())
\r
144 return index + offset;
\r
145 else if (index - ZERO_SHIFT + size == header.getSize())
\r
148 throw new IllegalArgumentException("Underflow, index=" + index + " size=" + size);
\r
150 final protected void getCopy(int index, byte[] to, int start, int size) {
\r
151 int realIndex = checkIndexAndGetRealIndex(index, size);
\r
153 throw new IllegalArgumentException("Illgal table size " + size);
\r
154 System.arraycopy(table, realIndex, to, start, size);
\r
156 final protected void getCopy(int index, char[] to, int start, int size) {
\r
157 // int realIndex = checkIndexAndGetRealIndex(index, size);
\r
159 // throw new IllegalArgumentException("Illgal table size " + size);
\r
160 byte[] bs = (byte[])table;
\r
161 start += index+offset+1;
\r
162 for(int i=0;i<size;i++) to[i] = (char)bs[start++];
\r
163 // System.arraycopy(table, realIndex, to, start, size);
\r
165 final protected void setCopy(int index, int size, TableType from, int fromStartIndex) {
\r
166 // System.out.println("setCopy index=" + index + " size=" + size + "fromStartIndex=" + fromStartIndex + "from.length=" + ((byte[])from).length + "table.length=" + ((byte[])table).length);
\r
167 int realIndex = checkIndexAndGetRealIndex(index, size);
\r
168 System.arraycopy(from, fromStartIndex, table, realIndex, size);
\r
170 final protected boolean isEqual(int index, TableType to, int toStartIndex, int toSize) {
\r
171 int realIndex = checkIndexAndGetRealIndex(index, toSize);
\r
172 return factory.isEqual(table, realIndex, toSize, to, toStartIndex);
\r
175 * @param size of the element (how many table slots is allocated).
\r
176 * @return table index not the real index. To get real index use checkIndexAndGetRealIndex.
\r
178 final protected int createNewElement(int size) {
\r
180 throw new IllegalArgumentException("Illegal table size " + size);
\r
183 int oldSize = header.getSize();
\r
184 int newSize = oldSize + size;
\r
185 if (newSize > header.getCapacity())
\r
187 header.setSize(newSize);
\r
188 header.setCount(header.getCount()+1);
\r
189 return ZERO_SHIFT + oldSize;
\r
191 final protected void deleteOldElement(int index, int size) {
\r
192 checkIndexAndGetRealIndex(index, size);
\r
193 header.setCount(header.getCount()-1);
\r
195 final protected TableHeader getHeader() {
\r
198 final protected int getTableBase() {
\r
199 return offset + ZERO_SHIFT;
\r
201 final protected TableType getTable() {
\r
204 final protected int getExtra(int index) {
\r
205 return header.getExtra(index);
\r
207 final protected void setExtra(int index, int value) {
\r
208 header.setExtra(index, value);
\r
210 final private void realloc(int newSize) {
\r
211 int realCapacity = newSize + Math.max(INCREMENT_SIZE, newSize/10);
\r
212 TableType oldTable = table;
\r
213 newTable(realCapacity);
\r
214 sizeListener.resized();
\r
215 int oldBase = getTableBase();
\r
216 offset = -ZERO_SHIFT;
\r
217 header.setOffset(offset);
\r
218 int oldSize = header.getSize();
\r
219 // If zero can cause ArrayIndexOutOfBoundsException because oldBase
\r
220 // (index) can be out of bounds in this case and it is checked even
\r
221 // if olsSize is zero (i.e. number of copied bytes is zero).
\r
223 System.arraycopy(oldTable, oldBase, table, 0, oldSize);
\r
226 final private void newTable(int capacity) {
\r
227 table = factory.newTable(capacity);
\r
228 header.setCapacity(capacity);
\r
231 public <T> int store(T _ret, int retPos) {
\r
235 if(table instanceof byte[]) {
\r
236 System.arraycopy(table, getTableBase(), _ret, retPos, getHeader().getSize());
\r
237 retPos += getHeader().getSize();
\r
238 } else if(table instanceof int[]) {
\r
239 int[] t = (int[])table;
\r
240 int[] ret = (int[])_ret;
\r
241 for(int i=getTableBase();i<getTableBase() + getHeader().getSize();i++) {
\r
244 // Bytes.writeLE(ret, retPos, v);
\r
247 } else if(table instanceof long[]) {
\r
248 long[] t = (long[])table;
\r
249 long[] ret = (long[])_ret;
\r
250 for(int i=getTableBase();i<getTableBase() + getHeader().getSize();i++) {
\r
253 // Bytes.writeLE8(ret, retPos, v);
\r
257 getHeader().setOffset(off-1);
\r
258 getHeader().setCapacity(getHeader().getSize());
\r
262 public <T> int storeBytes(byte[] _ret, int off, int retPos) {
\r
264 //int off = retPos;
\r
266 if(table instanceof byte[]) {
\r
267 System.arraycopy(table, getTableBase(), _ret, retPos, getHeader().getSize());
\r
268 retPos += getHeader().getSize();
\r
269 } else if(table instanceof int[]) {
\r
270 int[] t = (int[])table;
\r
271 for(int i=getTableBase();i<getTableBase() + getHeader().getSize();i++) {
\r
273 // ret[retPos++] = v;
\r
274 Bytes.writeLE(_ret, retPos, v);
\r
277 } else if(table instanceof long[]) {
\r
278 long[] t = (long[])table;
\r
279 for(int i=getTableBase();i<getTableBase() + getHeader().getSize();i++) {
\r
281 Bytes.writeLE8(_ret, retPos, v);
\r
286 getHeader().setOffset(off-1);
\r
287 getHeader().setCapacity(getHeader().getSize());
\r
292 public abstract <Context> boolean foreach(int setIndex, Procedure procedure, final Context context, final ClusterSupport support, Modifier modifier) throws DatabaseException;
\r