/* * citygml4j - The Open Source Java API for CityGML * https://github.com/citygml4j * * Copyright 2013-2017 Claus Nagel <claus.nagel@gmail.com> * * 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.citygml4j.util.xml; import java.lang.reflect.Array; public class ArrayBuffer<T> { private final static int DEFAULT_SIZE = 512; private T[] items; private ArrayBuffer<T> next; private ArrayBuffer<T> previous; private int ptr; @SuppressWarnings("unchecked") protected ArrayBuffer(Class<T> c, int size, ArrayBuffer<T> previous) { items = (T[])Array.newInstance(c, size); this.previous = previous; } protected ArrayBuffer(Class<T> c, int size) { this(c, size, null); } protected ArrayBuffer(Class<T> c, ArrayBuffer<T> previous) { this(c, DEFAULT_SIZE, previous); } protected ArrayBuffer(Class<T> c) { this(c, DEFAULT_SIZE, null); } public int size() { return items.length; } public int currentPtr() { return ptr; } public void decrementPtr() { if (ptr > 0) ptr--; } public ArrayBuffer<T> nextBuffer() { return next; } public ArrayBuffer<T> previousBuffer() { return previous; } public void dropPreviousBuffer() { previous = null; } @SuppressWarnings({ "unchecked", "rawtypes" }) public ArrayBuffer<T> appendBuffer() { ArrayBuffer<T> next = new ArrayBuffer(items.getClass().getComponentType(), items.length, this); this.next = next; return next; } public ArrayBuffer<T> rewindToHeadBuffer() { ArrayBuffer<T> head = this; ptr = 1; while (head.previous != null) { head = head.previous; head.ptr = 1; } return head; } public ArrayBuffer<T> dropBuffer() { if (previous == null) return this; ArrayBuffer<T> previous = this.previous; previous.next = null; return previous; } public void push(T item) { if (ptr == items.length) throw new IllegalStateException("Cannot push onto a full buffer."); items[ptr++] = item; } public T peek() { if (ptr == 0) return previous != null ? previous.peek() : null; return items[ptr - 1]; } public T pop() { if (ptr == 0) throw new IllegalStateException("Cannot pop from on an empty buffer."); T tmp = items[--ptr]; items[ptr] = null; return tmp; } public T next(boolean release) { if (ptr == 0) throw new IllegalStateException("Cannot call next on an empty buffer."); T tmp = items[ptr -1]; if (release) items[ptr - 1] = null; ptr++; return tmp; } }