/* * @(#) IntStorage.java - Abstract class for storage of integers. * (c) 2000-2001 Ivan Maidanski http://ivmai.chat.ru * Freeware class library sources. All rights reserved. ** * Language: Java [pure] * Tested with: JDK v1.1.6 * Last modified: 2001-07-21 11:55:00 GMT+04:00 */ /* * This software is the proprietary information of the author. ** * Permission to use, copy, and distribute this software and its * documentation for non-commercial purposes and without fee is * hereby granted provided that this copyright notice appears in all * copies. ** * This software should not be modified in any way; any found bug * should be reported to the author. ** * The author disclaims all warranties with regard to this software, * including all implied warranties of merchantability and fitness. * In no event shall the author be liable for any special, indirect * or consequential damages or any damages whatsoever resulting from * loss of use, data or profits, whether in an action of contract, * negligence or other tortuous action, arising out of or in * connection with the use or performance of this software. */ package ivmai.storage; /** * Abstract class for storage of integers (optimized). ** * @version 2.0 * @author Ivan Maidanski ** * @since 2.0 */ public abstract class IntStorage extends Storage { /** * NOTE: links must be != null (length > 1), links[1] = * emptyLocation() - 1. */ protected transient int[] links; public IntStorage(int initialLength) { if (initialLength <= 1) initialLength = -1 >>> 1; this.links = new int[initialLength]; } public final int emptyLocation() { return this.links[1] + 1; } /** * NOTE: value must be of Integer and insertion after prevLoc must * be possible in this storage (according to the semantics), * otherwise ArrayStoreException is thrown. Enough capacity ensured * before any changes. Result is the location of the inserted value. * Observers notification is performed. Must be synchronized * outside. */ public final int insertAt(int prevLoc, int emptyLocation, Object value) throws IllegalArgumentException, ArrayStoreException { if (value instanceof Integer) return insertIntAt(prevLoc, emptyLocation, ((Integer)value).intValue()); if (prevLoc != 0 && !isValidAt(prevLoc > 0 ? prevLoc : -prevLoc)) throw new IllegalArgumentException("prevLoc: " + Integer.toString(prevLoc)); if (emptyLocation < 0 || isValidAt(emptyLocation)) throw new IllegalArgumentException("emptyLocation: " + Integer.toString(emptyLocation)); throw new ArrayStoreException("prevLoc: " + Integer.toString(prevLoc) + ", emptyLocation: " + Integer.toString(emptyLocation) + ", value: " + (value != null ? value.toString() : "null")); } /** * NOTE: If prevLoc != 0 and (prevLoc > 0 ? prevLoc : -prevLoc) is * an "empty" (including negative) location then * IllegalArgumentException is thrown. If 0 > emptyLocation or * emptyLocation is not an "empty" location then * IllegalArgumentException is thrown. emptyLocation is the location * of the inserted value unless emptyLocation == 0 (means any empty * location). If insertion is impossible then ArrayStoreException is * thrown. Enough capacity is ensured before any changes. New value * is inserted as a first child node of -prevLoc (if 0 >= prevLoc) * or as a next sibling node of prevLoc (if prevLoc > 0). Result is * the location of the inserted value. Alters storage state. The * effectiveness is constant (typically). Observers notification is * performed. Must be synchronized outside. */ public abstract int insertIntAt(int prevLoc, int emptyLocation, int value) throws IllegalArgumentException, ArrayStoreException; /** * NOTE: If 0 >= location then IllegalArgumentException is thrown. * value must be either null (always accepted) or of Integer * (otherwise ArrayStoreException is thrown), result (oldValue) is * either null or of Integer. If operation is impossible (according * to the storage semantics) then ArrayStoreException is thrown. * Enough capacity ensured before any changes. Alters storage state. * Observers notification is performed. Must be synchronized * outside. */ public final Object setAt(int location, Object value) throws IllegalArgumentException, ArrayStoreException { int intOldValue = getIntAt(location); Object oldValue = null; if (intOldValue != 0 || isValidAt(location)) oldValue = new Integer(intOldValue); if (value == null) { removeIntAt(location); return oldValue; } if (value instanceof Integer) { setIntAt(location, ((Integer)value).intValue()); return oldValue; } if (location <= 0) throw new IllegalArgumentException("location: " + Integer.toString(location)); throw new ArrayStoreException("location: " + Integer.toString(location) + ", oldValue: " + (oldValue != null ? oldValue.toString() : "null") + ", value: " + value.toString()); } /** * NOTE: If 0 >= location then IllegalArgumentException is thrown. * If operation is impossible (according to the storage semantics) * then ArrayStoreException is thrown. Enough capacity ensured * before any changes. Alters storage state. Result is the previous * value at location (or 0 if location was "empty"). The * effectiveness is constant (typically) or logarithmic. Observers * notification is performed. Must be synchronized outside. */ public abstract int setIntAt(int location, int value) throws IllegalArgumentException, ArrayStoreException; /** * NOTE: If 0 >= location then IllegalArgumentException is thrown. * If location is "empty" then nothing is performed and 0 is * returned. Alters storage state. Result is the removed value at * location. Observers notification is performed. Must be * synchronized outside. */ public abstract int removeIntAt(int location) throws IllegalArgumentException; /** * NOTE: Result != null if and only if location is not "empty". If * location is not "empty" then it is "valid". Storage state is not * altered. Requires no synchronization. */ public final Object getAt(int location) { Object value = null; int intValue; if ((intValue = getIntAt(location)) != 0 || isValidAt(location)) value = new Integer(intValue); return value; } /** * NOTE: If location is "empty" then 0 is returned. Storage state is * not altered. The effectiveness is constant. Requires no * synchronization. */ public abstract int getIntAt(int location); /** * NOTE: If value is not instanceof Integer then 0 is returned. Must * be synchronized outside. */ public final int locationOf(Object value, int prevLocation, boolean forward) throws IllegalArgumentException { if (value instanceof Integer) prevLocation = locationOfInt(((Integer)value).intValue(), prevLocation, forward); else if (prevLocation != 0) { parentLocation(prevLocation); prevLocation = 0; } return prevLocation; } /** * NOTE: If prevLocation != 0 and prevLocation is an "empty" * location then IllegalArgumentException is thrown. Search is * started after/before prevLocation. Result is either 0 (no more * values) or a (not "empty") location of the first found element, * which is equal to value. If (prevLocation == 0 or prevLocation is * "valid") and result != 0 then result is a "valid" location. * Storage state is not altered. The effectiveness is linear, * logarithmic (typically) or constant. Must be synchronized * outside. */ public abstract int locationOfInt(int value, int prevLocation, boolean forward) throws IllegalArgumentException; /** * NOTE: If value is not instanceof Integer then 0 is returned. Must * be synchronized outside. */ public final int findLessGreater(Object value, boolean greater, int prevLocation, boolean forward) throws IllegalArgumentException { if (value instanceof Integer) prevLocation = findLessGreaterInt(((Integer)value).intValue(), greater, prevLocation, forward); else if (prevLocation != 0) { parentLocation(prevLocation); prevLocation = 0; } return prevLocation; } /** * NOTE: If prevLocation != 0 and prevLocation is an "empty" * location then IllegalArgumentException is thrown. Else search is * started after/before prevLocation. Result is either 0 (no more * values) or a (not "empty") location of the first/next found * element, which is (greater ? 'greater' : 'less') than value. * Storage state is not altered. The effectiveness is linear, * logarithmic (typically) or constant. Must be synchronized * outside. */ public abstract int findLessGreaterInt(int value, boolean greater, int prevLocation, boolean forward) throws IllegalArgumentException; /** * NOTE: Must be synchronized outside. */ public Object clone() { IntStorage storage = (IntStorage)super.clone(); storage.links = (int[])storage.links.clone(); return storage; } /** * NOTE: Shallow check for integrity of this object. Must be * synchronized outside. For debug purpose only. */ public void integrityCheck() { super.integrityCheck(); if (this.links == null) throw new InternalError("links: null"); } }