Quadcap Embeddable Database

com/quadcap/util/DList.java

Go to the documentation of this file.
00001 package com.quadcap.util; 00002 00003 /* Copyright 1997 - 2003 Quadcap Software. All rights reserved. 00004 * 00005 * This software is distributed under the Quadcap Free Software License. 00006 * This software may be used or modified for any purpose, personal or 00007 * commercial. Open Source redistributions are permitted. Commercial 00008 * redistribution of larger works derived from, or works which bundle 00009 * this software requires a "Commercial Redistribution License"; see 00010 * http://www.quadcap.com/purchase. 00011 * 00012 * Redistributions qualify as "Open Source" under one of the following terms: 00013 * 00014 * Redistributions are made at no charge beyond the reasonable cost of 00015 * materials and delivery. 00016 * 00017 * Redistributions are accompanied by a copy of the Source Code or by an 00018 * irrevocable offer to provide a copy of the Source Code for up to three 00019 * years at the cost of materials and delivery. Such redistributions 00020 * must allow further use, modification, and redistribution of the Source 00021 * Code under substantially the same terms as this license. 00022 * 00023 * Redistributions of source code must retain the copyright notices as they 00024 * appear in each source code file, these license terms, and the 00025 * disclaimer/limitation of liability set forth as paragraph 6 below. 00026 * 00027 * Redistributions in binary form must reproduce this Copyright Notice, 00028 * these license terms, and the disclaimer/limitation of liability set 00029 * forth as paragraph 6 below, in the documentation and/or other materials 00030 * provided with the distribution. 00031 * 00032 * The Software is provided on an "AS IS" basis. No warranty is 00033 * provided that the Software is free of defects, or fit for a 00034 * particular purpose. 00035 * 00036 * Limitation of Liability. Quadcap Software shall not be liable 00037 * for any damages suffered by the Licensee or any third party resulting 00038 * from use of the Software. 00039 */ 00040 00041 import java.io.*; 00042 00043 import java.util.Enumeration; 00044 /** 00045 * This class manages a doubly linked list, with head and tail. It's 00046 * actually implemented as a circular list, with a single head pointer, 00047 * and the tail is <code>head.prev</code>.<p> 00048 * 00049 * It would be good to have list primitives that worked well moving items 00050 * from one list to another. moveFront(), in particular, should be able 00051 * to splice an object out of one list and put it at the front of a 00052 * different list.<p> 00053 * 00054 * @author Stan Bailes 00055 */ 00056 public class DList { 00057 /** The number of entries in the list. We are careful to track the 00058 * size accurately. */ 00059 int size; 00060 00061 /** The head of the list, null if the list is empty. Also, an indirect 00062 * pointer to the tail of the list, since the list is linked circularly. */ 00063 DListItem head; 00064 00065 /** 00066 * Construct an empty DList. 00067 */ 00068 public DList() { 00069 head = null; 00070 size = 0; 00071 } 00072 00073 /** 00074 * Make the DList a specified size, adding null entries or deleting 00075 * tail entries. 00076 * 00077 * @param newsize the new size of the list 00078 */ 00079 public void resize(int newsize) { 00080 while (size < newsize) addBack((Object)null); 00081 try { 00082 while (size > newsize) popBack(); 00083 } catch (ListException e) { 00084 // rethrow as exception? 00085 throw new RuntimeException(e.toString()); 00086 } 00087 } 00088 00089 /** 00090 * Return the number of items in the list. 00091 * 00092 * @return the list's size 00093 */ 00094 public int size() { 00095 return this.size; 00096 } 00097 00098 /** 00099 * Add an object to the front of the list. 00100 * 00101 * @param obj the object to add 00102 */ 00103 public DListItem addFront(Object obj) { 00104 DListItem d = new DListItem(obj); 00105 addFront(d); 00106 return d; 00107 } 00108 00109 /** 00110 * Add an object after an existing list item. 00111 * 00112 * @param d the item after which the object is added 00113 * @param obj the object to add 00114 */ 00115 public void addAfter(DListItem d, Object obj) { 00116 DListItem e = new DListItem(obj); 00117 e.next = d.next; 00118 e.next.prev = e; 00119 e.prev = d; 00120 d.next = e; 00121 } 00122 00123 /** 00124 * Add an object before an existing list item. 00125 * 00126 * @param d the item before which the object is added 00127 * @param obj the object to add 00128 */ 00129 public void addBefore(DListItem d, Object obj) { 00130 DListItem e = new DListItem(obj); 00131 e.next = d; 00132 e.prev = d.prev; 00133 e.prev.next = e; 00134 d.prev = e; 00135 } 00136 00137 /** 00138 * Add an object to the back of the list. 00139 * @param obj the object to add 00140 */ 00141 public DListItem addBack(Object obj) { 00142 DListItem d = new DListItem(obj); 00143 addBack(d); 00144 return d; 00145 } 00146 00147 /** 00148 * Access the object at the front of the list. Throw an exception 00149 * if the list is empty. 00150 * 00151 * @return the item at the head of the list 00152 */ 00153 public DListItem head() throws ListException { 00154 if (head == null) throw new ListException("head() of empty list"); 00155 return head; 00156 } 00157 00158 /** 00159 * Access the object at the back of the list. Throw an exception 00160 * if the list is empty. 00161 * 00162 * @return the item at the tail of the list 00163 */ 00164 public DListItem tail() throws ListException { 00165 if (head == null) throw new ListException("tail() of empty list"); 00166 return head.prev; 00167 } 00168 00169 /** 00170 * Remove and return the item at the front of the list. 00171 * 00172 * @return the item at the head of the list 00173 */ 00174 public DListItem popFront() throws ListException { 00175 if (head == null) throw new ListException("popFront() of empty list"); 00176 DListItem d = head; 00177 unlink(d); 00178 if (d == d.next) head = null; 00179 else head = d.next; 00180 return d; 00181 } 00182 00183 /** 00184 * Remove and return the item at the back of the list. 00185 * 00186 * @return the item at the tail of the list 00187 */ 00188 public DListItem popBack() throws ListException { 00189 if (head == null) throw new ListException("popBack() of empty list"); 00190 DListItem d = head.prev; 00191 unlink(d); 00192 if (d == d.next) head = null; 00193 return d; 00194 } 00195 00196 /** 00197 * This method returns a string containing the display representation 00198 * of this list. 00199 */ 00200 public String toString() { 00201 ByteArrayOutputStream bos = new ByteArrayOutputStream(); 00202 show(new PrintStream(bos)); 00203 return bos.toString(); 00204 } 00205 00206 /** 00207 * This method displays a list on the specified output stream. 00208 */ 00209 public void show(PrintWriter os, String delim) { 00210 String delimiter = ""; 00211 os.print("("); 00212 if (head != null) { 00213 boolean started = false; 00214 for (DListItem d = head; !started || d != head; d = d.next) { 00215 if (d.obj == null) continue; 00216 started = true; 00217 os.print(delimiter + d.obj); 00218 delimiter = delim; 00219 } 00220 } 00221 os.println(")"); 00222 } 00223 00224 /** 00225 * This method displays a list using commas as delimiters. 00226 * 00227 * @param os the PrintStream on which to display this list. 00228 */ 00229 public void show(PrintStream os) { 00230 show(new PrintWriter(os), ", "); 00231 } 00232 00233 /** 00234 * This method displays a list using commas as delimiters. 00235 * 00236 * @param os the PrintWriter on which to display this list. 00237 */ 00238 public void show(PrintWriter os) { 00239 show(os, ", "); 00240 } 00241 00242 //------------------------------------------------------------------------ 00243 // private implementation 00244 //------------------------------------------------------------------------ 00245 00246 /** 00247 * Move the specified item, which is assumed to be already in the 00248 * list, to the front of this list. 00249 * 00250 * @param d the item to be placed at the front of this list. 00251 */ 00252 public final void moveFront(DListItem d) { 00253 if (d != head) { 00254 d.next.prev = d.prev; 00255 d.prev.next = d.next; 00256 d.next = head != null ? head : d; 00257 d.prev = head != null ? head.prev : d; 00258 d.prev.next = d; 00259 d.next.prev = d; 00260 head = d; 00261 } 00262 } 00263 00264 /* addFront */ 00265 final void addFront(DListItem d) { 00266 addBack(d); 00267 head = d; 00268 } 00269 00270 /* addBack */ 00271 final void addBack(DListItem d) { 00272 size++; 00273 d.next = head != null ? head : d; 00274 d.prev = head != null ? head.prev : d; 00275 d.prev.next = d; 00276 d.next.prev = d; 00277 if (head == null) head = d; 00278 } 00279 00280 /* unlink */ 00281 public final void unlink(DListItem d) { 00282 if (d != null) { 00283 d.next.prev = d.prev; 00284 d.prev.next = d.next; 00285 if (d == d.next) { 00286 head = null; 00287 } else if (head == d) { 00288 head = d.next; 00289 } 00290 size--; 00291 } 00292 } 00293 00294 /** 00295 * Return an enumeration of all of the items in this list. 00296 */ 00297 public Enumeration elements() { 00298 final DList thislist = this; 00299 final DListItem thisd = head; 00300 00301 return new Enumeration() { 00302 DList dlist = thislist; 00303 DListItem d = thisd; 00304 boolean first = true; 00305 public boolean hasMoreElements() { 00306 return d != null && first || d != dlist.head; 00307 } 00308 public Object nextElement() { 00309 Object obj = d.obj; 00310 d = d.next; 00311 first = false; 00312 return obj; 00313 } 00314 }; 00315 } 00316 }