package js.tinyvm; import java.io.IOException; import java.util.ArrayList; import java.util.Iterator; import js.tinyvm.io.IByteWriter; import js.tinyvm.io.IOUtilities; /** * Record table. */ public class RecordTable<T extends WritableData> extends WritableDataWithOffset { /** * Descriptive name of this record table. */ private String _name; /** * Allow duplicates in table? */ private boolean _duplicates; /** * Align output? */ private boolean _align; /** * List of all writable element. */ private ArrayList<T> _list; /** * Length of output. */ private int _length; /** * Constructor. * * @param name description of this record table * @param allowDuplicates allow duplicates? * @param align align output? */ public RecordTable (String name, boolean allowDuplicates, boolean align) { assert name != null: "Precondition: name != null"; _name = name; _duplicates = allowDuplicates; _align = align; _list = new ArrayList<T>(); _length = -1; } // // public interface // /** * Add a writable element. * * @param element */ public void add (T element) { assert element != null: "Precondition: element != null"; if (_duplicates || !_list.contains(element)) { _list.add(element); } } /** * Get writable element by its index. * * @param index index */ public T get (int index) { assert index >= 0 && index < size(): "Precondition: index >= 0 && index < size()"; T result = _list.get(index); assert result != null: "Postconditon: result != null"; return result; } /** * Get index of writable element. * * @param element * @return index or -1 if not found */ public int indexOf (T element) { assert element != null: "Precondition: element != null"; return _list.indexOf(element); } /** * Iterator. */ public Iterator<T> iterator () { Iterator<T> result = _list.iterator(); assert result != null: "Postconditon: result != null"; return result; } /** * Number of entries. */ public int size () { return _list.size(); } // // Writable interface // /** * Dump all elements. */ public void dump (IByteWriter writer) throws TinyVMException { assert writer != null: "Precondition: writer != null"; try { boolean pDoVerify = TinyVMConstants.VERIFY_LEVEL > 0; for (Iterator<T> iter = _list.iterator(); iter.hasNext();) { WritableData pData = iter.next(); int pLength = pData.getLength(); int pPrevSize = writer.offset(); pData.dump(writer); if (pDoVerify) { if (writer.offset() != pPrevSize + pLength) { if (pData instanceof RecordTable) { // _logger.log(Level.SEVERE, "Aligned sequence: " // + ((RecordTable) pData)._align); } throw new TinyVMException("Bug RT-1: Written=" + (writer.offset() - pPrevSize) + " Length=" + pLength + " Class=" + pData.getClass().getName()); } } } if (_align) { IOUtilities.writePadding(writer, 4); } } catch (IOException e) { throw new TinyVMException(e.getMessage(), e); } } /** * Length. */ public int getLength () throws TinyVMException { if (_length == -1) { _length = 0; for (Iterator<T> iter = _list.iterator(); iter.hasNext();) { _length += iter.next().getLength(); } // _logger.log(Level.INFO, "length of " + _name + ": " + _length); if (_align) { _length = IOUtilities.adjustedSize(_length, 4); } } return _length; } /** * Init offset of record table and all of its elements. */ public void initOffset (int startOffset) throws TinyVMException { // _logger.log(Level.INFO, "init offset of " + _name + ": " + // startOffset); super.initOffset(startOffset); for (Iterator<T> iter = _list.iterator(); iter.hasNext();) { WritableData element = iter.next(); if (element instanceof WritableDataWithOffset) { ((WritableDataWithOffset) element).initOffset(startOffset); } startOffset += element.getLength(); } } // private static final Logger _logger = Logger.getLogger("TinyVM"); }