diff --git a/teavm-core/src/main/java/org/teavm/common/RecordArray.java b/teavm-core/src/main/java/org/teavm/common/RecordArray.java new file mode 100644 index 000000000..8f3399dc9 --- /dev/null +++ b/teavm-core/src/main/java/org/teavm/common/RecordArray.java @@ -0,0 +1,92 @@ +/* + * Copyright 2014 Alexey Andreev. + * + * 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.teavm.common; + +import java.util.Arrays; + +/** + * + * @author Alexey Andreev + */ +public class RecordArray { + private int recordSize; + private int arraysPerRecord; + private int[] data; + private int[] substart; + private int[] subdata; + + RecordArray(int recordSize, int arraysPerRecord, int[] data, int[] substart, int[] subdata) { + this.recordSize = recordSize; + this.arraysPerRecord = arraysPerRecord; + this.data = data; + this.substart = substart; + this.subdata = subdata; + } + + public Record get(int index) { + return new Record(index * recordSize, index * arraysPerRecord); + } + + public int size() { + return data.length / recordSize; + } + + public int getRecordSize() { + return recordSize; + } + + public int arraysPerRecord() { + return arraysPerRecord; + } + + public class Record { + int offset; + int arrayOffset; + + Record(int offset, int arrayOffset) { + this.offset = offset; + this.arrayOffset = arrayOffset; + } + + public int getPosition() { + return offset / recordSize; + } + + public int get(int index) { + if (index >= recordSize) { + throw new IndexOutOfBoundsException("Index out of bounds: " + index + " of " + recordSize); + } + return data[offset + index]; + } + + public int size() { + return recordSize; + } + + public int[] getArray(int index) { + if (index > arraysPerRecord) { + throw new IndexOutOfBoundsException("Index out of bounds: " + index + " of " + arraysPerRecord); + } + int start = substart[arrayOffset + index]; + int end = substart[arrayOffset + index + 1]; + return Arrays.copyOfRange(subdata, start, end); + } + + public int numArrays() { + return arraysPerRecord; + } + } +} diff --git a/teavm-core/src/main/java/org/teavm/common/RecordArrayBuilder.java b/teavm-core/src/main/java/org/teavm/common/RecordArrayBuilder.java new file mode 100644 index 000000000..4f5125355 --- /dev/null +++ b/teavm-core/src/main/java/org/teavm/common/RecordArrayBuilder.java @@ -0,0 +1,148 @@ +/* + * Copyright 2014 Alexey Andreev. + * + * 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.teavm.common; + +/** + * + * @author Alexey Andreev + */ +public class RecordArrayBuilder { + private int recordSize; + private int arraysPerRecord; + private IntegerArray data = new IntegerArray(1); + private IntegerArray substart = new IntegerArray(1); + private IntegerArray subdata = new IntegerArray(1); + private IntegerArray subnext = new IntegerArray(1); + + public RecordArrayBuilder(int recordSize, int arraysPerRecord) { + this.recordSize = recordSize; + this.arraysPerRecord = arraysPerRecord; + } + + public Record get(int index) { + return new Record(index * recordSize, index * arraysPerRecord); + } + + public Record add() { + int offset = data.size(); + for (int i = 0; i < recordSize; ++i) { + data.add(0); + } + int arrayOffset = substart.size(); + for (int i = 0; i < arraysPerRecord; ++i) { + substart.add(-1); + } + return new Record(offset, arrayOffset); + } + + public int size() { + return data.size() / recordSize; + } + + public int getRecordSize() { + return recordSize; + } + + public int getArraysPerRecord() { + return arraysPerRecord; + } + + public RecordArray build() { + int[] builtSubstart = new int[substart.size() + 1]; + IntegerArray builtSubdata = new IntegerArray(1); + for (int i = 0; i < substart.size(); ++i) { + int ptr = substart.get(i); + while (ptr >= 0) { + builtSubdata.add(subdata.get(ptr)); + ptr = subnext.get(ptr); + } + builtSubstart[i + 1] = builtSubdata.size(); + } + return new RecordArray(recordSize, arraysPerRecord, data.getAll(), builtSubstart, builtSubdata.getAll()); + } + + public class Record { + private int offset; + private int arrayOffset; + + public Record(int offset, int arrayOffset) { + this.offset = offset; + this.arrayOffset = arrayOffset; + } + + public int getPosition() { + return offset / recordSize; + } + + public int get(int index) { + if (index >= recordSize) { + throw new IndexOutOfBoundsException("Index out of bounds: " + index + " of " + recordSize); + } + return data.get(index + offset); + } + + public int size() { + return recordSize; + } + + public int numArrays() { + return arraysPerRecord; + } + + public RecordSubArray getArray(int index) { + if (index > arraysPerRecord) { + throw new IndexOutOfBoundsException("Index out of bounds: " + index + " of " + arraysPerRecord); + } + return new RecordSubArray(arrayOffset + index); + } + } + + public class RecordSubArray { + private int offset; + + public RecordSubArray(int offset) { + this.offset = offset; + } + + public int[] getData() { + IntegerArray array = new IntegerArray(1); + int ptr = substart.get(offset); + while (ptr >= 0) { + array.add(subdata.get(ptr)); + ptr = subnext.get(ptr); + } + int[] result = array.getAll(); + int half = result.length / 2; + for (int i = 0; i < half; ++i) { + int tmp = result[i]; + result[i] = result[result.length - i - 1]; + result[result.length - i - 1] = tmp; + } + return result; + } + + public void clear() { + substart.set(offset, -1); + } + + public void add(int value) { + int ptr = substart.get(offset); + substart.set(offset, subdata.size()); + subdata.add(value); + subnext.add(ptr); + } + } +}