summaryrefslogtreecommitdiff
path: root/src/aapl
diff options
context:
space:
mode:
Diffstat (limited to 'src/aapl')
-rw-r--r--src/aapl/.gitignore2
-rw-r--r--src/aapl/COPYING20
-rw-r--r--src/aapl/ChangeLog562
-rw-r--r--src/aapl/Makefile.am7
-rw-r--r--src/aapl/README6
-rw-r--r--src/aapl/astring.h862
-rw-r--r--src/aapl/avlbasic.h66
-rw-r--r--src/aapl/avlcommon.h1637
-rw-r--r--src/aapl/avlibasic.h68
-rw-r--r--src/aapl/avlikeyless.h65
-rw-r--r--src/aapl/avlimap.h78
-rw-r--r--src/aapl/avlimel.h80
-rw-r--r--src/aapl/avlimelkey.h77
-rw-r--r--src/aapl/avliset.h76
-rw-r--r--src/aapl/avlitree.h79
-rw-r--r--src/aapl/avlkeyless.h59
-rw-r--r--src/aapl/avlmap.h75
-rw-r--r--src/aapl/avlmel.h75
-rw-r--r--src/aapl/avlmelkey.h72
-rw-r--r--src/aapl/avlset.h71
-rw-r--r--src/aapl/avltree.h74
-rw-r--r--src/aapl/bstcommon.h815
-rw-r--r--src/aapl/bstmap.h114
-rw-r--r--src/aapl/bstset.h87
-rw-r--r--src/aapl/bsttable.h85
-rw-r--r--src/aapl/bubblesort.h95
-rw-r--r--src/aapl/buffer.h60
-rw-r--r--src/aapl/compare.h269
-rw-r--r--src/aapl/dlcommon.h791
-rw-r--r--src/aapl/dlist.h65
-rw-r--r--src/aapl/dlistmel.h72
-rw-r--r--src/aapl/dlistval.h72
-rw-r--r--src/aapl/insertsort.h95
-rw-r--r--src/aapl/mergesort.h141
-rw-r--r--src/aapl/quicksort.h186
-rw-r--r--src/aapl/resize.h345
-rw-r--r--src/aapl/rope.h237
-rw-r--r--src/aapl/sbstmap.h122
-rw-r--r--src/aapl/sbstset.h95
-rw-r--r--src/aapl/sbsttable.h94
-rw-r--r--src/aapl/svector.h1351
-rw-r--r--src/aapl/table.h253
-rw-r--r--src/aapl/vector.h1190
-rw-r--r--src/aapl/version.mk2
44 files changed, 10747 insertions, 0 deletions
diff --git a/src/aapl/.gitignore b/src/aapl/.gitignore
new file mode 100644
index 00000000..b336cc7c
--- /dev/null
+++ b/src/aapl/.gitignore
@@ -0,0 +1,2 @@
+/Makefile
+/Makefile.in
diff --git a/src/aapl/COPYING b/src/aapl/COPYING
new file mode 100644
index 00000000..e246673a
--- /dev/null
+++ b/src/aapl/COPYING
@@ -0,0 +1,20 @@
+
+Copyright (c) 2001-2016 Adrian Thurston <thurston@colm.net> et al.
+
+Permission is hereby granted, free of charge, to any person obtaining a copy of
+this software and associated documentation files (the "Software"), to deal in
+the Software without restriction, including without limitation the rights to
+use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
+of the Software, and to permit persons to whom the Software is furnished to do
+so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in all
+copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+SOFTWARE.
diff --git a/src/aapl/ChangeLog b/src/aapl/ChangeLog
new file mode 100644
index 00000000..483ad825
--- /dev/null
+++ b/src/aapl/ChangeLog
@@ -0,0 +1,562 @@
+Aapl 2.14 - March 17, 2006
+==========================
+ -Added a transfer function to the double list. This function should supersede
+ the use of shallowCopy + abandon. In the by-value list the destination list
+ is emptied first.
+ -Added a transfer function to the Avl tree.
+ -All double lists and Avl trees now implement deep copies in the
+ operator=(...) functions and copy constructors. Previously only the by-value
+ versions of these structures would do deep copies.
+ -Removed the deep and shallow copy functions from the double lists and Avl
+ trees. These structures should now be consistent accross all variants except
+ for the fact that the by-value versions delete elements in destructors and
+ when overwriting and the others simply abandon their elements (which may not
+ be allocated on the stack).
+
+Aapl 2.13 - Jan 25, 2006
+========================
+ -The vector and binary search table constructors that set an initial amount
+ of allocation have been removed. They have been replaced with constructors
+ that insert initial values, which is a more common task and is a more
+ intuitive use for contructors.
+ -Removed the String class. Better to use the stl string class. Aapl::String
+ does not provide any real advantage over the STL version. Aapl::String has
+ not been heavily tested and does not have very much functionality.
+ -Removed the "tiny" versions of templates. These templates had functionality
+ reduced in the interest of reducing compiled binary size. These templates
+ did not find any real world use, nor were they heavily tested.
+ -Removed the "simple" versions of vectors. These should be implemented as
+ template specializations, not new classes. May be brought back as such in
+ the future.
+ -Added vinsert and vremove routines for accessing the insert and remove of
+ the underlying vector of binary search tables. Previously, these were
+ accessed by prefixing the insert call with the vector base class name,
+ however this method is somewhat inconvenient, because it either requires all
+ the template arguments to be given or an additional typedef to be made.
+ Prefixing the call with the letter v is simpler.
+
+Aapl 2.12 - May 15, 2005
+========================
+ -Documentation updates to trees, lists, compare classes, binary search tables
+ and various other places.
+ -Added iterator documentation and example.
+ -Added proper includes for all examples, which now all compile.
+ -Table comparisons now properly inherit the CompareT class, enabling table
+ comparisons to call non-static element compare classes.
+ -Removed the Deque structure. This structure was never used, incomplete and
+ poorly tested. In most problems for which it is a candidate (large
+ collections of objects in sequential ordering that are not required to be in
+ contiguous memory), a simple replacement can easily be implemented with a
+ small amount of code. Rather than be allowed to go unused and unmaintained,
+ it is removed.
+ -In the AvlTreeEl structures for Maps and Sets, getKey can be const.
+ -Removed the non-standard malloc include.
+
+Aapl 2.11 - May 30, 2004
+========================
+ -Moved from ints to longs for most integer values to get 64 bit numbers on 64
+ bit machines. Fixes alignment problems on 64 bit machines.
+ -Added AvliBasic, the linked version of the basic tree where the entire
+ element is the key.
+ -Updated documentation.
+
+Aapl 2.10 -- Feb 5, 2004
+========================
+ -Fixes for two-stage lookup. Compiles with gcc-3.4
+ Details at http://gcc.gnu.org/onlinedocs/gcc/Name-lookup.html#Name%20lookup
+ -Fixed wrong Vector::Iter::pos() routines.
+ -FsmGraph code removed from aapl, as an increasing amount of diverse
+ specialization is required in applications. No longer feels like a general
+ purpose template.
+
+Aapl 2.9 -- Dec 8, 2003
+=======================
+ -Rewrote Deque to look and behave more like the rest of Aapl. Split it into
+ Deque and DequeSimp. Deque supports complex classes with constructors and
+ destructors. DequeSimp is for simple classes that can be coppied with
+ memcpy. Wrote stress tests for both.
+ -SVector::makeRawSpaceFor fixed to detach from the vector when the current
+ storage is shared. This affected SBstTable::insert() routines and caused
+ them to modify shared data, instead of behaving like copy on write as they
+ should.
+ -Tiny templates renamed to be consistent with the non-tiny templates. The
+ tiny versions now only have a T prepended to the name, the second character
+ is no longer lowercased. This changes Tavl* to TAvl*, TdList* to TDList* and
+ TsVect* to TSVect*.
+ -Removed AvlPmap, AvlPset, AvliPmap, and AvliPset. Rationale is that these
+ are too application specific. They require a pointer as the key (not
+ anything that dereferences the pointer) and so do not generalize very well.
+ Due to their lack of generality, they belong in application code. They
+ allowed a savings in code size when many instantiations were necessary,
+ however, the savings was only slightly better than TAvlTree.
+ -Test programs split into stress tests and non stress tests. All stress tests
+ run indefinitely as long as they don't encounter an error condition, in
+ which case they terminate by an assertion failure. They can be given a time
+ limit to run for by specifying the number of seconds on the command line.
+ -FsmGraph given repetition operators for repeating a machine n times.
+ -Concatenation operator accepts an optional list of states to draw the epsilon
+ transition instead of the from graph's final state set.
+ -Useless shared table header template parameter removed.
+
+Aapl 2.8.2 -- Aug 18, 2003
+==========================
+ -AvlSet::Iter and DListVal::Iter data access operators (*, ->) now return the
+ node in the tree, rather than value. This is to make all iterator behaviour
+ consistent: return the element. This also allows for O(1) statements like
+ tree.detach( iter );
+ -DList and DListMel and Avl trees that are not sets or maps no longer do a
+ deep copy in the copy constructor and assignement operator. This is to stay
+ consistent with the fact that these lists and trees are not responsible for
+ managing the memory of the elements they contain.
+ -Table compare split into static and non-static versions. Default is the
+ static version, which compiles out the 'this' pointer. If an item compare
+ requires access to class data, the CmpTableNs can be used.
+ -The user's Fsm class is now required as a template parameter to FsmTrans,
+ FsmState and FsmGraph.
+ -All callbacks moved into FsmGraph class to allow the access of user data in
+ FsmGraph.
+ -Added callbacks for state creation and destruction to FsmGraph.
+ -EpsilonOp now takes a list of fsms to draw ops to. Allows the merging in of
+ several machines using only a single invocation of the NFA to DFA algorithm.
+ -FsmKeyOps is now expected to be a base class of the derived fsm class (ie a
+ sibling of FsmGraph).
+ -In transition lists are encapsulated in a class with an iterator.
+ -Unused leavingFsm parameter to starOp and concatOp removed.
+ -Fixed documentation building warnings.
+ -Documented iterator classes.
+
+Aapl 2.8.1 -- Jun 11, 2003
+==========================
+ -All iterator endpoint test functions have been renamed.
+ Iter::more() -> Iter::lte()
+ Iter::done() -> Iter::end()
+ Iter::revMore() -> Iter::gtb()
+ Iter::revDone() -> Iter::beg()
+ The rationale is that it is not obvious that more() and done() are direction
+ specific. It is more clear that lte() (less than end) needs to be changed to
+ gtb() (greater than beginning) when reversing the direction of a traversal.
+ -All avl tree element classes have been renamed to make element names
+ consistent.
+ AvlNode -> AvlTreeEl
+ AvliNode -> AvliTreeEl
+ AvlMapNode -> AvlMapEl
+ AvliMapNode -> AvliMapEl
+ AvlSetNode -> AvlSetEl
+ AvliSetNode -> AvliSetEl
+ TavlNode -> TavlTreeEl
+ TavliNode -> TavliTreeEl
+ TavlMapNode -> TavlMapEl
+ TavliMapNode -> TavliMapEl
+ TavlSetNode -> TavlSetEl
+ TavliSetNode -> TavliSetEl
+ AvlPmapNode -> AvlPmapEl
+ AvliPmapNode -> AvliPmapEl
+ AvlPsetNode -> AvlPsetEl
+ AvliPsetNode -> AvliPsetEl
+ FsmSDNode -> StateDictEl
+ AvlTree::nodeCount -> AvlTree::treeSize
+ -All binary search table and avl tree classes now inherit from the compare
+ class. This allows the compare function to be non-static and for it make use
+ of state that is common to the data structure.
+ -BstTable(int allocLen) no longer uses Vector::setAsNew and therefore Element
+ does not require Element() constructor.
+
+Aapl 2.8.0 -- Jan 5, 2003
+=========================
+ -Switched to the LGPL.
+ -Added get() to String class. Returns the data ptr.
+ -Added operator<<(ostream &, String&). Previously relied on the implicit
+ cast to char* which did not work all the time.
+ -Iterators renamed and rewritten. The new style for checking if the iterator
+ is done is to call more() or done() if moving forwards and revMore() or
+ revDone() if moving backwards. Iterators now have first() and last() calls
+ for checking if the iterator is on the first and last element. The next()
+ and prev() calls now return the next and previous. THEY NO LONGER MOVE THE
+ ITERATOR FORWARD OR BACKWARDS. Increment() and decrement() are now available
+ for moving the iterator.
+ -Various fixes for the intel C++ compiler.
+ -Shared vector table header renamed from TabHead to STabHead.
+ -Started Tiny DList, Tiny VectSimp, Tiny SVectSimp, and Tiny AvlTree. These
+ classes reduce final executable size by reusing core code across
+ instantiations with different types. They can be used identically to the
+ non-tiny counterpart if only iterators are used for accesing the structure.
+ The catch is that the underlying data structures have generic pointers that
+ are not directly usable without casting.
+
+Aapl 2.7.0 -- Dec 20, 2002
+==========================
+ -DoubleList::length -> DoubleList::listLen and added length() function. This
+ is to keep consistent with vectors and strings.
+ -Sorting routines now inherit from the compare class and use a non-static
+ compare routine. This lets the compare have state. This will likely be
+ extended to all structures that use a compare class.
+ -Constructor added to string that does sprintf style formatting.
+ -Routines added to string for setting from a char*, len pair.
+ -Table class (used by vector) member length changed to tabLen and the
+ the length() const routine added. This makes SVector a more easy substitute
+ for Vector. Previously the length member was an int in Vector and a function
+ call in SVector. Now it is a function in both.
+ -String::str -> String::data and String::getLen() -> String::length() to make
+ access of string data consistent with access of table data.
+ -Binary search tweaked to use a shift in place of a divide.
+ -FsmGraph code from rlfsm moved back into Aapl and Reglang FSM terminated.
+ Now that the graph code has been separted from the priority and action code,
+ the base template is leaner and more generalized. It now fits well in Aapl
+ as a generic programming construct. Also, rlfsm was not enjoying much
+ exposure and no sense in letting the fsmgraph code fight for itself. The
+ relevant fsmgraph changes since the split at 2.5.0 follow:
+ -Support of arbitrary key types for graph completed.
+ -Dramatic performance improvements in basic fsm operations. Kleen star,
+ union, and concatenation do not require a walk of all states and can go very
+ fast when there is no overlap between the machines.
+ -Fsm Range transitions implemented. Can now efficiently specify machines that
+ span very large ranges.
+ -More efficient partition based fsm minimization implemented. Algorithm is
+ similar to Hopcroft's minimization algorithm.
+ -Fsm Graph split into base code that implements FSM operations, NFA-DFA
+ conversion and minimization and a superclass that implements priority and
+ action setting. Allows the base code to be easily reused for other
+ applications that require different state and transition properties. The
+ superclass is left as user code in Ragel and is not included in Aapl.
+ -Can now have various classes of named entry points in an fsm graph for
+ maintaining entry other than the start state. This is useful for making
+ actions that jump into or call various named locations in the machine.
+ -Various bugs in fsm graph code fixed.
+
+Aapl 2.6.0 -- Nov 4, 2002
+=========================
+ -Added AvlPmap, AvlPset, AvliPmap and AvliPset classes. These are
+ instantiations of AvlMap and AvlSet with void* types and a small inline
+ wrapper interface for doing type conversions. If many different maps are
+ used for storing integers or pointers then these classes can cut down on
+ code bloat.
+ -Added AvlTree::remove, which will detach and delete elements from the tree.
+ -Removed set, unSet and isSet from AvlTree. These functions are redundant and
+ clutter the interface.
+ insert/remove/find functionality just for convenience. Prefer to remove them
+ than to clutter the interface with inconsistently named functions.
+ -Fixed the return type of BstTable::removeMulti. It should be an int (not
+ bool) because it returns the number of items removed.
+ -Added SVector and SVectSimp: implicitly shared copy-on-write vectors.
+ -Added ResizeCtLin: Identical to ResizeLin, except the step is specified at
+ compile time using a template argument.
+ -Removed deepCopy from the classes that by default behave as a deep copy.
+ Found the duplicate function to make it confusing as to how the structure's
+ operator= behaves.
+ -File rename of shrstr to astring, to make it easier to find.
+ -BsTable renamed to BstTable to stay consistenty named with the other Bst
+ classes. Also renamed the file from bstable.h to bsttable.h for consistency.
+ -Compare class routines are now Compare::compare (used to be
+ Compare::Compare). This is to keep with the lowercase function name
+ convention.
+ -Added the insertion of whole elements to BsTable and BstMap (already exists
+ for BstMap).
+ -Added the insertion of entire other tables to BsTable, BstMap and BstSet.
+ -The getKey function for binary search table must now be const as well as the
+ existing requirement of returning a const object. This was needed for the
+ insertion of whole elements so the requirement was made for all
+ insert/remove/find routines in order to stay consistent.
+ -Removed set, unSet and isSet from BstSet. These functions duplicated the
+ insert/remove/find functionality just for convenience. Prefer to remove them
+ than to clutter the interface with inconsistently named functions.
+
+Aapl 2.5.4 -- Sept 20, 2002
+===========================
+ -All of Aapl is now in the Aapl:: namespace, which is disabled by default. It
+ can be turned on by defining #define AAPL_NAMESPACE.
+ -Mergesort uses only memcpy to move data around, instead of the inconsistent
+ use of the = operator. Classes that are sorted have no way of knowing that
+ they are being moved around in mem.
+ -Implemented QuickSort, BubbleSort and Insertion Sort.
+ -QuickSort uses InsertSort when the array being sorted is small.
+ -MergeSort uses BubbleSort when the array be sorted is small.
+ -Implemented an implicitly shared string class.
+
+Aapl 2.5.3 -- Aug 17, 2002
+==========================
+ -Much work done on the user documentation.
+ -AvlMap and AvlSet destructors now delete all elements. The idea is that
+ these classes manage memory on behalf of the user, so cleanup. Also, a deep
+ copy will cause the existing contents to be deleted. The remaining avl trees
+ do not assume ownership of element and thus do not delete anything.
+
+Aapl 2.5.2 -- Aug 14, 2002
+==========================
+ -Bug fixed in Vector::replace. When overwriting data without overwriting up
+ to the end of the vector or extending it, the vector would shrink in size.
+ This is because the tableLength was getting set to the end of the overwrite
+ region in every case.
+ -Bug fixed in empty and abandon of Avli* trees. They now clear the list head
+ and tail pointers.
+ -shallowCopy, deepCopy and the = operator were added to double list, vector,
+ and avl tree. The = operator implements the deep copy functionality.
+ -The Vector class was heavily rewritten. The purpose of the rewrite is to
+ have a vector that does not require the class that it contains to have a
+ default constructor. In many cases adding a default constructor violates the
+ design of a class. A class should not be required to have a default
+ constructor just because it is going into a vector. To have this feature,
+ the new vector differs from the old vector in a few ways. If the vector is
+ instructed to add elements off the end of the vector then undefined
+ behaviour results. The new vector will not implictly create new items.
+ Also, new items cannot be added to the list by giving a null data pointer.
+ Instead insertNew, appendNew, etc. can be used.
+ -DListVal destructor now deletes all elements. The reasoning is that DListVal
+ manages elements and so it should clean up after itself.
+ -remove routines added to double list classes. They are the same as detach
+ except they also delete elements.
+ -Default down resize of ResizeRunTime fixed: now is Exponential as is the up
+ resizing.
+
+Aapl 2.5.1 -- Aug 9, 2002
+=========================
+ -Class and function descriptions from doc/*.txt moved to source code in
+ doxygen format.
+ -Iterators slimmed down in anticipation of the more coplicated iterator for
+ avltree. Iterators now provide basic moving forward and backward and looking
+ at current value. Looking ahead and moving ahead by more than one space is no
+ longer supported.
+ -Assignment operator of all iterators now return a reference to this.
+ -Implemented iterator for avl tree (non Avli* trees). The iterator can be
+ started on either end and can move forwards or backwards. Does not support
+ trees larger than 32 element in height (should be sufficient).
+
+Aapl 2.5.0 -- Jun 22, 2002
+==========================
+ -Doxygen docs started.
+ -ExpnResize -> ResizeExpn, ConstResize -> ResizeConst, LinResize -> ResizeLin
+ Name changes that will keep a lexographically sorted list of classes in good
+ order.
+ -StrCmp -> CmpStr, OrdCmp -> CmpOrd, TableCmp -> CmpTable for same reason as
+ above.
+ -BstTable fixed so that Resize class is passed to underlying vector.
+ -Pdp Endianness support removed as it is untested. Don't have a pdp endian
+ machine on which to test.
+ -cc file extension changed to cpp for better portability.
+
+ ******** Aapl split out into three libs: Aapl, Autil, Reglang FSM ***********
+
+ Aapl is: A generic programming template library. Aapl is an alternative to
+ the STL. It currently contains Linked List, Avl Tree, Vector, Binary Search
+ Table, Double Ended Queue, Merge Sort.
+
+ Autil is: A library of simple utility classes that are easy to come by.
+ Autil contains paramater parser, byte ordering facilities, character
+ classes.
+
+ Reglang FSM is: A template library of algorithms and data structures for
+ compiling state machines from regular languages.
+
+Aapl 2.4.1 -- May 4, 2002
+=========================
+ -Fixed automatic dependencies, were not working correctly.
+ -C++ standards compliant I/O and namespaces.
+
+Aapl 2.4.0 -- May 3, 2002
+=========================
+ -Vector now uses malloc, realloc and free so the performance gain of
+ of using realloc over new, memcpy, delete in resizing can be realized.
+ -Buffer Renamed to VectSimp. The name buffer is way overused and brings
+ preconceptions with it. VectSimp now has the same functionality as vector.
+ It is a 'flavour' of vector. The main difference is that is does not use
+ copy constructors/destructors. It uses memcpy to put data in and as a result
+ can go much faster. The idea is that it is used on 'simple data'.
+ -The type of resizing that vector uses is no longer controlled by including
+ different files and using different names (ie, VectorC no longer exists).
+ The old style (last seen in v1.1.2) of using a template parameter has been
+ resurrected. It was previously removed because it caused very long symbol
+ names. That problem has been fixed by making the class that goes into that
+ template parameter not a template. It is a normal class and as such will
+ cause symbol names to increase a constant amount. The old way was the class
+ was a template taking type T so that essentially doubled the length of the
+ symbol. The purpose of this change is to eliminate the many files required
+ to have all the different resizing types. Any class that inherits from
+ vector needs to have many flavours in order to support the different
+ resizing types and that gets ugly. Providing resizing options to the bstable
+ classes would require 30 files.
+ -Default step for linear resizing is changed from 10 to 256.
+ -FsmGraph structure supports Default transitions. Default transitions can be
+ used in place of newing up a transition for every char in the alphabet in
+ order to get the 'dot' and 'dot star' fsms. It is incredibly more efficient
+ and will make large integer alphabets feasible.
+ -The conversion from FsmGraph to FsmMachine is now moved into a class called
+ FsmBuild.
+ -FsmMachine no longer stores transition indices as a linear chunk. Now
+ stores key, index pairs. This will facilitate using FsmMachine with very
+ large alphabets because large index tables will not be allocated. when there
+ is great variation in transition keys.
+ -FsmMachine stores only offsets, no pointers.
+ -Aapl assert is removed in favour of using system assert. Can't see a reason
+ to duplicate system include.
+ -Lowercased the interface to BsTable.
+ -Makefiles use automatic dependencies.
+ -AvlTree interface was lowercased/consolodated.
+ -Large switches at the top of *common.h files were removed. The defines were
+ put into the files that include the common files.
+ -BsTable interface was lowercased/consolodated.
+ -BstSet replaces VectSet.
+ -Configure script allows you to specify what objects to build using the
+ --enable-src option
+ -AvlTree verification is moved out of the main tree and into the test cases.
+
+Aapl 2.3.1 -- March 25, 2002
+============================
+ -Fixed errors in the event loop with respect to unregistering.
+ -Added Signal handling to event loop.
+ -Breaking out of event loop is now much cleaner.
+ -Added CONTENTS file.
+ -Removed trivial class File. I think most would rather code this kind
+ of stuff on their own, or use a more featureful library.
+ -Removed Data base class. Again, kind of trivial. Better left to the user.
+ -DList::detach{Front,End} -> DList::detach{First,Last}. This change was
+ made in order to be more consistent with the iterator convention of
+ using first, last, sfirst, slast.
+ -Wrote documentation for double list.
+
+Aapl 2.3.0 -- March 19, 2002
+============================
+ IMPORTANT: This release marks the beginning of a major change in the
+ naming conventions. Previously, naming conventions had function names
+ starting with an upper case. The member functions will slowly be changed
+ to start with a lower case. Some functions names will also be changed
+ to follow the conventions in doc/conventions.txt. Vector and DList have
+ already been changed.
+
+ These changes are being made to make aapl more compatible with existing
+ template libraries and to provide a more consistent interface across
+ the classes.
+
+ -Vector and double list get iterators.
+ -Fixed buffer. Restructuring vector broke it.
+ -Lower cased names in vector.
+ -Lower cased names in doublelist.
+ -Vector::Overwrite -> Vector::replace
+ -Vector::Delete -> Vector::remove
+ -DList::AddEnd -> DoubleList::append()
+ -DList::AddFront -> DoubleList::prepend()
+ -DList::DeleteElements -> DoubleList::empty()
+ -DList::EmptyList -> DoubleList::abandon()
+ -Added DListVal, which is the 'by-value-type' double list that does
+ not require a DListEl class to be defined.
+ -Began conventions doc.
+ -Rewrote the connection/selector code. It is now simpler and more generic.
+ Docs on the way. The code is now in event.{h,cc}. The select loop can
+ reliably translate asyncronous signals into events in the event loop.
+ However, code is not yet set up for processing the signal events. The event
+ loop handles signals using sigsetjmp/siglongjmp and avoides the classic unix
+ select loop race condition with respect to signals.
+
+Aapl 2.2.0 -- Feb 25, 2002
+==========================
+ -Added AvlSet. AvlSet is like AvlMap except you give only a key. It also has
+ the set interface: Set, UnSet and IsSet that return boolean values and don't
+ really care to speak about element in a tree.
+ -Added walkable versions of avl tree. There is a walkable version of all
+ existing trees. They are AvliTree, AvliMel, AvliMelKey, AvliMap, and AvliSet.
+ Implemented by having the element inherit from DListEl and the tree inherit
+ from DList. All operations on the tree remain O(log(N)). Maintaining the list
+ pointers adds a constant amount of work. Adds 8 bytes to each element (for a
+ total of 24) and 12 bytes to the tree (for a total of 20).
+ -Added a few more sections to docs for AvlTree
+
+Aapl 2.1.0 -- Feb 22, 2002
+==========================
+ IMPORTANT: VectorC(int) no longer has the same meaning. Previously it set
+ allocation length with no size. Now it sets size with no allocation so
+ it is effectively useless as the table cannot grow it's allocation. It
+ will assert fail. Use VectorC(int, int) instead. See Vector docs.
+
+ -Further split Vector into all possible types of upresizing and down
+ resizing. Existing Vectors remain unchanged except for constructor of
+ VectorC. It is now possible to have a vector that up resizes linear and
+ down exponential or up exponential and no down (constant), etc. Also
+ added VectorR, which allows for runtime setting of how to resize.
+ -Implemented a step for the linear vector. Now the following is true:
+ If the sequence of size requests is linear, the number of resizes is
+ also linear.
+ -Wrote docs for Vector.
+
+Aapl 2.0.0 -- Feb 17, 2002
+==========================
+ IMPORTANT: The 2.x.x version of Aapl is not backwards compatible with
+ 1.x.x version. Code that compiles against 1.x.x may not compile against
+ 2.x.x. The changes mostly amount to two things:
+
+ 1) Making data and function class member naming convetions consistent. All
+ variables start with a lower case whereas functions, classes, constants
+ and type names all start with an upper case.
+
+ 2) Shortening the symbols in resulting object code. Aapl classes achieved
+ great versatility by providing many tempate parameters mostly with
+ default values. Now this versatility is achieved by splitting the class
+ up into many different classes, each with thier own 'flavour' of the data
+ structure. This split is accomplished using preprocessor defines so there
+ is no code duplication. Classes now have shorter names and only required
+ template paramaters. This dramatically cuts down on long symbols and
+ eliminates compiler warnings on platforms that restrict symbol lengths.
+
+ -Made all data member names consistent with general coding style: constant
+ identifiers start with upper case, variables (members too) start with lower.
+ -Split up DoubleList into DList and DListMel. Goal is shorter
+ symbol names by making two specialzed classes instead of one general class.
+ -Split up AvlTree into 4 classes. Same goal as split of DoubleList.
+ AvlTree now supports having multiple keys in the same object as well as
+ multiple tree pointers. This means a single object can be in different
+ trees that each use different keys.
+ -General rearranging of code in fsmgraph and changing templates to result
+ in shorter symbols. Try to keep symbol lengths < 255.
+ -Split up Vector into 3 classes, one for each table type.
+ -Split up VectorSet into 3 classes, one for each table type. Also renamed
+ it to VectSet for conciseness.
+ -Split up Binary Search table into 6 classes, one for each table type times
+ regular bst table and bstmap. The bstmap has the template semantics of
+ the old bstable. BsTable lets you give the whole object you want to put in
+ the table in the same manner as vector and avltree.
+ -Both AvlTree and BsTable use GetKey() functions in the element/element types.
+ Previously they required that the key member be named 'key.' It can now
+ be named anything, and it must be returned by GetKey.
+ -Added copy constructor for AvlTree.
+ -Added Avl test progs for the various flavours.
+ -Started some real docs. Currently only AvlTree is documented.
+
+Aapl 1.2.2 -- Feb 2, 2002
+=========================
+ -Started ChangeLog file.
+ -Parser Gen is now gone from aapl. It is not generic reusable code. It now
+ lives in Keller which will be released soon.
+
+Aapl 1.2.1 -- Jan 29, 2002
+==========================
+ -Can choose between assertions that dump details of the assertion
+ failure to the screen then segfault or just segfault using a define.
+ -Bugfix in avltree insertion. Only showed up when re-using avl element.
+ The insert routine was not nulling out appropriate pointers when adding
+ a leaf element. Worked correctly when always newing up element (how avl tree
+ is mostly used) as nulling out pointers is done by the element constructor.
+ -File Buffer size up to 1K. Was at 10 bytes for debugging/testing purposes.
+ -Transition count variables gone from fsm graph. Computing this is silly as
+ the vectors that implement the out transitions
+ -Transition priorities routines in FSM Graph no longer operate as a 'delta'
+ but instead as absolute.
+ -Function keys are no long a duple, instead just one integer. Using two
+ integers is overkill and not likely to be used. To acieve the same effect as
+ a duple, break the bits of the single integer into multiple fields.
+ -Allow the shifting of the priorities of start transitions to above some
+ value. Useful before staring machines so that out transitions of a final
+ state run before the transitions of the start state when going from a final
+ state back into the machine.
+ -Allow the clearing of transition functions.
+ -Cleaned up FsmAttachStates: no longer reusing transitions when replacing,
+ old trans are deleted and a new one is made. This eliminates the need for
+ the ResetTransition routine.
+ -When building machines, use max int and min int as the defaults for highIndex
+ and lowIndex.
+ -When building machines, transition 0 is always the error transition,
+ no longer insert it into the transition list on demand.
+ -When building machines, compute the global high and low index. Used by ragel.
+ -Out priorities have a concept of being set vs not being set.
+ -Concatenation and Star can now behave as if they do not cause leaving the fsm.
+ Allows the user to turn off picking up of out transitions and out priorities.
+
+Aapl 1.2 -- Aug 28, 2001
+========================
+ -Initial release.
diff --git a/src/aapl/Makefile.am b/src/aapl/Makefile.am
new file mode 100644
index 00000000..b3cd0c94
--- /dev/null
+++ b/src/aapl/Makefile.am
@@ -0,0 +1,7 @@
+aaplinclude_HEADERS = \
+ avlbasic.h avlimel.h avlmap.h bstcommon.h compare.h insertsort.h \
+ sbstset.h avlcommon.h avlimelkey.h avlmel.h bstmap.h dlcommon.h \
+ mergesort.h sbsttable.h avlibasic.h avliset.h avlmelkey.h bstset.h \
+ dlist.h quicksort.h svector.h avlikeyless.h avlitree.h avlset.h \
+ bsttable.h dlistmel.h resize.h table.h avlimap.h avlkeyless.h avltree.h \
+ bubblesort.h dlistval.h sbstmap.h vector.h astring.h buffer.h rope.h
diff --git a/src/aapl/README b/src/aapl/README
new file mode 100644
index 00000000..a2fa5e65
--- /dev/null
+++ b/src/aapl/README
@@ -0,0 +1,6 @@
+This directory contains the Aapl source distribution. For the
+documentation, build scripts, test programs, ChangeLog, etc. get the
+aapldev package.
+
+AaplDev and other information about Aapl is available from
+http://www.elude.ca/aapl/
diff --git a/src/aapl/astring.h b/src/aapl/astring.h
new file mode 100644
index 00000000..29d876f4
--- /dev/null
+++ b/src/aapl/astring.h
@@ -0,0 +1,862 @@
+/*
+ * Copyright 2002 Adrian Thurston <thurston@colm.net>
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to
+ * deal in the Software without restriction, including without limitation the
+ * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
+ * sell copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+#ifndef _AAPL_ASTRING_H
+#define _AAPL_ASTRING_H
+
+#include <new>
+#include <stdlib.h>
+#include <stdarg.h>
+#include <stdio.h>
+#include <iostream>
+#include <assert.h>
+#include <string.h>
+
+#ifdef AAPL_NAMESPACE
+namespace Aapl {
+#endif
+
+#ifdef AAPL_DOCUMENTATION
+
+/**
+ * \defgroup astring String
+ * \brief Implicitly shared copy-on-write string.
+ *
+ * @{
+ */
+
+/**
+ * \class String
+ * \brief Implicitly shared copy-on-write string.
+ */
+
+/*@}*/
+
+class String
+{
+public:
+ /**
+ * \brief Create a null string. Data points to NULL.
+ */
+ String();
+
+ /**
+ * \brief Construct a string from a c-style string.
+ *
+ * A new buffer is allocated for the c string. Initially, this string will
+ * be the only String class referencing the data.
+ */
+ String( const char *s );
+
+ /**
+ * \brief Construct a string from a c-style string of specific length.
+ *
+ * A new buffer is allocated for the c string. Initially, this string will
+ * be the only String class referencing the data.
+ */
+ String( const char *s, long len );
+
+ /**
+ * \brief Construct a string from another String.
+ *
+ * A refernce to the buffer allocated for s is taken. A new buffer is
+ * not allocated.
+ */
+ String( const String &s );
+
+ /**
+ * \brief Construct a string using snprintf.
+ *
+ * Requires a maximum length for the resulting string. If the formatting
+ * (not including trailing null) requires more space than maxLen, the
+ * result will be truncated to maxLen long. Only the length actually
+ * written will be used by the new string. This string will be the only
+ * String class referencing the data.
+ */
+ String( long maxLen, const char *format, ... )
+
+ /**
+ * \brief Clean up the string.
+ *
+ * If the string is not null, the referenced data is detached. If no other
+ * string refernces the detached data, it is deleted.
+ */
+ ~String();
+
+ /**
+ * \brief Set the string from a c-style string.
+ *
+ * If this string is not null, the current buffer is dereferenced and
+ * possibly deleted. A new buffer is allocated (or possibly the old buffer
+ * reused) for the string. Initially, this string will be the only String
+ * class referencing the data.
+ *
+ * If s is null, then this string becomes a null ptr.
+ *
+ * \returns A reference to this.
+ */
+ String &operator=( const char *s );
+
+ /**
+ * \brief Set the string from a c-style of specific length.
+ *
+ * If this string is not null, the current buffer is dereferenced and
+ * possibly deleted. A new buffer is allocated (or possibly the old buffer
+ * reused) for the string. Initially, this string will be the only String
+ * class referencing the data.
+ *
+ * If s is null, then this string becomes a null ptr.
+ *
+ * \returns A reference to this.
+ */
+ void setAs( const char *s, long len );
+
+ /**
+ * \brief Set the string from a single char.
+ *
+ * The current buffer is dereferenced and possibly deleted. A new buffer
+ * is allocated (or possibly the old buffer reused) for the string.
+ * Initially, this string will be the only String class referencing the
+ * data.
+ *
+ * If s is null, then this string becomes a null ptr.
+ *
+ * \returns A reference to this.
+ */
+ String &operator=( const char c );
+
+
+ /**
+ * \brief Set the string from another String.
+ *
+ * If this string is not null, the current buffer is dereferenced and
+ * possibly deleted. A reference to the buffer allocated for s is taken.
+ * A new buffer is not allocated.
+ *
+ * If s is null, then this string becomes a null ptr.
+ *
+ * \returns a reference to this.
+ */
+ String &operator=( const String &s );
+
+ /**
+ * \brief Append a c string to the end of this string.
+ *
+ * If this string shares its allocation with another, a copy is first
+ * taken. The buffer for this string is grown and s is appended to the
+ * end.
+ *
+ * If s is null nothing happens.
+ *
+ * \returns a reference to this.
+ */
+ String &operator+=( const char *s );
+
+ /**
+ * \brief Append a c string of specific length to the end of this string.
+ *
+ * If this string shares its allocation with another, a copy is first
+ * taken. The buffer for this string is grown and s is appended to the
+ * end.
+ *
+ * If s is null nothing happens.
+ *
+ * \returns a reference to this.
+ */
+ void append( const char *s, long len );
+
+ /**
+ * \brief Append a single char to the end of this string.
+ *
+ * If this string shares its allocation with another, a copy is first
+ * taken. The buffer for this string is grown and s is appended to the
+ * end.
+ *
+ * \returns a reference to this.
+ */
+ String &operator+=( const char c );
+
+ /**
+ * \brief Append a String to the end of this string.
+ *
+ * If this string shares its allocation with another, a copy is first
+ * taken. The buffer for this string is grown and the data of s is
+ * appeneded to the end.
+ *
+ * If s is null nothing happens.
+ *
+ * returns a reference to this.
+ */
+ String &operator+=( const String &s );
+
+ /**
+ * \brief Cast to a char star.
+ *
+ * \returns the string data. A null string returns 0.
+ */
+ operator char*() const;
+
+ /**
+ * \brief Get a pointer to the data.
+ *
+ * \returns the string Data
+ */
+ char *get() const;
+
+ /**
+ * \brief Get the length of the string
+ *
+ * If the string is null, then undefined behaviour results.
+ *
+ * \returns the length of the string.
+ */
+ long length() const;
+
+ /**
+ * \brief Pointer to the data.
+ *
+ * Publically accessible pointer to the data. Immediately in front of the
+ * string data block is the string header which stores the refcount and
+ * length. Consequently, care should be taken if modifying this pointer.
+ */
+ char *data;
+};
+
+/**
+ * \relates String
+ * \brief Concatenate a c-style string and a String.
+ *
+ * \returns The concatenation of the two strings in a String.
+ */
+String operator+( const String &s1, const char *s2 );
+
+/**
+ * \relates String
+ * \brief Concatenate a String and a c-style string.
+ *
+ * \returns The concatenation of the two strings in a String.
+ */
+String operator+( const char *s1, const String &s2 );
+
+/**
+ * \relates String
+ * \brief Concatenate two String classes.
+ *
+ * \returns The concatenation of the two strings in a String.
+ */
+String operator+( const String &s1, const String &s2 );
+
+#endif
+
+template<class T> class StrTmpl
+{
+public:
+ class Fresh {};
+
+ /* Header located just before string data. Keeps the length and a refcount on
+ * the data. */
+ struct Head
+ {
+ long refCount;
+ long length;
+ };
+
+ /**
+ * \brief Create a null string.
+ */
+ StrTmpl() : data(0) { }
+
+ /* Clean up the string. */
+ ~StrTmpl();
+
+ /* Construct a string from a c-style string. */
+ StrTmpl( const char *s );
+
+ /* Construct a string from a c-style string of specific len. */
+ StrTmpl( const char *s, long len );
+
+ /* Allocate len spaces. */
+ StrTmpl( const Fresh &, long len );
+
+ /* Construct a string from another StrTmpl. */
+ StrTmpl( const StrTmpl &s );
+
+ /* Construct a string from with, sprintf. */
+ StrTmpl( long lenGuess, const char *format, ... );
+
+ /* Set the string from a c-style string. */
+ StrTmpl &operator=( const char *s );
+
+ /* Set the string from a c-style string of specific len. */
+ void setAs( const char *s, long len );
+
+ /* Allocate len spaces. */
+ void setAs( const Fresh &, long len );
+
+ void chop( long len );
+
+ /* Construct a string from with, sprintf. */
+ void setAs( long lenGuess, const char *format, ... );
+
+ /* Set the string from a single char. */
+ StrTmpl &operator=( const char c );
+
+ /* Set the string from another StrTmpl. */
+ StrTmpl &operator=( const StrTmpl &s );
+
+ /* Append a c string to the end of this string. */
+ StrTmpl &operator+=( const char *s );
+
+ /* Append a c string to the end of this string of specifi len. */
+ void append( const char *s, long len );
+
+ /* Append a single char to the end of this string. */
+ StrTmpl &operator+=( const char c );
+
+ /* Append an StrTmpl to the end of this string. */
+ StrTmpl &operator+=( const StrTmpl &s );
+
+ /* Cast to a char star. */
+ operator char*() const { return data; }
+
+ /* Get a pointer to the data. */
+ char *get() const { return data; }
+
+ /* Return the length of the string. Must check for null data pointer. */
+ long length() const { return data ? (((Head*)data)-1)->length : 0; }
+
+ void empty() { setAs( (const char *)0, 0 ); }
+
+ /**
+ * \brief Pointer to the data.
+ */
+ char *data;
+
+protected:
+ /* Make space for a string of length len to be appended. */
+ char *appendSpace( long len );
+ void initSpace( long length );
+ void setSpace( long length );
+
+ template <class FT> friend StrTmpl<FT> operator+(
+ const StrTmpl<FT> &s1, const char *s2 );
+ template <class FT> friend StrTmpl<FT> operator+(
+ const char *s1, const StrTmpl<FT> &s2 );
+ template <class FT> friend StrTmpl<FT> operator+(
+ const StrTmpl<FT> &s1, const StrTmpl<FT> &s2 );
+
+private:
+ /* A dummy struct solely to make a constructor that will never be
+ * ambiguous with the public constructors. */
+ struct DisAmbig { };
+ StrTmpl( char *data, const DisAmbig & ) : data(data) { }
+};
+
+/* Free all mem used by the string. */
+template<class T> StrTmpl<T>::~StrTmpl()
+{
+ if ( data != 0 ) {
+ /* If we are the only ones referencing the string, then delete it. */
+ Head *head = ((Head*) data) - 1;
+ head->refCount -= 1;
+ if ( head->refCount == 0 )
+ free( head );
+ }
+}
+
+/* Create from a c-style string. */
+template<class T> StrTmpl<T>::StrTmpl( const char *s )
+{
+ if ( s == 0 )
+ data = 0;
+ else {
+ /* Find the length and allocate the space for the shared string. */
+ long length = strlen( s );
+
+ /* Init space for the data. */
+ initSpace( length );
+
+ /* Copy in the data. */
+ memcpy( data, s, length+1 );
+ }
+}
+
+/* Create from a c-style string. */
+template<class T> StrTmpl<T>::StrTmpl( const char *s, long length )
+{
+ if ( s == 0 )
+ data = 0;
+ else {
+ /* Init space for the data. */
+ initSpace( length );
+
+ /* Copy in the data. */
+ memcpy( data, s, length );
+ data[length] = 0;
+ }
+}
+
+/* Create from a c-style string. */
+template<class T> StrTmpl<T>::StrTmpl( const Fresh &, long length )
+{
+ /* Init space for the data. */
+ initSpace( length );
+ data[length] = 0;
+}
+
+/* Create from another string class. */
+template<class T> StrTmpl<T>::StrTmpl( const StrTmpl &s )
+{
+ if ( s.data == 0 )
+ data = 0;
+ else {
+ /* Take a reference to the string. */
+ Head *strHead = ((Head*)s.data) - 1;
+ strHead->refCount += 1;
+ data = (char*) (strHead+1);
+ }
+}
+
+/* Construct a string from with, sprintf. */
+template<class T> StrTmpl<T>::StrTmpl( long lenGuess, const char *format, ... )
+{
+ /* Set the string for len. */
+ initSpace( lenGuess );
+
+ va_list args;
+
+ /* Write to the temporary buffer. */
+ va_start( args, format );
+
+ long written = vsnprintf( data, lenGuess+1, format, args );
+ if ( written > lenGuess ) {
+ setSpace( written );
+ written = vsnprintf( data, written+1, format, args );
+ }
+ chop( written );
+
+ va_end( args );
+}
+
+/* Construct a string from with, sprintf. */
+template<class T> void StrTmpl<T>::setAs( long lenGuess, const char *format, ... )
+{
+ /* Set the string for len. */
+ setSpace( lenGuess );
+
+ va_list args;
+
+ /* Write to the temporary buffer. */
+ va_start( args, format );
+
+ long written = vsnprintf( data, lenGuess+1, format, args );
+ if ( written > lenGuess ) {
+ setSpace( written );
+ written = vsnprintf( data, written+1, format, args );
+ }
+ chop( written );
+
+ va_end( args );
+}
+
+template<class T> void StrTmpl<T>::initSpace( long length )
+{
+ /* Find the length and allocate the space for the shared string. */
+ Head *head = (Head*) malloc( sizeof(Head) + length+1 );
+ if ( head == 0 )
+ throw std::bad_alloc();
+
+ /* Init the header. */
+ head->refCount = 1;
+ head->length = length;
+
+ /* Save the pointer to the data. */
+ data = (char*) (head+1);
+}
+
+
+/* Set this string to be the c string exactly. The old string is discarded.
+ * Returns a reference to this. */
+template<class T> StrTmpl<T> &StrTmpl<T>::operator=( const char *s )
+{
+ if ( s == 0 ) {
+ /* Just free the data, we are being set to null. */
+ if ( data != 0 ) {
+ Head *head = ((Head*)data) - 1;
+ head->refCount -= 1;
+ if ( head->refCount == 0 )
+ free(head);
+ data = 0;
+ }
+ }
+ else {
+ /* Find the length of the string we are setting. */
+ long length = strlen( s );
+
+ /* Set the string for len. */
+ setSpace( length );
+
+ /* Copy in the data. */
+ memcpy( data, s, length+1 );
+ }
+ return *this;
+}
+
+/* Set this string to be the c string exactly. The old string is discarded.
+ * Returns a reference to this. */
+template<class T> void StrTmpl<T>::setAs( const char *s, long length )
+{
+ if ( s == 0 ) {
+ /* Just free the data, we are being set to null. */
+ if ( data != 0 ) {
+ Head *head = ((Head*)data) - 1;
+ head->refCount -= 1;
+ if ( head->refCount == 0 )
+ free(head);
+ data = 0;
+ }
+ }
+ else {
+ /* Set the string for len. */
+ setSpace( length );
+
+ /* Copy in the data. */
+ memcpy( data, s, length );
+ data[length] = 0;
+ }
+}
+
+template<class T> void StrTmpl<T>::chop( long length )
+{
+ /* Detach from the existing string. */
+ Head *head = ((Head*)data) - 1;
+ assert( head->refCount == 1 );
+ assert( length <= head->length );
+ head->length = length;
+ data[length] = 0;
+}
+
+/* Set this string to be the c string exactly. The old string is discarded.
+ * Returns a reference to this. */
+template<class T> void StrTmpl<T>::setAs( const Fresh &, long length )
+{
+ setSpace( length );
+ data[length] = 0;
+}
+
+/* Set this string to be the single char exactly. The old string is discarded.
+ * Returns a reference to this. */
+template<class T> StrTmpl<T> &StrTmpl<T>::operator=( const char c )
+{
+ /* Set to length 1. */
+ setSpace( 1 );
+
+ /* Copy in the data. */
+ data[0] = c;
+ data[1] = 0;
+
+ /* Return ourselves. */
+ return *this;
+}
+
+/* Set this string to be the StrTmpl s exactly. The old string is
+ * discarded. */
+template<class T> StrTmpl<T> &StrTmpl<T>::operator=( const StrTmpl &s )
+{
+ /* Detach from the existing string. */
+ if ( data != 0 ) {
+ Head *head = ((Head*)data) - 1;
+ head->refCount -= 1;
+ if ( head->refCount == 0 )
+ free( head );
+ }
+
+ if ( s.data != 0 ) {
+ /* Take a reference to the string. */
+ Head *strHead = ((Head*)s.data) - 1;
+ strHead->refCount += 1;
+ data = (char*)(strHead+1);
+ }
+ else {
+ /* Setting from a null string, just null our pointer. */
+ data = 0;
+ }
+ return *this;
+}
+
+/* Prepare the string to be set to something else of the given length. */
+template<class T> void StrTmpl<T>::setSpace( long length )
+{
+ /* Detach from the existing string. */
+ Head *head = ((Head*)data) - 1;
+ if ( data != 0 && --head->refCount == 0 ) {
+ /* Resuse the space. */
+ head = (Head*) realloc( head, sizeof(Head) + length+1 );
+ }
+ else {
+ /* Need to make new space, there is no usable old space. */
+ head = (Head*) malloc( sizeof(Head) + length+1 );
+ }
+ if ( head == 0 )
+ throw std::bad_alloc();
+
+ /* Init the header. */
+ head->refCount = 1;
+ head->length = length;
+
+ /* Copy in the data and save the pointer to it. */
+ data = (char*) (head+1);
+}
+
+/* Append a c-style string to the end of this string. Returns a reference to
+ * this */
+template<class T> StrTmpl<T> &StrTmpl<T>::operator+=( const char *s )
+{
+ /* Find the length of the string appended. */
+ if ( s != 0 ) {
+ /* Get the string length and make space on the end. */
+ long addedLen = strlen( s );
+ char *dest = appendSpace( addedLen );
+
+ /* Copy the data in. Plus one for the null. */
+ memcpy( dest, s, addedLen+1 );
+ }
+ return *this;
+}
+
+/* Append a c-style string of specific length to the end of this string.
+ * Returns a reference to this */
+template<class T> void StrTmpl<T>::append( const char *s, long length )
+{
+ /* Find the length of the string appended. */
+ if ( s != 0 ) {
+ /* Make space on the end. */
+ char *dest = appendSpace( length );
+
+ /* Copy the data in. Plus one for the null. */
+ memcpy( dest, s, length );
+ dest[length] = 0;
+ }
+}
+
+/* Append a single char to the end of this string. Returns a reference to
+ * this */
+template<class T> StrTmpl<T> &StrTmpl<T>::operator+=( const char c )
+{
+ /* Grow on the end. */
+ char *dst = appendSpace( 1 );
+
+ /* Append a single charachter. */
+ dst[0] = c;
+ dst[1] = 0;
+ return *this;
+}
+
+
+/* Append an StrTmpl string to the end of this string. Returns a reference
+ * to this */
+template<class T> StrTmpl<T> &StrTmpl<T>::operator+=( const StrTmpl &s )
+{
+ /* Find the length of the string appended. */
+ if ( s.data != 0 ) {
+ /* Find the length to append. */
+ long addedLen = (((Head*)s.data) - 1)->length;
+
+ /* Make space on the end to put the string. */
+ char *dest = appendSpace( addedLen );
+
+ /* Append the data, add one for the null. */
+ memcpy( dest, s.data, addedLen+1 );
+ }
+ return *this;
+}
+
+/* Make space for a string of length len to be appended. */
+template<class T> char *StrTmpl<T>::appendSpace( long len )
+{
+ if ( data == 0 ) {
+ initSpace( len );
+ return data;
+ }
+ else {
+ /* Find the length of this and the string appended. */
+ Head *head = (((Head*)data) - 1);
+ long thisLen = head->length;
+
+ if ( head->refCount == 1 ) {
+ /* No other string is using the space, grow this space. */
+ head = (Head*) realloc( head,
+ sizeof(Head) + thisLen + len + 1 );
+ if ( head == 0 )
+ throw std::bad_alloc();
+ data = (char*) (head+1);
+
+ /* Adjust the length. */
+ head->length += len;
+ }
+ else {
+ /* Another string is using this space, make new space. */
+ head->refCount -= 1;
+ Head *newHead = (Head*) malloc(
+ sizeof(Head) + thisLen + len + 1 );
+ if ( newHead == 0 )
+ throw std::bad_alloc();
+ data = (char*) (newHead+1);
+
+ /* Set the new header and data from this. */
+ newHead->refCount = 1;
+ newHead->length = thisLen + len;
+ memcpy( data, head+1, thisLen );
+ }
+
+ /* Return writing position. */
+ return data + thisLen;
+ }
+}
+
+/* Concatenate a String and a c-style string. */
+template<class T> StrTmpl<T> operator+( const StrTmpl<T> &s1, const char *s2 )
+{
+ /* Find s2 length and alloc the space for the result. */
+ long str1Len = (((typename StrTmpl<T>::Head*)(s1.data)) - 1)->length;
+ long str2Len = strlen( s2 );
+
+ typename StrTmpl<T>::Head *head = (typename StrTmpl<T>::Head*)
+ malloc( sizeof(typename StrTmpl<T>::Head) + str1Len + str2Len + 1 );
+ if ( head == 0 )
+ throw std::bad_alloc();
+
+ /* Set up the header. */
+ head->refCount = 1;
+ head->length = str1Len + str2Len;
+
+ /* Save the pointer to data and copy the data in. */
+ char *data = (char*) (head+1);
+ memcpy( data, s1.data, str1Len );
+ memcpy( data + str1Len, s2, str2Len + 1 );
+ return StrTmpl<T>( data, typename StrTmpl<T>::DisAmbig() );
+}
+
+/* Concatenate a c-style string and a String. */
+template<class T> StrTmpl<T> operator+( const char *s1, const StrTmpl<T> &s2 )
+{
+ /* Find s2 length and alloc the space for the result. */
+ long str1Len = strlen( s1 );
+ long str2Len = (((typename StrTmpl<T>::Head*)(s2.data)) - 1)->length;
+
+ typename StrTmpl<T>::Head *head = (typename StrTmpl<T>::Head*)
+ malloc( sizeof(typename StrTmpl<T>::Head) + str1Len + str2Len + 1 );
+ if ( head == 0 )
+ throw std::bad_alloc();
+
+ /* Set up the header. */
+ head->refCount = 1;
+ head->length = str1Len + str2Len;
+
+ /* Save the pointer to data and copy the data in. */
+ char *data = (char*) (head+1);
+ memcpy( data, s1, str1Len );
+ memcpy( data + str1Len, s2.data, str2Len + 1 );
+ return StrTmpl<T>( data, typename StrTmpl<T>::DisAmbig() );
+}
+
+/* Add two StrTmpl strings. */
+template<class T> StrTmpl<T> operator+( const StrTmpl<T> &s1, const StrTmpl<T> &s2 )
+{
+ /* Find s2 length and alloc the space for the result. */
+ long str1Len = (((typename StrTmpl<T>::Head*)(s1.data)) - 1)->length;
+ long str2Len = (((typename StrTmpl<T>::Head*)(s2.data)) - 1)->length;
+ typename StrTmpl<T>::Head *head = (typename StrTmpl<T>::Head*)
+ malloc( sizeof(typename StrTmpl<T>::Head) + str1Len + str2Len + 1 );
+ if ( head == 0 )
+ throw std::bad_alloc();
+
+ /* Set up the header. */
+ head->refCount = 1;
+ head->length = str1Len + str2Len;
+
+ /* Save the pointer to data and copy the data in. */
+ char *data = (char*) (head+1);
+ memcpy( data, s1.data, str1Len );
+ memcpy( data + str1Len, s2.data, str2Len + 1 );
+ return StrTmpl<T>( data, typename StrTmpl<T>::DisAmbig() );
+}
+
+/* Operator used in case the compiler does not support the conversion. */
+template <class T> inline std::ostream &operator<<( std::ostream &o, const StrTmpl<T> &s )
+{
+ return o.write( s.data, s.length() );
+}
+
+typedef StrTmpl<char> String;
+
+/*
+ * StringStream for appending to streams with an ostream.
+ */
+struct StringOutBuf
+:
+ public std::streambuf
+{
+ StringOutBuf( String &s )
+ :
+ s(s)
+ {
+ }
+
+ int_type overflow( int_type c )
+ {
+ if ( c != EOF ) {
+ char z = c;
+ s.append( &z, 1 );
+ }
+ return c;
+ }
+
+ std::streamsize xsputn( const char *data, std::streamsize num )
+ {
+ s.append( data, num );
+ return num;
+ }
+
+ String &s;
+};
+
+struct StringStream
+:
+ public std::ostream
+{
+ StringStream( String &s )
+ :
+ std::ostream( 0 ),
+ buf( s )
+ {
+ rdbuf( &buf );
+ }
+
+ StringOutBuf buf;
+};
+
+#ifdef AAPL_NAMESPACE
+}
+#endif
+
+#endif /* _AAPL_ASTRING_H */
diff --git a/src/aapl/avlbasic.h b/src/aapl/avlbasic.h
new file mode 100644
index 00000000..4e31dd97
--- /dev/null
+++ b/src/aapl/avlbasic.h
@@ -0,0 +1,66 @@
+/*
+ * Copyright 2002 Adrian Thurston <thurston@colm.net>
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to
+ * deal in the Software without restriction, including without limitation the
+ * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
+ * sell copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+#ifndef _AAPL_AVLBASIC_H
+#define _AAPL_AVLBASIC_H
+
+#include "compare.h"
+
+/**
+ * \addtogroup avltree
+ * @{
+ */
+
+/**
+ * \class AvlBasic
+ * \brief AVL Tree in which the entire element structure is the key.
+ *
+ * AvlBasic is an AVL tree that does not distinguish between the element that
+ * it contains and the key. The entire element structure is the key that is
+ * used to compare the relative ordering of elements. This is similar to the
+ * BstSet structure.
+ *
+ * AvlBasic does not assume ownership of elements in the tree. Items must be
+ * explicitly de-allocated.
+ */
+
+/*@}*/
+
+#define BASE_EL(name) name
+#define BASEKEY(name) name
+#define AVLMEL_CLASSDEF class Element, class Compare
+#define AVLMEL_TEMPDEF class Element, class Compare
+#define AVLMEL_TEMPUSE Element, Compare
+#define AvlTree AvlBasic
+#define AVL_BASIC
+
+#include "avlcommon.h"
+
+#undef BASE_EL
+#undef BASEKEY
+#undef AVLMEL_CLASSDEF
+#undef AVLMEL_TEMPDEF
+#undef AVLMEL_TEMPUSE
+#undef AvlTree
+#undef AVL_BASIC
+
+#endif /* _AAPL_AVLBASIC_H */
diff --git a/src/aapl/avlcommon.h b/src/aapl/avlcommon.h
new file mode 100644
index 00000000..a1f86692
--- /dev/null
+++ b/src/aapl/avlcommon.h
@@ -0,0 +1,1637 @@
+/*
+ * Copyright 2001 Adrian Thurston <thurston@colm.net>
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to
+ * deal in the Software without restriction, including without limitation the
+ * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
+ * sell copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+/* This header is not wrapped in ifndef becuase it is not intended to
+ * be included by the user. */
+
+#include <assert.h>
+
+#ifdef AAPL_NAMESPACE
+namespace Aapl {
+#endif
+
+#ifdef WALKABLE
+/* This is used by AvlTree, AvlMel and AvlMelKey so it
+ * must be protected by global ifdefs. */
+#ifndef __AAPL_AVLI_EL__
+#define __AAPL_AVLI_EL__
+
+/**
+ * \brief Tree element properties for linked AVL trees.
+ *
+ * AvliTreeEl needs to be inherited by classes that intend to be element in an
+ * AvliTree.
+ */
+template<class SubClassEl> struct AvliTreeEl
+{
+ /**
+ * \brief Tree pointers connecting element in a tree.
+ */
+ SubClassEl *left, *right, *parent;
+
+ /**
+ * \brief Linked list pointers.
+ */
+ SubClassEl *prev, *next;
+
+ /**
+ * \brief Height of the tree rooted at this element.
+ *
+ * Height is required by the AVL balancing algorithm.
+ */
+ long height;
+};
+#endif /* __AAPL_AVLI_EL__ */
+
+#else /* not WALKABLE */
+
+/* This is used by All the non walkable trees so it must be
+ * protected by a global ifdef. */
+#ifndef __AAPL_AVL_EL__
+#define __AAPL_AVL_EL__
+/**
+ * \brief Tree element properties for linked AVL trees.
+ *
+ * AvlTreeEl needs to be inherited by classes that intend to be element in an
+ * AvlTree.
+ */
+template<class SubClassEl> struct AvlTreeEl
+{
+ /**
+ * \brief Tree pointers connecting element in a tree.
+ */
+ SubClassEl *left, *right, *parent;
+
+ /**
+ * \brief Height of the tree rooted at this element.
+ *
+ * Height is required by the AVL balancing algorithm.
+ */
+ long height;
+};
+#endif /* __AAPL_AVL_EL__ */
+#endif /* def WALKABLE */
+
+
+#if defined( AVLTREE_MAP )
+
+#ifdef WALKABLE
+
+/**
+ * \brief Tree element for AvliMap
+ *
+ * Stores the key and value pair.
+ */
+template <class Key, class Value> struct AvliMapEl :
+ public AvliTreeEl< AvliMapEl<Key, Value> >
+{
+ AvliMapEl(const Key &key)
+ : key(key) { }
+ AvliMapEl(const Key &key, const Value &value)
+ : key(key), value(value) { }
+
+ const Key &getKey() const { return key; }
+
+ /** \brief The key. */
+ Key key;
+
+ /** \brief The value. */
+ Value value;
+};
+#else /* not WALKABLE */
+
+/**
+ * \brief Tree element for AvlMap
+ *
+ * Stores the key and value pair.
+ */
+template <class Key, class Value> struct AvlMapEl :
+ public AvlTreeEl< AvlMapEl<Key, Value> >
+{
+ AvlMapEl(const Key &key)
+ : key(key) { }
+ AvlMapEl(const Key &key, const Value &value)
+ : key(key), value(value) { }
+
+ const Key &getKey() const { return key; }
+
+ /** \brief The key. */
+ Key key;
+
+ /** \brief The value. */
+ Value value;
+};
+#endif /* def WALKABLE */
+
+#elif defined( AVLTREE_SET )
+
+#ifdef WALKABLE
+/**
+ * \brief Tree element for AvliSet
+ *
+ * Stores the key.
+ */
+template <class Key> struct AvliSetEl :
+ public AvliTreeEl< AvliSetEl<Key> >
+{
+ AvliSetEl(const Key &key) : key(key) { }
+
+ const Key &getKey() const { return key; }
+
+ /** \brief The key. */
+ Key key;
+};
+#else /* not WALKABLE */
+/**
+ * \brief Tree element for AvlSet
+ *
+ * Stores the key.
+ */
+template <class Key> struct AvlSetEl :
+ public AvlTreeEl< AvlSetEl<Key> >
+{
+ AvlSetEl(const Key &key) : key(key) { }
+
+ const Key &getKey() const { return key; }
+
+ /** \brief The key. */
+ Key key;
+};
+#endif /* def WALKABLE */
+
+#endif /* AVLTREE_SET */
+
+/* Common AvlTree Class */
+template < AVLMEL_CLASSDEF > class AvlTree
+#if !defined( AVL_KEYLESS ) && defined ( WALKABLE )
+ : public Compare, public BASELIST
+#elif !defined( AVL_KEYLESS )
+ : public Compare
+#elif defined( WALKABLE )
+ : public BASELIST
+#endif
+{
+public:
+ typedef Element El;
+
+ /**
+ * \brief Create an empty tree.
+ */
+#ifdef WALKABLE
+ AvlTree() : root(0), treeSize(0) { }
+#else
+ AvlTree() : root(0), head(0), tail(0), treeSize(0) { }
+#endif
+
+ /**
+ * \brief Perform a deep copy of the tree.
+ *
+ * Each element is duplicated for the new tree. Copy constructors are used
+ * to create the new elements.
+ */
+ AvlTree(const AvlTree &other);
+
+#if defined( AVLTREE_MAP ) || defined( AVLTREE_SET )
+ /**
+ * \brief Clear the contents of the tree.
+ *
+ * All element are deleted.
+ */
+ ~AvlTree() { empty(); }
+
+ /**
+ * \brief Perform a deep copy of the tree.
+ *
+ * Each element is duplicated for the new tree. Copy constructors are used
+ * to create the new element. If this tree contains items, they are first
+ * deleted.
+ *
+ * \returns A reference to this.
+ */
+ AvlTree &operator=( const AvlTree &tree );
+
+ /**
+ * \brief Transfer the elements of another tree into this.
+ *
+ * First deletes all elements in this tree.
+ */
+ void transfer( AvlTree &tree );
+#else
+ /**
+ * \brief Abandon all elements in the tree.
+ *
+ * Tree elements are not deleted.
+ */
+ ~AvlTree() {}
+
+ /**
+ * \brief Perform a deep copy of the tree.
+ *
+ * Each element is duplicated for the new tree. Copy constructors are used
+ * to create the new element. If this tree contains items, they are
+ * abandoned.
+ *
+ * \returns A reference to this.
+ */
+ AvlTree &operator=( const AvlTree &tree );
+
+ /**
+ * \brief Transfer the elements of another tree into this.
+ *
+ * All elements in this tree are abandoned first.
+ */
+ void transfer( AvlTree &tree );
+#endif
+
+#ifndef AVL_KEYLESS
+ /* Insert a element into the tree. */
+ Element *insert( Element *element, Element **lastFound = 0 );
+
+#ifdef AVL_BASIC
+ /* Find a element in the tree. Returns the element if
+ * element exists, false otherwise. */
+ Element *find( const Element *element ) const;
+
+#else
+ Element *insert( const Key &key, Element **lastFound = 0 );
+
+#ifdef AVLTREE_MAP
+ Element *insert( const Key &key, const Value &val,
+ Element **lastFound = 0 );
+#endif
+
+ /* Find a element in the tree. Returns the element if
+ * key exists, false otherwise. */
+ Element *find( const Key &key ) const;
+
+ /* Detach a element from the tree. */
+ Element *detach( const Key &key );
+
+ /* Detach and delete a element from the tree. */
+ bool remove( const Key &key );
+#endif /* AVL_BASIC */
+#endif /* AVL_KEYLESS */
+
+ /* Detach a element from the tree. */
+ Element *detach( Element *element );
+
+ /* Detach and delete a element from the tree. */
+ void remove( Element *element );
+
+ /* Free all memory used by tree. */
+ void empty();
+
+ /* Abandon all element in the tree. Does not delete element. */
+ void abandon();
+
+ /** Root element of the tree. */
+ Element *root;
+
+#ifndef WALKABLE
+ Element *head, *tail;
+#endif
+
+ /** The number of element in the tree. */
+ long treeSize;
+
+ /** \brief Return the number of elements in the tree. */
+ long length() const { return treeSize; }
+
+ /** \brief Return the number of elements in the tree. */
+ long size() const { return treeSize; }
+
+ /* Various classes for setting the iterator */
+ struct Iter;
+ struct IterFirst { IterFirst( const AvlTree &t ) : t(t) { } const AvlTree &t; };
+ struct IterLast { IterLast( const AvlTree &t ) : t(t) { } const AvlTree &t; };
+ struct IterNext { IterNext( const Iter &i ) : i(i) { } const Iter &i; };
+ struct IterPrev { IterPrev( const Iter &i ) : i(i) { } const Iter &i; };
+
+#ifdef WALKABLE
+ /**
+ * \brief Avl Tree Iterator.
+ * \ingroup iterators
+ */
+ struct Iter
+ {
+ /* Default construct. */
+ Iter() : ptr(0) { }
+
+ /* Construct from an avl tree and iterator-setting classes. */
+ Iter( const AvlTree &t ) : ptr(t.head) { }
+ Iter( const IterFirst &af ) : ptr(af.t.head) { }
+ Iter( const IterLast &al ) : ptr(al.t.tail) { }
+ Iter( const IterNext &an ) : ptr(findNext(an.i.ptr)) { }
+ Iter( const IterPrev &ap ) : ptr(findPrev(ap.i.ptr)) { }
+
+ /* Assign from a tree and iterator-setting classes. */
+ Iter &operator=( const AvlTree &tree ) { ptr = tree.head; return *this; }
+ Iter &operator=( const IterFirst &af ) { ptr = af.t.head; return *this; }
+ Iter &operator=( const IterLast &al ) { ptr = al.t.tail; return *this; }
+ Iter &operator=( const IterNext &an ) { ptr = findNext(an.i.ptr); return *this; }
+ Iter &operator=( const IterPrev &ap ) { ptr = findPrev(ap.i.ptr); return *this; }
+
+ /** \brief Less than end? */
+ bool lte() const { return ptr != 0; }
+
+ /** \brief At end? */
+ bool end() const { return ptr == 0; }
+
+ /** \brief Greater than beginning? */
+ bool gtb() const { return ptr != 0; }
+
+ /** \brief At beginning? */
+ bool beg() const { return ptr == 0; }
+
+ /** \brief At first element? */
+ bool first() const { return ptr && ptr->BASE_EL(prev) == 0; }
+
+ /** \brief At last element? */
+ bool last() const { return ptr && ptr->BASE_EL(next) == 0; }
+
+ /** \brief Implicit cast to Element*. */
+ operator Element*() const { return ptr; }
+
+ /** \brief Dereference operator returns Element&. */
+ Element &operator *() const { return *ptr; }
+
+ /** \brief Arrow operator returns Element*. */
+ Element *operator->() const { return ptr; }
+
+ /** \brief Move to next item. */
+ inline Element *operator++();
+
+ /** \brief Move to next item. */
+ inline Element *operator++(int);
+
+ /** \brief Move to next item. */
+ inline Element *increment();
+
+ /** \brief Move to previous item. */
+ inline Element *operator--();
+
+ /** \brief Move to previous item. */
+ inline Element *operator--(int);
+
+ /** \brief Move to previous item. */
+ inline Element *decrement();
+
+ /** \brief Return the next item. Does not modify this. */
+ IterNext next() const { return IterNext( *this ); }
+
+ /** \brief Return the previous item. Does not modify this. */
+ IterPrev prev() const { return IterPrev( *this ); }
+
+ private:
+ static Element *findPrev( Element *element ) { return element->BASE_EL(prev); }
+ static Element *findNext( Element *element ) { return element->BASE_EL(next); }
+
+ public:
+
+ /** \brief The iterator is simply a pointer. */
+ Element *ptr;
+ };
+
+#else
+
+ /**
+ * \brief Avl Tree Iterator.
+ * \ingroup iterators
+ */
+ struct Iter
+ {
+ /* Default construct. */
+ Iter() : ptr(0), tree(0) { }
+
+ /* Construct from a tree and iterator-setting classes. */
+ Iter( const AvlTree &t ) : ptr(t.head), tree(&t) { }
+ Iter( const IterFirst &af ) : ptr(af.t.head), tree(&af.t) { }
+ Iter( const IterLast &al ) : ptr(al.t.tail), tree(&al.t) { }
+ Iter( const IterNext &an ) : ptr(findNext(an.i.ptr)), tree(an.i.tree) { }
+ Iter( const IterPrev &ap ) : ptr(findPrev(ap.i.ptr)), tree(ap.i.tree) { }
+
+ /* Assign from a tree and iterator-setting classes. */
+ Iter &operator=( const AvlTree &t )
+ { ptr = t.head; tree = &t; return *this; }
+ Iter &operator=( const IterFirst &af )
+ { ptr = af.t.head; tree = &af.t; return *this; }
+ Iter &operator=( const IterLast &al )
+ { ptr = al.t.tail; tree = &al.t; return *this; }
+ Iter &operator=( const IterNext &an )
+ { ptr = findNext(an.i.ptr); tree = an.i.tree; return *this; }
+ Iter &operator=( const IterPrev &ap )
+ { ptr = findPrev(ap.i.ptr); tree = ap.i.tree; return *this; }
+
+ /** \brief Less than end? */
+ bool lte() const { return ptr != 0; }
+
+ /** \brief At end? */
+ bool end() const { return ptr == 0; }
+
+ /** \brief Greater than beginning? */
+ bool gtb() const { return ptr != 0; }
+
+ /** \brief At beginning? */
+ bool beg() const { return ptr == 0; }
+
+ /** \brief At first element? */
+ bool first() const { return ptr && ptr == tree->head; }
+
+ /** \brief At last element? */
+ bool last() const { return ptr && ptr == tree->tail; }
+
+ /** \brief Implicit cast to Element*. */
+ operator Element*() const { return ptr; }
+
+ /** \brief Dereference operator returns Element&. */
+ Element &operator *() const { return *ptr; }
+
+ /** \brief Arrow operator returns Element*. */
+ Element *operator->() const { return ptr; }
+
+ /** \brief Move to next item. */
+ inline Element *operator++();
+
+ /** \brief Move to next item. */
+ inline Element *operator++(int);
+
+ /** \brief Move to next item. */
+ inline Element *increment();
+
+ /** \brief Move to previous item. */
+ inline Element *operator--();
+
+ /** \brief Move to previous item. */
+ inline Element *operator--(int);
+
+ /** \brief Move to previous item. */
+ inline Element *decrement();
+
+ /** \brief Return the next item. Does not modify this. */
+ IterNext next() const { return IterNext( *this ); }
+
+ /** \brief Return the previous item. Does not modify this. */
+ IterPrev prev() const { return IterPrev( *this ); }
+
+ private:
+ static Element *findPrev( Element *element );
+ static Element *findNext( Element *element );
+
+ public:
+ /** \brief The iterator is simply a pointer. */
+ Element *ptr;
+
+ /* The list is not walkable so we need to keep a pointerto the tree
+ * so we can test against head and tail in O(1) time. */
+ const AvlTree *tree;
+ };
+#endif
+
+ /** \brief Return first element. */
+ IterFirst first() { return IterFirst( *this ); }
+
+ /** \brief Return last element. */
+ IterLast last() { return IterLast( *this ); }
+
+protected:
+ /* Recursive worker for the copy constructor. */
+ Element *copyBranch( Element *element );
+
+ /* Recursively delete element in the tree. */
+ void deleteChildrenOf(Element *n);
+
+ /* rebalance the tree beginning at the leaf whose
+ * grandparent is unbalanced. */
+ Element *rebalance(Element *start);
+
+ /* Move up the tree from a given element, recalculating the heights. */
+ void recalcHeights(Element *start);
+
+ /* Move up the tree and find the first element whose
+ * grand-parent is unbalanced. */
+ Element *findFirstUnbalGP(Element *start);
+
+ /* Move up the tree and find the first element which is unbalanced. */
+ Element *findFirstUnbalEl(Element *start);
+
+ /* Replace a element in the tree with another element not in the tree. */
+ void replaceEl(Element *element, Element *replacement);
+
+ /* Remove a element from the tree and put another (normally a child of element)
+ * in its place. */
+ void removeEl(Element *element, Element *filler);
+
+ /* Once an insertion point is found at a leaf then do the insert. */
+ void attachRebal( Element *element, Element *parentEl, Element *lastLess );
+};
+
+/* Copy constructor. New up each item. */
+template <AVLMEL_TEMPDEF> AvlTree<AVLMEL_TEMPUSE>::
+ AvlTree(const AvlTree<AVLMEL_TEMPUSE> &other)
+#if !defined( AVL_KEYLESS ) && defined ( WALKABLE )
+ /* BASELIST should be made empty. The copyBranch function
+ * will fill in the details for us. */
+ : Compare( other ), BASELIST()
+#elif !defined( AVL_KEYLESS )
+ : Compare( other )
+#elif defined( WALKABLE )
+ : BASELIST( )
+#endif
+{
+ treeSize = other.treeSize;
+ root = other.root;
+
+#ifndef WALKABLE
+ head = 0;
+ tail = 0;
+#endif
+
+ /* If there is a root, copy the tree. */
+ if ( other.root != 0 )
+ root = copyBranch( other.root );
+}
+
+#if defined( AVLTREE_MAP ) || defined( AVLTREE_SET )
+
+/* Assignment does deep copy. */
+template <AVLMEL_TEMPDEF> AvlTree<AVLMEL_TEMPUSE> &AvlTree<AVLMEL_TEMPUSE>::
+ operator=( const AvlTree &other )
+{
+ /* Clear the tree first. */
+ empty();
+
+ /* Reset the list pointers, the tree copy will fill in the list for us. */
+#ifdef WALKABLE
+ BASELIST::abandon();
+#else
+ head = 0;
+ tail = 0;
+#endif
+
+ /* Copy the entire tree. */
+ treeSize = other.treeSize;
+ root = other.root;
+ if ( other.root != 0 )
+ root = copyBranch( other.root );
+ return *this;
+}
+
+template <AVLMEL_TEMPDEF> void AvlTree<AVLMEL_TEMPUSE>::
+ transfer(AvlTree<AVLMEL_TEMPUSE> &other)
+{
+ /* Clear the tree first. */
+ empty();
+
+ treeSize = other.treeSize;
+ root = other.root;
+
+#ifdef WALKABLE
+ BASELIST::head = other.BASELIST::head;
+ BASELIST::tail = other.BASELIST::tail;
+ BASELIST::listLen = other.BASELIST::listLen;
+#else
+ head = other.head;
+ tail = other.tail;
+#endif
+
+ other.abandon();
+}
+
+#else /* ! AVLTREE_MAP && ! AVLTREE_SET */
+
+/* Assignment does deep copy. This version does not clear the tree first. */
+template <AVLMEL_TEMPDEF> AvlTree<AVLMEL_TEMPUSE> &AvlTree<AVLMEL_TEMPUSE>::
+ operator=( const AvlTree &other )
+{
+ /* Reset the list pointers, the tree copy will fill in the list for us. */
+#ifdef WALKABLE
+ BASELIST::abandon();
+#else
+ head = 0;
+ tail = 0;
+#endif
+
+ /* Copy the entire tree. */
+ treeSize = other.treeSize;
+ root = other.root;
+ if ( other.root != 0 )
+ root = copyBranch( other.root );
+ return *this;
+}
+
+template <AVLMEL_TEMPDEF> void AvlTree<AVLMEL_TEMPUSE>::
+ transfer(AvlTree<AVLMEL_TEMPUSE> &other)
+{
+ treeSize = other.treeSize;
+ root = other.root;
+
+#ifdef WALKABLE
+ BASELIST::head = other.BASELIST::head;
+ BASELIST::tail = other.BASELIST::tail;
+ BASELIST::listLen = other.BASELIST::listLen;
+#else
+ head = other.head;
+ tail = other.tail;
+#endif
+
+ other.abandon();
+}
+
+#endif
+
+/*
+ * Iterator operators.
+ */
+
+/* Prefix ++ */
+template <AVLMEL_TEMPDEF> Element *AvlTree<AVLMEL_TEMPUSE>::Iter::
+ operator++()
+{
+ return ptr = findNext( ptr );
+}
+
+/* Postfix ++ */
+template <AVLMEL_TEMPDEF> Element *AvlTree<AVLMEL_TEMPUSE>::Iter::
+ operator++(int)
+{
+ Element *rtn = ptr;
+ ptr = findNext( ptr );
+ return rtn;
+}
+
+/* increment */
+template <AVLMEL_TEMPDEF> Element *AvlTree<AVLMEL_TEMPUSE>::Iter::
+ increment()
+{
+ return ptr = findNext( ptr );
+}
+
+/* Prefix -- */
+template <AVLMEL_TEMPDEF> Element *AvlTree<AVLMEL_TEMPUSE>::Iter::
+ operator--()
+{
+ return ptr = findPrev( ptr );
+}
+
+/* Postfix -- */
+template <AVLMEL_TEMPDEF> Element *AvlTree<AVLMEL_TEMPUSE>::Iter::
+ operator--(int)
+{
+ Element *rtn = ptr;
+ ptr = findPrev( ptr );
+ return rtn;
+}
+
+/* decrement */
+template <AVLMEL_TEMPDEF> Element *AvlTree<AVLMEL_TEMPUSE>::Iter::
+ decrement()
+{
+ return ptr = findPrev( ptr );
+}
+
+#ifndef WALKABLE
+
+/* Move ahead one. */
+template <AVLMEL_TEMPDEF> Element *AvlTree<AVLMEL_TEMPUSE>::Iter::
+ findNext( Element *element )
+{
+ /* Try to go right once then infinite left. */
+ if ( element->BASE_EL(right) != 0 ) {
+ element = element->BASE_EL(right);
+ while ( element->BASE_EL(left) != 0 )
+ element = element->BASE_EL(left);
+ }
+ else {
+ /* Go up to parent until we were just a left child. */
+ while ( true ) {
+ Element *last = element;
+ element = element->BASE_EL(parent);
+ if ( element == 0 || element->BASE_EL(left) == last )
+ break;
+ }
+ }
+ return element;
+}
+
+/* Move back one. */
+template <AVLMEL_TEMPDEF> Element *AvlTree<AVLMEL_TEMPUSE>::Iter::
+ findPrev( Element *element )
+{
+ /* Try to go left once then infinite right. */
+ if ( element->BASE_EL(left) != 0 ) {
+ element = element->BASE_EL(left);
+ while ( element->BASE_EL(right) != 0 )
+ element = element->BASE_EL(right);
+ }
+ else {
+ /* Go up to parent until we were just a left child. */
+ while ( true ) {
+ Element *last = element;
+ element = element->BASE_EL(parent);
+ if ( element == 0 || element->BASE_EL(right) == last )
+ break;
+ }
+ }
+ return element;
+}
+
+#endif
+
+
+/* Recursive worker for tree copying. */
+template <AVLMEL_TEMPDEF> Element *AvlTree<AVLMEL_TEMPUSE>::
+ copyBranch( Element *element )
+{
+ /* Duplicate element. Either the base element's copy constructor or defaul
+ * constructor will get called. Both will suffice for initting the
+ * pointers to null when they need to be. */
+ Element *retVal = new Element(*element);
+
+ /* If the left tree is there, copy it. */
+ if ( retVal->BASE_EL(left) ) {
+ retVal->BASE_EL(left) = copyBranch(retVal->BASE_EL(left));
+ retVal->BASE_EL(left)->BASE_EL(parent) = retVal;
+ }
+
+#ifdef WALKABLE
+ BASELIST::addAfter( BASELIST::tail, retVal );
+#else
+ if ( head == 0 )
+ head = retVal;
+ tail = retVal;
+#endif
+
+ /* If the right tree is there, copy it. */
+ if ( retVal->BASE_EL(right) ) {
+ retVal->BASE_EL(right) = copyBranch(retVal->BASE_EL(right));
+ retVal->BASE_EL(right)->BASE_EL(parent) = retVal;
+ }
+ return retVal;
+}
+
+/* Once an insertion position is found, attach a element to the tree. */
+template <AVLMEL_TEMPDEF> void AvlTree<AVLMEL_TEMPUSE>::
+ attachRebal( Element *element, Element *parentEl, Element *lastLess )
+{
+ /* Increment the number of element in the tree. */
+ treeSize += 1;
+
+ /* Set element's parent. */
+ element->BASE_EL(parent) = parentEl;
+
+ /* New element always starts as a leaf with height 1. */
+ element->BASE_EL(left) = 0;
+ element->BASE_EL(right) = 0;
+ element->BASE_EL(height) = 1;
+
+ /* Are we inserting in the tree somewhere? */
+ if ( parentEl != 0 ) {
+ /* We have a parent so we are somewhere in the tree. If the parent
+ * equals lastLess, then the last traversal in the insertion went
+ * left, otherwise it went right. */
+ if ( lastLess == parentEl ) {
+ parentEl->BASE_EL(left) = element;
+#ifdef WALKABLE
+ BASELIST::addBefore( parentEl, element );
+#endif
+ }
+ else {
+ parentEl->BASE_EL(right) = element;
+#ifdef WALKABLE
+ BASELIST::addAfter( parentEl, element );
+#endif
+ }
+
+#ifndef WALKABLE
+ /* Maintain the first and last pointers. */
+ if ( head->BASE_EL(left) == element )
+ head = element;
+
+ /* Maintain the first and last pointers. */
+ if ( tail->BASE_EL(right) == element )
+ tail = element;
+#endif
+ }
+ else {
+ /* No parent element so we are inserting the root. */
+ root = element;
+#ifdef WALKABLE
+ BASELIST::addAfter( BASELIST::tail, element );
+#else
+ head = tail = element;
+#endif
+ }
+
+
+ /* Recalculate the heights. */
+ recalcHeights(parentEl);
+
+ /* Find the first unbalance. */
+ Element *ub = findFirstUnbalGP(element);
+
+ /* rebalance. */
+ if ( ub != 0 )
+ {
+ /* We assert that after this single rotation the
+ * tree is now properly balanced. */
+ rebalance(ub);
+ }
+}
+
+#ifndef AVL_KEYLESS
+
+/**
+ * \brief Insert an existing element into the tree.
+ *
+ * If the insert succeeds and lastFound is given then it is set to the element
+ * inserted. If the insert fails then lastFound is set to the existing element in
+ * the tree that has the same key as element. If the element's avl pointers are
+ * already in use then undefined behaviour results.
+ *
+ * \returns The element inserted upon success, null upon failure.
+ */
+template <AVLMEL_TEMPDEF> Element *AvlTree<AVLMEL_TEMPUSE>::
+ insert( Element *element, Element **lastFound )
+{
+ long keyRelation;
+ Element *curEl = root, *parentEl = 0;
+ Element *lastLess = 0;
+
+ while (true) {
+ if ( curEl == 0 ) {
+ /* We are at an external element and did not find the key we were
+ * looking for. Attach underneath the leaf and rebalance. */
+ attachRebal( element, parentEl, lastLess );
+
+ if ( lastFound != 0 )
+ *lastFound = element;
+ return element;
+ }
+
+#ifdef AVL_BASIC
+ keyRelation = this->compare( *element, *curEl );
+#else
+ keyRelation = this->compare( element->BASEKEY(getKey()),
+ curEl->BASEKEY(getKey()) );
+#endif
+
+ /* Do we go left? */
+ if ( keyRelation < 0 ) {
+ parentEl = lastLess = curEl;
+ curEl = curEl->BASE_EL(left);
+ }
+ /* Do we go right? */
+ else if ( keyRelation > 0 ) {
+ parentEl = curEl;
+ curEl = curEl->BASE_EL(right);
+ }
+ /* We have hit the target. */
+ else {
+ if ( lastFound != 0 )
+ *lastFound = curEl;
+ return 0;
+ }
+ }
+}
+
+#ifdef AVL_BASIC
+
+/**
+ * \brief Find a element in the tree with the given key.
+ *
+ * \returns The element if key exists, null if the key does not exist.
+ */
+template <AVLMEL_TEMPDEF> Element *AvlTree<AVLMEL_TEMPUSE>::
+ find( const Element *element ) const
+{
+ Element *curEl = root;
+ long keyRelation;
+
+ while (curEl) {
+ keyRelation = this->compare( *element, *curEl );
+
+ /* Do we go left? */
+ if ( keyRelation < 0 )
+ curEl = curEl->BASE_EL(left);
+ /* Do we go right? */
+ else if ( keyRelation > 0 )
+ curEl = curEl->BASE_EL(right);
+ /* We have hit the target. */
+ else {
+ return curEl;
+ }
+ }
+ return 0;
+}
+
+#else
+
+/**
+ * \brief Insert a new element into the tree with given key.
+ *
+ * If the key is not already in the tree then a new element is made using the
+ * Element(const Key &key) constructor and the insert succeeds. If lastFound is
+ * given then it is set to the element inserted. If the insert fails then
+ * lastFound is set to the existing element in the tree that has the same key as
+ * element.
+ *
+ * \returns The new element upon success, null upon failure.
+ */
+template <AVLMEL_TEMPDEF> Element *AvlTree<AVLMEL_TEMPUSE>::
+ insert( const Key &key, Element **lastFound )
+{
+ long keyRelation;
+ Element *curEl = root, *parentEl = 0;
+ Element *lastLess = 0;
+
+ while (true) {
+ if ( curEl == 0 ) {
+ /* We are at an external element and did not find the key we were
+ * looking for. Create the new element, attach it underneath the leaf
+ * and rebalance. */
+ Element *element = new Element( key );
+ attachRebal( element, parentEl, lastLess );
+
+ if ( lastFound != 0 )
+ *lastFound = element;
+ return element;
+ }
+
+ keyRelation = this->compare( key, curEl->BASEKEY(getKey()) );
+
+ /* Do we go left? */
+ if ( keyRelation < 0 ) {
+ parentEl = lastLess = curEl;
+ curEl = curEl->BASE_EL(left);
+ }
+ /* Do we go right? */
+ else if ( keyRelation > 0 ) {
+ parentEl = curEl;
+ curEl = curEl->BASE_EL(right);
+ }
+ /* We have hit the target. */
+ else {
+ if ( lastFound != 0 )
+ *lastFound = curEl;
+ return 0;
+ }
+ }
+}
+
+#ifdef AVLTREE_MAP
+/**
+ * \brief Insert a new element into the tree with key and value.
+ *
+ * If the key is not already in the tree then a new element is constructed and
+ * the insert succeeds. If lastFound is given then it is set to the element
+ * inserted. If the insert fails then lastFound is set to the existing element in
+ * the tree that has the same key as element. This insert routine is only
+ * available in AvlMap because it is the only class that knows about a Value
+ * type.
+ *
+ * \returns The new element upon success, null upon failure.
+ */
+template <AVLMEL_TEMPDEF> Element *AvlTree<AVLMEL_TEMPUSE>::
+ insert( const Key &key, const Value &val, Element **lastFound )
+{
+ long keyRelation;
+ Element *curEl = root, *parentEl = 0;
+ Element *lastLess = 0;
+
+ while (true) {
+ if ( curEl == 0 ) {
+ /* We are at an external element and did not find the key we were
+ * looking for. Create the new element, attach it underneath the leaf
+ * and rebalance. */
+ Element *element = new Element( key, val );
+ attachRebal( element, parentEl, lastLess );
+
+ if ( lastFound != 0 )
+ *lastFound = element;
+ return element;
+ }
+
+ keyRelation = this->compare(key, curEl->getKey());
+
+ /* Do we go left? */
+ if ( keyRelation < 0 ) {
+ parentEl = lastLess = curEl;
+ curEl = curEl->BASE_EL(left);
+ }
+ /* Do we go right? */
+ else if ( keyRelation > 0 ) {
+ parentEl = curEl;
+ curEl = curEl->BASE_EL(right);
+ }
+ /* We have hit the target. */
+ else {
+ if ( lastFound != 0 )
+ *lastFound = curEl;
+ return 0;
+ }
+ }
+}
+#endif /* AVLTREE_MAP */
+
+
+/**
+ * \brief Find a element in the tree with the given key.
+ *
+ * \returns The element if key exists, null if the key does not exist.
+ */
+template <AVLMEL_TEMPDEF> Element *AvlTree<AVLMEL_TEMPUSE>::
+ find( const Key &key ) const
+{
+ Element *curEl = root;
+ long keyRelation;
+
+ while (curEl) {
+ keyRelation = this->compare( key, curEl->BASEKEY(getKey()) );
+
+ /* Do we go left? */
+ if ( keyRelation < 0 )
+ curEl = curEl->BASE_EL(left);
+ /* Do we go right? */
+ else if ( keyRelation > 0 )
+ curEl = curEl->BASE_EL(right);
+ /* We have hit the target. */
+ else {
+ return curEl;
+ }
+ }
+ return 0;
+}
+
+
+/**
+ * \brief Find a element, then detach it from the tree.
+ *
+ * The element is not deleted.
+ *
+ * \returns The element detached if the key is found, othewise returns null.
+ */
+template <AVLMEL_TEMPDEF> Element *AvlTree<AVLMEL_TEMPUSE>::
+ detach(const Key &key)
+{
+ Element *element = find( key );
+ if ( element ) {
+ detach(element);
+ }
+
+ return element;
+}
+
+/**
+ * \brief Find, detach and delete a element from the tree.
+ *
+ * \returns True if the element was found and deleted, false otherwise.
+ */
+template <AVLMEL_TEMPDEF> bool AvlTree<AVLMEL_TEMPUSE>::
+ remove(const Key &key)
+{
+ /* Assume not found. */
+ bool retVal = false;
+
+ /* Look for the key. */
+ Element *element = find( key );
+ if ( element != 0 ) {
+ /* If found, detach the element and delete. */
+ detach( element );
+ delete element;
+ retVal = true;
+ }
+
+ return retVal;
+}
+
+#endif /* AVL_BASIC */
+#endif /* AVL_KEYLESS */
+
+
+/**
+ * \brief Detach and delete a element from the tree.
+ *
+ * If the element is not in the tree then undefined behaviour results.
+ */
+template <AVLMEL_TEMPDEF> void AvlTree<AVLMEL_TEMPUSE>::
+ remove(Element *element)
+{
+ /* Detach and delete. */
+ detach(element);
+ delete element;
+}
+
+/**
+ * \brief Detach a element from the tree.
+ *
+ * If the element is not in the tree then undefined behaviour results.
+ *
+ * \returns The element given.
+ */
+template <AVLMEL_TEMPDEF> Element *AvlTree<AVLMEL_TEMPUSE>::
+ detach(Element *element)
+{
+ Element *replacement, *fixfrom;
+ long lheight, rheight;
+
+#ifdef WALKABLE
+ /* Remove the element from the ordered list. */
+ BASELIST::detach( element );
+#endif
+
+ /* Update treeSize. */
+ treeSize--;
+
+ /* Find a replacement element. */
+ if (element->BASE_EL(right))
+ {
+ /* Find the leftmost element of the right subtree. */
+ replacement = element->BASE_EL(right);
+ while (replacement->BASE_EL(left))
+ replacement = replacement->BASE_EL(left);
+
+ /* If replacing the element the with its child then we need to start
+ * fixing at the replacement, otherwise we start fixing at the
+ * parent of the replacement. */
+ if (replacement->BASE_EL(parent) == element)
+ fixfrom = replacement;
+ else
+ fixfrom = replacement->BASE_EL(parent);
+
+#ifndef WALKABLE
+ if ( element == head )
+ head = replacement;
+#endif
+
+ removeEl(replacement, replacement->BASE_EL(right));
+ replaceEl(element, replacement);
+ }
+ else if (element->BASE_EL(left))
+ {
+ /* Find the rightmost element of the left subtree. */
+ replacement = element->BASE_EL(left);
+ while (replacement->BASE_EL(right))
+ replacement = replacement->BASE_EL(right);
+
+ /* If replacing the element the with its child then we need to start
+ * fixing at the replacement, otherwise we start fixing at the
+ * parent of the replacement. */
+ if (replacement->BASE_EL(parent) == element)
+ fixfrom = replacement;
+ else
+ fixfrom = replacement->BASE_EL(parent);
+
+#ifndef WALKABLE
+ if ( element == tail )
+ tail = replacement;
+#endif
+
+ removeEl(replacement, replacement->BASE_EL(left));
+ replaceEl(element, replacement);
+ }
+ else
+ {
+ /* We need to start fixing at the parent of the element. */
+ fixfrom = element->BASE_EL(parent);
+
+#ifndef WALKABLE
+ if ( element == head )
+ head = element->BASE_EL(parent);
+ if ( element == tail )
+ tail = element->BASE_EL(parent);
+#endif
+
+ /* The element we are deleting is a leaf element. */
+ removeEl(element, 0);
+ }
+
+ /* If fixfrom is null it means we just deleted
+ * the root of the tree. */
+ if ( fixfrom == 0 )
+ return element;
+
+ /* Fix the heights after the deletion. */
+ recalcHeights(fixfrom);
+
+ /* Fix every unbalanced element going up in the tree. */
+ Element *ub = findFirstUnbalEl(fixfrom);
+ while ( ub )
+ {
+ /* Find the element to rebalance by moving down from the first unbalanced
+ * element 2 levels in the direction of the greatest heights. On the
+ * second move down, the heights may be equal ( but not on the first ).
+ * In which case go in the direction of the first move. */
+ lheight = ub->BASE_EL(left) ? ub->BASE_EL(left)->BASE_EL(height) : 0;
+ rheight = ub->BASE_EL(right) ? ub->BASE_EL(right)->BASE_EL(height) : 0;
+ assert( lheight != rheight );
+ if (rheight > lheight)
+ {
+ ub = ub->BASE_EL(right);
+ lheight = ub->BASE_EL(left) ?
+ ub->BASE_EL(left)->BASE_EL(height) : 0;
+ rheight = ub->BASE_EL(right) ?
+ ub->BASE_EL(right)->BASE_EL(height) : 0;
+ if (rheight > lheight)
+ ub = ub->BASE_EL(right);
+ else if (rheight < lheight)
+ ub = ub->BASE_EL(left);
+ else
+ ub = ub->BASE_EL(right);
+ }
+ else
+ {
+ ub = ub->BASE_EL(left);
+ lheight = ub->BASE_EL(left) ?
+ ub->BASE_EL(left)->BASE_EL(height) : 0;
+ rheight = ub->BASE_EL(right) ?
+ ub->BASE_EL(right)->BASE_EL(height) : 0;
+ if (rheight > lheight)
+ ub = ub->BASE_EL(right);
+ else if (rheight < lheight)
+ ub = ub->BASE_EL(left);
+ else
+ ub = ub->BASE_EL(left);
+ }
+
+
+ /* rebalance returns the grandparant of the subtree formed
+ * by the element that were rebalanced.
+ * We must continue upward from there rebalancing. */
+ fixfrom = rebalance(ub);
+
+ /* Find the next unbalaced element. */
+ ub = findFirstUnbalEl(fixfrom);
+ }
+
+ return element;
+}
+
+
+/**
+ * \brief Empty the tree and delete all the element.
+ *
+ * Resets the tree to its initial state.
+ */
+template <AVLMEL_TEMPDEF> void AvlTree<AVLMEL_TEMPUSE>::empty()
+{
+ if ( root ) {
+ /* Recursively delete from the tree structure. */
+ deleteChildrenOf(root);
+ delete root;
+ root = 0;
+ treeSize = 0;
+
+#ifdef WALKABLE
+ BASELIST::abandon();
+#else
+ head = tail = 0;
+#endif
+ }
+}
+
+/**
+ * \brief Forget all element in the tree.
+ *
+ * Does not delete element. Resets the the tree to it's initial state.
+ */
+template <AVLMEL_TEMPDEF> void AvlTree<AVLMEL_TEMPUSE>::abandon()
+{
+ root = 0;
+ treeSize = 0;
+
+#ifdef WALKABLE
+ BASELIST::abandon();
+#else
+ head = tail = 0;
+#endif
+}
+
+/* Recursively delete all the children of a element. */
+template <AVLMEL_TEMPDEF> void AvlTree<AVLMEL_TEMPUSE>::
+ deleteChildrenOf( Element *element )
+{
+ /* Recurse left. */
+ if (element->BASE_EL(left)) {
+ deleteChildrenOf(element->BASE_EL(left));
+
+ /* Delete left element. */
+ delete element->BASE_EL(left);
+ element->BASE_EL(left) = 0;
+ }
+
+ /* Recurse right. */
+ if (element->BASE_EL(right)) {
+ deleteChildrenOf(element->BASE_EL(right));
+
+ /* Delete right element. */
+ delete element->BASE_EL(right);
+ element->BASE_EL(left) = 0;
+ }
+}
+
+/* rebalance from a element whose gradparent is unbalanced. Only
+ * call on a element that has a grandparent. */
+template <AVLMEL_TEMPDEF> Element *AvlTree<AVLMEL_TEMPUSE>::
+ rebalance(Element *n)
+{
+ long lheight, rheight;
+ Element *a, *b, *c;
+ Element *t1, *t2, *t3, *t4;
+
+ Element *p = n->BASE_EL(parent); /* parent (Non-NUL). L*/
+ Element *gp = p->BASE_EL(parent); /* Grand-parent (Non-NULL). */
+ Element *ggp = gp->BASE_EL(parent); /* Great grand-parent (may be NULL). */
+
+ if (gp->BASE_EL(right) == p)
+ {
+ /* gp
+ * \
+ * p
+ */
+ if (p->BASE_EL(right) == n)
+ {
+ /* gp
+ * \
+ * p
+ * \
+ * n
+ */
+ a = gp;
+ b = p;
+ c = n;
+ t1 = gp->BASE_EL(left);
+ t2 = p->BASE_EL(left);
+ t3 = n->BASE_EL(left);
+ t4 = n->BASE_EL(right);
+ }
+ else
+ {
+ /* gp
+ * \
+ * p
+ * /
+ * n
+ */
+ a = gp;
+ b = n;
+ c = p;
+ t1 = gp->BASE_EL(left);
+ t2 = n->BASE_EL(left);
+ t3 = n->BASE_EL(right);
+ t4 = p->BASE_EL(right);
+ }
+ }
+ else
+ {
+ /* gp
+ * /
+ * p
+ */
+ if (p->BASE_EL(right) == n)
+ {
+ /* gp
+ * /
+ * p
+ * \
+ * n
+ */
+ a = p;
+ b = n;
+ c = gp;
+ t1 = p->BASE_EL(left);
+ t2 = n->BASE_EL(left);
+ t3 = n->BASE_EL(right);
+ t4 = gp->BASE_EL(right);
+ }
+ else
+ {
+ /* gp
+ * /
+ * p
+ * /
+ * n
+ */
+ a = n;
+ b = p;
+ c = gp;
+ t1 = n->BASE_EL(left);
+ t2 = n->BASE_EL(right);
+ t3 = p->BASE_EL(right);
+ t4 = gp->BASE_EL(right);
+ }
+ }
+
+ /* Perform rotation.
+ */
+
+ /* Tie b to the great grandparent. */
+ if ( ggp == 0 )
+ root = b;
+ else if ( ggp->BASE_EL(left) == gp )
+ ggp->BASE_EL(left) = b;
+ else
+ ggp->BASE_EL(right) = b;
+ b->BASE_EL(parent) = ggp;
+
+ /* Tie a as a leftchild of b. */
+ b->BASE_EL(left) = a;
+ a->BASE_EL(parent) = b;
+
+ /* Tie c as a rightchild of b. */
+ b->BASE_EL(right) = c;
+ c->BASE_EL(parent) = b;
+
+ /* Tie t1 as a leftchild of a. */
+ a->BASE_EL(left) = t1;
+ if ( t1 != 0 ) t1->BASE_EL(parent) = a;
+
+ /* Tie t2 as a rightchild of a. */
+ a->BASE_EL(right) = t2;
+ if ( t2 != 0 ) t2->BASE_EL(parent) = a;
+
+ /* Tie t3 as a leftchild of c. */
+ c->BASE_EL(left) = t3;
+ if ( t3 != 0 ) t3->BASE_EL(parent) = c;
+
+ /* Tie t4 as a rightchild of c. */
+ c->BASE_EL(right) = t4;
+ if ( t4 != 0 ) t4->BASE_EL(parent) = c;
+
+ /* The heights are all recalculated manualy and the great
+ * grand-parent is passed to recalcHeights() to ensure
+ * the heights are correct up the tree.
+ *
+ * Note that recalcHeights() cuts out when it comes across
+ * a height that hasn't changed.
+ */
+
+ /* Fix height of a. */
+ lheight = a->BASE_EL(left) ? a->BASE_EL(left)->BASE_EL(height) : 0;
+ rheight = a->BASE_EL(right) ? a->BASE_EL(right)->BASE_EL(height) : 0;
+ a->BASE_EL(height) = (lheight > rheight ? lheight : rheight) + 1;
+
+ /* Fix height of c. */
+ lheight = c->BASE_EL(left) ? c->BASE_EL(left)->BASE_EL(height) : 0;
+ rheight = c->BASE_EL(right) ? c->BASE_EL(right)->BASE_EL(height) : 0;
+ c->BASE_EL(height) = (lheight > rheight ? lheight : rheight) + 1;
+
+ /* Fix height of b. */
+ lheight = a->BASE_EL(height);
+ rheight = c->BASE_EL(height);
+ b->BASE_EL(height) = (lheight > rheight ? lheight : rheight) + 1;
+
+ /* Fix height of b's parents. */
+ recalcHeights(ggp);
+ return ggp;
+}
+
+/* Recalculates the heights of all the ancestors of element. */
+template <AVLMEL_TEMPDEF> void AvlTree<AVLMEL_TEMPUSE>::
+ recalcHeights(Element *element)
+{
+ long lheight, rheight, new_height;
+ while ( element != 0 )
+ {
+ lheight = element->BASE_EL(left) ? element->BASE_EL(left)->BASE_EL(height) : 0;
+ rheight = element->BASE_EL(right) ? element->BASE_EL(right)->BASE_EL(height) : 0;
+
+ new_height = (lheight > rheight ? lheight : rheight) + 1;
+
+ /* If there is no chage in the height, then there will be no
+ * change in any of the ancestor's height. We can stop going up.
+ * If there was a change, continue upward. */
+ if (new_height == element->BASE_EL(height))
+ return;
+ else
+ element->BASE_EL(height) = new_height;
+
+ element = element->BASE_EL(parent);
+ }
+}
+
+/* Finds the first element whose grandparent is unbalanced. */
+template <AVLMEL_TEMPDEF> Element *AvlTree<AVLMEL_TEMPUSE>::
+ findFirstUnbalGP(Element *element)
+{
+ long lheight, rheight, balanceProp;
+ Element *gp;
+
+ if ( element == 0 || element->BASE_EL(parent) == 0 ||
+ element->BASE_EL(parent)->BASE_EL(parent) == 0 )
+ return 0;
+
+ /* Don't do anything if we we have no grandparent. */
+ gp = element->BASE_EL(parent)->BASE_EL(parent);
+ while ( gp != 0 )
+ {
+ lheight = gp->BASE_EL(left) ? gp->BASE_EL(left)->BASE_EL(height) : 0;
+ rheight = gp->BASE_EL(right) ? gp->BASE_EL(right)->BASE_EL(height) : 0;
+ balanceProp = lheight - rheight;
+
+ if ( balanceProp < -1 || balanceProp > 1 )
+ return element;
+
+ element = element->BASE_EL(parent);
+ gp = gp->BASE_EL(parent);
+ }
+ return 0;
+}
+
+
+/* Finds the first element that is unbalanced. */
+template <AVLMEL_TEMPDEF> Element *AvlTree<AVLMEL_TEMPUSE>::
+ findFirstUnbalEl(Element *element)
+{
+ if ( element == 0 )
+ return 0;
+
+ while ( element != 0 )
+ {
+ long lheight = element->BASE_EL(left) ?
+ element->BASE_EL(left)->BASE_EL(height) : 0;
+ long rheight = element->BASE_EL(right) ?
+ element->BASE_EL(right)->BASE_EL(height) : 0;
+ long balanceProp = lheight - rheight;
+
+ if ( balanceProp < -1 || balanceProp > 1 )
+ return element;
+
+ element = element->BASE_EL(parent);
+ }
+ return 0;
+}
+
+/* Replace a element in the tree with another element not in the tree. */
+template <AVLMEL_TEMPDEF> void AvlTree<AVLMEL_TEMPUSE>::
+ replaceEl(Element *element, Element *replacement)
+{
+ Element *parent = element->BASE_EL(parent),
+ *left = element->BASE_EL(left),
+ *right = element->BASE_EL(right);
+
+ replacement->BASE_EL(left) = left;
+ if (left)
+ left->BASE_EL(parent) = replacement;
+ replacement->BASE_EL(right) = right;
+ if (right)
+ right->BASE_EL(parent) = replacement;
+
+ replacement->BASE_EL(parent) = parent;
+ if (parent)
+ {
+ if (parent->BASE_EL(left) == element)
+ parent->BASE_EL(left) = replacement;
+ else
+ parent->BASE_EL(right) = replacement;
+ }
+ else
+ root = replacement;
+
+ replacement->BASE_EL(height) = element->BASE_EL(height);
+}
+
+/* Removes a element from a tree and puts filler in it's place.
+ * Filler should be null or a child of element. */
+template <AVLMEL_TEMPDEF> void AvlTree<AVLMEL_TEMPUSE>::
+ removeEl(Element *element, Element *filler)
+{
+ Element *parent = element->BASE_EL(parent);
+
+ if (parent)
+ {
+ if (parent->BASE_EL(left) == element)
+ parent->BASE_EL(left) = filler;
+ else
+ parent->BASE_EL(right) = filler;
+ }
+ else
+ root = filler;
+
+ if (filler)
+ filler->BASE_EL(parent) = parent;
+
+ return;
+}
+
+#ifdef AAPL_NAMESPACE
+}
+#endif
diff --git a/src/aapl/avlibasic.h b/src/aapl/avlibasic.h
new file mode 100644
index 00000000..5f9b2c7f
--- /dev/null
+++ b/src/aapl/avlibasic.h
@@ -0,0 +1,68 @@
+/*
+ * Copyright 2002 Adrian Thurston <thurston@colm.net>
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to
+ * deal in the Software without restriction, including without limitation the
+ * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
+ * sell copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+#ifndef _AAPL_AVLIBASIC_H
+#define _AAPL_AVLIBASIC_H
+
+#include "compare.h"
+
+/**
+ * \addtogroup avlitree
+ * @{
+ */
+
+/**
+ * \class AvliBasic
+ * \brief Linked AVL Tree in which the entire element structure is the key.
+ *
+ * AvliBasic is a linked AVL tree that does not distinguish between the
+ * element that it contains and the key. The entire element structure is the
+ * key that is used to compare the relative ordering of elements. This is
+ * similar to the BstSet structure.
+ *
+ * AvliBasic does not assume ownership of elements in the tree. Items must be
+ * explicitly de-allocated.
+ */
+
+/*@}*/
+
+#define BASE_EL(name) name
+#define BASEKEY(name) name
+#define AVLMEL_CLASSDEF class Element, class Compare
+#define AVLMEL_TEMPDEF class Element, class Compare
+#define AVLMEL_TEMPUSE Element, Compare
+#define AvlTree AvliBasic
+#define AVL_BASIC
+#define WALKABLE
+
+#include "avlcommon.h"
+
+#undef BASE_EL
+#undef BASEKEY
+#undef AVLMEL_CLASSDEF
+#undef AVLMEL_TEMPDEF
+#undef AVLMEL_TEMPUSE
+#undef AvlTree
+#undef AVL_BASIC
+#undef WALKABLE
+
+#endif /* _AAPL_AVLIBASIC_H */
diff --git a/src/aapl/avlikeyless.h b/src/aapl/avlikeyless.h
new file mode 100644
index 00000000..8d90443b
--- /dev/null
+++ b/src/aapl/avlikeyless.h
@@ -0,0 +1,65 @@
+/*
+ * Copyright 2002, 2003 Adrian Thurston <thurston@colm.net>
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to
+ * deal in the Software without restriction, including without limitation the
+ * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
+ * sell copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+#ifndef _AAPL_AVLIKEYLESS_H
+#define _AAPL_AVLIKEYLESS_H
+
+#include "compare.h"
+#include "dlistmel.h"
+
+/**
+ * \addtogroup avlitree
+ * @{
+ */
+
+/**
+ * \class AvliKeyless
+ * \brief Linked AVL tree that has no insert/find/remove functions that take a
+ * key.
+ *
+ * AvliKeyless is an implementation of the AVL tree rebalancing functionality
+ * only. It provides the common code for the tiny AVL tree implementations.
+ */
+
+/*@}*/
+
+#define BASE_EL(name) name
+#define BASELIST DListMel< Element, AvliTreeEl<Element> >
+#define AVLMEL_CLASSDEF class Element
+#define AVLMEL_TEMPDEF class Element
+#define AVLMEL_TEMPUSE Element
+#define AvlTree AvliKeyless
+#define WALKABLE
+#define AVL_KEYLESS
+
+#include "avlcommon.h"
+
+#undef BASE_EL
+#undef BASELIST
+#undef AVLMEL_CLASSDEF
+#undef AVLMEL_TEMPDEF
+#undef AVLMEL_TEMPUSE
+#undef AvlTree
+#undef WALKABLE
+#undef AVL_KEYLESS
+
+#endif /* _AAPL_AVLIKEYLESS_H */
diff --git a/src/aapl/avlimap.h b/src/aapl/avlimap.h
new file mode 100644
index 00000000..f2b1b0c5
--- /dev/null
+++ b/src/aapl/avlimap.h
@@ -0,0 +1,78 @@
+/*
+ * Copyright 2002 Adrian Thurston <thurston@colm.net>
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to
+ * deal in the Software without restriction, including without limitation the
+ * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
+ * sell copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+#ifndef _AAPL_AVLIMAP_H
+#define _AAPL_AVLIMAP_H
+
+#include "compare.h"
+#include "dlist.h"
+
+/**
+ * \addtogroup avlitree
+ * @{
+ */
+
+/**
+ * \class AvliMap
+ * \brief Linked key and value oriented AVL tree.
+ *
+ * AvliMap stores key and value pairs in elements that managed by the tree. It
+ * is intendend to be similar to map template found in the STL. AvliMap
+ * requires that a Key type, a Value type, and a class containing a compare()
+ * routine for Key be given. Items can be inserted with just a key or with a
+ * key and value pair.
+ *
+ * AvliMap assumes all elements in the tree are allocated on the heap and are
+ * to be managed by the tree. This means that the class destructor will delete
+ * the contents of the tree. A deep copy will cause existing elements to be
+ * deleted first.
+ *
+ * \include ex_avlimap.cpp
+ */
+
+/*@}*/
+
+#define AVLTREE_MAP
+#define BASE_EL(name) name
+#define BASEKEY(name) name
+#define BASELIST DList< AvliMapEl<Key,Value> >
+#define AVLMEL_CLASSDEF class Key, class Value, class Compare = CmpOrd<Key>
+#define AVLMEL_TEMPDEF class Key, class Value, class Compare
+#define AVLMEL_TEMPUSE Key, Value, Compare
+#define AvlTree AvliMap
+#define Element AvliMapEl<Key,Value>
+#define WALKABLE
+
+#include "avlcommon.h"
+
+#undef AVLTREE_MAP
+#undef BASE_EL
+#undef BASEKEY
+#undef BASELIST
+#undef AVLMEL_CLASSDEF
+#undef AVLMEL_TEMPDEF
+#undef AVLMEL_TEMPUSE
+#undef AvlTree
+#undef Element
+#undef WALKABLE
+
+#endif /* _AAPL_AVLIMAP_H */
diff --git a/src/aapl/avlimel.h b/src/aapl/avlimel.h
new file mode 100644
index 00000000..9a7ff951
--- /dev/null
+++ b/src/aapl/avlimel.h
@@ -0,0 +1,80 @@
+/*
+ * Copyright 2002 Adrian Thurston <thurston@colm.net>
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to
+ * deal in the Software without restriction, including without limitation the
+ * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
+ * sell copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+#ifndef _AAPL_AVLIMEL_H
+#define _AAPL_AVLIMEL_H
+
+#include "compare.h"
+#include "dlistmel.h"
+
+/**
+ * \addtogroup avlitree
+ * @{
+ */
+
+/**
+ * \class AvliMel
+ * \brief Linked AVL tree for element appearing in multiple trees.
+ *
+ * AvliMel allows for an element to simultaneously be in multiple trees without
+ * the trees interferring with one another. For each tree that the element is
+ * to appear in, there must be a distinct set of AVL Tree management data that
+ * can be unambiguously referenced with some base class name. This name
+ * is passed to the tree as a template parameter and is used in the tree
+ * algorithms.
+ *
+ * The element must use the same key type and value in each tree that it
+ * appears in. If distinct keys are required, the AvliMelKey structure is
+ * available.
+ *
+ * AvliMel does not assume ownership of elements in the tree. The destructor
+ * will not delete the elements. If the user wishes to explicitly deallocate
+ * all the items in the tree the empty() routine is available.
+ *
+ * \include ex_avlimel.cpp
+ */
+
+/*@}*/
+
+#define BASE_EL(name) BaseEl::name
+#define BASEKEY(name) name
+#define BASELIST DListMel< Element, BaseEl >
+#define AVLMEL_CLASSDEF class Element, class Key, \
+ class BaseEl, class Compare = CmpOrd<Key>
+#define AVLMEL_TEMPDEF class Element, class Key, \
+ class BaseEl, class Compare
+#define AVLMEL_TEMPUSE Element, Key, BaseEl, Compare
+#define AvlTree AvliMel
+#define WALKABLE
+
+#include "avlcommon.h"
+
+#undef BASE_EL
+#undef BASEKEY
+#undef BASELIST
+#undef AVLMEL_CLASSDEF
+#undef AVLMEL_TEMPDEF
+#undef AVLMEL_TEMPUSE
+#undef AvlTree
+#undef WALKABLE
+
+#endif /* _AAPL_AVLIMEL_H */
diff --git a/src/aapl/avlimelkey.h b/src/aapl/avlimelkey.h
new file mode 100644
index 00000000..41d4ae49
--- /dev/null
+++ b/src/aapl/avlimelkey.h
@@ -0,0 +1,77 @@
+/*
+ * Copyright 2002 Adrian Thurston <thurston@colm.net>
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to
+ * deal in the Software without restriction, including without limitation the
+ * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
+ * sell copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+#ifndef _AAPL_AVLIMELKEY_H
+#define _AAPL_AVLIMELKEY_H
+
+#include "compare.h"
+#include "dlistmel.h"
+
+/**
+ * \addtogroup avlitree
+ * @{
+ */
+
+/**
+ * \class AvliMelKey
+ * \brief Linked AVL tree for element appearing in multiple trees with different keys.
+ *
+ * AvliMelKey is similar to AvliMel, except that an additional template
+ * parameter, BaseKey, is provided for resolving ambiguous references to
+ * getKey(). This means that if an element is stored in multiple trees, each
+ * tree can use a different key for ordering the elements in it. Using
+ * AvliMelKey an array of data structures can be indexed with an O(log(n))
+ * search on two or more of the values contained within it and without
+ * allocating any additional data.
+ *
+ * AvliMelKey does not assume ownership of elements in the tree. The destructor
+ * will not delete the elements. If the user wishes to explicitly deallocate
+ * all the items in the tree the empty() routine is available.
+ *
+ * \include ex_avlimelkey.cpp
+ */
+
+/*@}*/
+
+#define BASE_EL(name) BaseEl::name
+#define BASEKEY(name) BaseKey::name
+#define BASELIST DListMel< Element, BaseEl >
+#define AVLMEL_CLASSDEF class Element, class Key, class BaseEl, \
+ class BaseKey, class Compare = CmpOrd<Key>
+#define AVLMEL_TEMPDEF class Element, class Key, class BaseEl, \
+ class BaseKey, class Compare
+#define AVLMEL_TEMPUSE Element, Key, BaseEl, BaseKey, Compare
+#define AvlTree AvliMelKey
+#define WALKABLE
+
+#include "avlcommon.h"
+
+#undef BASE_EL
+#undef BASEKEY
+#undef BASELIST
+#undef AVLMEL_CLASSDEF
+#undef AVLMEL_TEMPDEF
+#undef AVLMEL_TEMPUSE
+#undef AvlTree
+#undef WALKABLE
+
+#endif /* _AAPL_AVLIMELKEY_H */
diff --git a/src/aapl/avliset.h b/src/aapl/avliset.h
new file mode 100644
index 00000000..e309c3ad
--- /dev/null
+++ b/src/aapl/avliset.h
@@ -0,0 +1,76 @@
+/*
+ * Copyright 2002 Adrian Thurston <thurston@colm.net>
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to
+ * deal in the Software without restriction, including without limitation the
+ * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
+ * sell copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+#ifndef _AAPL_AVLISET_H
+#define _AAPL_AVLISET_H
+
+#include "compare.h"
+#include "dlist.h"
+
+/**
+ * \addtogroup avlitree
+ * @{
+ */
+
+/**
+ * \class AvliSet
+ * \brief Linked Key-only oriented tree.
+ *
+ * AvliSet stores only keys in elements that are managed by the tree. AvliSet
+ * requires that a Key type and a class containing a compare() routine
+ * for Key be given. Items are inserted with just a key value.
+ *
+ * AvliSet assumes all elements in the tree are allocated on the heap and are
+ * to be managed by the tree. This means that the class destructor will delete
+ * the contents of the tree. A deep copy will cause existing elements to be
+ * deleted first.
+ *
+ * \include ex_avliset.cpp
+ */
+
+/*@}*/
+
+#define AVLTREE_SET
+#define BASE_EL(name) name
+#define BASEKEY(name) name
+#define BASELIST DList< AvliSetEl<Key> >
+#define AVLMEL_CLASSDEF class Key, class Compare = CmpOrd<Key>
+#define AVLMEL_TEMPDEF class Key, class Compare
+#define AVLMEL_TEMPUSE Key, Compare
+#define AvlTree AvliSet
+#define Element AvliSetEl<Key>
+#define WALKABLE
+
+#include "avlcommon.h"
+
+#undef AVLTREE_SET
+#undef BASE_EL
+#undef BASEKEY
+#undef BASELIST
+#undef AVLMEL_CLASSDEF
+#undef AVLMEL_TEMPDEF
+#undef AVLMEL_TEMPUSE
+#undef AvlTree
+#undef Element
+#undef WALKABLE
+
+#endif /* _AAPL_AVLISET_H */
diff --git a/src/aapl/avlitree.h b/src/aapl/avlitree.h
new file mode 100644
index 00000000..54c8f30f
--- /dev/null
+++ b/src/aapl/avlitree.h
@@ -0,0 +1,79 @@
+/*
+ * Copyright 2002 Adrian Thurston <thurston@colm.net>
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to
+ * deal in the Software without restriction, including without limitation the
+ * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
+ * sell copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+#ifndef _AAPL_AVLITREE_H
+#define _AAPL_AVLITREE_H
+
+#include "compare.h"
+#include "dlistmel.h"
+
+/**
+ * \addtogroup avlitree
+ * @{
+ */
+
+/**
+ * \class AvliTree
+ * \brief Linked AVL tree.
+ *
+ * AvliTree is the standard linked by-structure AVL tree. To use this
+ * structure the user must define an element type and give it the necessary
+ * properties. At the very least it must have a getKey() function that will be
+ * used to compare the relative ordering of elements and tree management data
+ * necessary for the AVL algorithm. An element type can acquire the management
+ * data by inheriting the AvliTreeEl class.
+ *
+ * AvliTree does not presume to manage the allocation of elements in the tree.
+ * The destructor will not delete the items in the tree, instead the elements
+ * must be explicitly de-allocated by the user if necessary and when it is
+ * safe to do so. The empty() routine will traverse the tree and delete all
+ * items.
+ *
+ * Since the tree does not manage the elements, it can contain elements that
+ * are allocated statically or that are part of another data structure.
+ *
+ * \include ex_avlitree.cpp
+ */
+
+/*@}*/
+
+#define BASE_EL(name) name
+#define BASEKEY(name) name
+#define BASELIST DListMel< Element, AvliTreeEl<Element> >
+#define AVLMEL_CLASSDEF class Element, class Key, class Compare = CmpOrd<Key>
+#define AVLMEL_TEMPDEF class Element, class Key, class Compare
+#define AVLMEL_TEMPUSE Element, Key, Compare
+#define AvlTree AvliTree
+#define WALKABLE
+
+#include "avlcommon.h"
+
+#undef BASE_EL
+#undef BASEKEY
+#undef BASELIST
+#undef AVLMEL_CLASSDEF
+#undef AVLMEL_TEMPDEF
+#undef AVLMEL_TEMPUSE
+#undef AvlTree
+#undef WALKABLE
+
+#endif /* _AAPL_AVLITREE_H */
diff --git a/src/aapl/avlkeyless.h b/src/aapl/avlkeyless.h
new file mode 100644
index 00000000..9ba769c2
--- /dev/null
+++ b/src/aapl/avlkeyless.h
@@ -0,0 +1,59 @@
+/*
+ * Copyright 2002, 2003 Adrian Thurston <thurston@colm.net>
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to
+ * deal in the Software without restriction, including without limitation the
+ * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
+ * sell copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+#ifndef _AAPL_AVLKEYLESS_H
+#define _AAPL_AVLKEYLESS_H
+
+#include "compare.h"
+
+/**
+ * \addtogroup avltree
+ * @{
+ */
+
+/**
+ * \class AvlKeyless
+ * \brief AVL tree that has no insert/find/remove functions that take a key.
+ *
+ * AvlKeyless is an implementation of the AVL tree rebalancing functionality
+ * only. It provides the common code for the tiny AVL tree implementations.
+ */
+
+/*@}*/
+
+#define BASE_EL(name) name
+#define AVLMEL_CLASSDEF class Element
+#define AVLMEL_TEMPDEF class Element
+#define AVLMEL_TEMPUSE Element
+#define AvlTree AvlKeyless
+#define AVL_KEYLESS
+
+#include "avlcommon.h"
+
+#undef BASE_EL
+#undef AVLMEL_CLASSDEF
+#undef AVLMEL_TEMPDEF
+#undef AVLMEL_TEMPUSE
+#undef AvlTree
+#undef AVL_KEYLESS
+
+#endif /* _AAPL_AVLKEYLESS_H */
diff --git a/src/aapl/avlmap.h b/src/aapl/avlmap.h
new file mode 100644
index 00000000..9b52c8ba
--- /dev/null
+++ b/src/aapl/avlmap.h
@@ -0,0 +1,75 @@
+/*
+ * Copyright 2002 Adrian Thurston <thurston@colm.net>
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to
+ * deal in the Software without restriction, including without limitation the
+ * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
+ * sell copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+#ifndef _AAPL_AVLMAP_H
+#define _AAPL_AVLMAP_H
+
+#include "compare.h"
+
+/**
+ * \addtogroup avltree
+ * @{
+ */
+
+/**
+ * \class AvlMap
+ * \brief Key and value oriented AVL tree.
+ *
+ * AvlMap stores key and value pairs in elements that managed by the tree. It
+ * is intendend to be similar to map template found in the STL. AvlMap
+ * requires that a Key type, a Value type, and a class containing a compare()
+ * routine for Key be given. Items can be inserted with just a key or with a
+ * key and value pair.
+ *
+ * AvlMap assumes all elements in the tree are allocated on the heap and are
+ * to be managed by the tree. This means that the class destructor will delete
+ * the contents of the tree. A deep copy will cause existing elements to be
+ * deleted first.
+ *
+ * \include ex_avlmap.cpp
+ */
+
+/*@}*/
+
+#define AVLTREE_MAP
+#define BASE_EL(name) name
+#define BASEKEY(name) name
+#define AVLMEL_CLASSDEF class Key, class Value, class Compare = CmpOrd<Key>
+#define AVLMEL_TEMPDEF class Key, class Value, class Compare
+#define AVLMEL_TEMPUSE Key, Value, Compare
+#define AvlTree AvlMap
+#define Element AvlMapEl<Key,Value>
+
+#include "avlcommon.h"
+
+#undef AVLTREE_MAP
+#undef BASE_EL
+#undef BASEKEY
+#undef AVLMEL_CLASSDEF
+#undef AVLMEL_TEMPDEF
+#undef AVLMEL_TEMPUSE
+#undef AvlTree
+#undef Element
+
+
+
+#endif /* _AAPL_AVLMAP_H */
diff --git a/src/aapl/avlmel.h b/src/aapl/avlmel.h
new file mode 100644
index 00000000..fe7671b8
--- /dev/null
+++ b/src/aapl/avlmel.h
@@ -0,0 +1,75 @@
+/*
+ * Copyright 2002 Adrian Thurston <thurston@colm.net>
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to
+ * deal in the Software without restriction, including without limitation the
+ * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
+ * sell copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+#ifndef _AAPL_AVLMEL_H
+#define _AAPL_AVLMEL_H
+
+#include "compare.h"
+
+/**
+ * \addtogroup avltree
+ * @{
+ */
+
+/**
+ * \class AvlMel
+ * \brief AVL tree for elements appearing in multiple trees.
+ *
+ * AvlMel allows for an element to simultaneously be in multiple trees without
+ * the trees interferring with one another. For each tree that the element is
+ * to appear in, there must be a distinct set of AVL Tree management data that
+ * can be unambiguously referenced with some base class name. This name
+ * is passed to the tree as a template parameter and is used in the tree
+ * algorithms.
+ *
+ * The element must use the same key type and value in each tree that it
+ * appears in. If distinct keys are required, the AvlMelKey structure is
+ * available.
+ *
+ * AvlMel does not assume ownership of elements in the tree. The destructor
+ * will not delete the elements. If the user wishes to explicitly deallocate
+ * all the items in the tree the empty() routine is available.
+ *
+ * \include ex_avlmel.cpp
+ */
+
+/*@}*/
+
+#define BASE_EL(name) BaseEl::name
+#define BASEKEY(name) name
+#define AVLMEL_CLASSDEF class Element, class Key, \
+ class BaseEl, class Compare = CmpOrd<Key>
+#define AVLMEL_TEMPDEF class Element, class Key, \
+ class BaseEl, class Compare
+#define AVLMEL_TEMPUSE Element, Key, BaseEl, Compare
+#define AvlTree AvlMel
+
+#include "avlcommon.h"
+
+#undef BASE_EL
+#undef BASEKEY
+#undef AVLMEL_CLASSDEF
+#undef AVLMEL_TEMPDEF
+#undef AVLMEL_TEMPUSE
+#undef AvlTree
+
+#endif /* _AAPL_AVLMEL_H */
diff --git a/src/aapl/avlmelkey.h b/src/aapl/avlmelkey.h
new file mode 100644
index 00000000..cce7126f
--- /dev/null
+++ b/src/aapl/avlmelkey.h
@@ -0,0 +1,72 @@
+/*
+ * Copyright 2002 Adrian Thurston <thurston@colm.net>
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to
+ * deal in the Software without restriction, including without limitation the
+ * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
+ * sell copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+#ifndef _AAPL_AVLMELKEY_H
+#define _AAPL_AVLMELKEY_H
+
+#include "compare.h"
+
+/**
+ * \addtogroup avltree
+ * @{
+ */
+
+/**
+ * \class AvlMelKey
+ * \brief AVL tree for elements appearing in multiple trees with different keys.
+ *
+ * AvlMelKey is similar to AvlMel, except that an additional template
+ * parameter, BaseKey, is provided for resolving ambiguous references to
+ * getKey(). This means that if an element is stored in multiple trees, each
+ * tree can use a different key for ordering the elements in it. Using
+ * AvlMelKey an array of data structures can be indexed with an O(log(n))
+ * search on two or more of the values contained within it and without
+ * allocating any additional data.
+ *
+ * AvlMelKey does not assume ownership of elements in the tree. The destructor
+ * will not delete the elements. If the user wishes to explicitly deallocate
+ * all the items in the tree the empty() routine is available.
+ *
+ * \include ex_avlmelkey.cpp
+ */
+
+/*@}*/
+
+#define BASE_EL(name) BaseEl::name
+#define BASEKEY(name) BaseKey::name
+#define AVLMEL_CLASSDEF class Element, class Key, class BaseEl, \
+ class BaseKey, class Compare = CmpOrd<Key>
+#define AVLMEL_TEMPDEF class Element, class Key, class BaseEl, \
+ class BaseKey, class Compare
+#define AVLMEL_TEMPUSE Element, Key, BaseEl, BaseKey, Compare
+#define AvlTree AvlMelKey
+
+#include "avlcommon.h"
+
+#undef BASE_EL
+#undef BASEKEY
+#undef AVLMEL_CLASSDEF
+#undef AVLMEL_TEMPDEF
+#undef AVLMEL_TEMPUSE
+#undef AvlTree
+
+#endif /* _AAPL_AVLMELKEY_H */
diff --git a/src/aapl/avlset.h b/src/aapl/avlset.h
new file mode 100644
index 00000000..97e5c484
--- /dev/null
+++ b/src/aapl/avlset.h
@@ -0,0 +1,71 @@
+/*
+ * Copyright 2002 Adrian Thurston <thurston@colm.net>
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to
+ * deal in the Software without restriction, including without limitation the
+ * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
+ * sell copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+#ifndef _AAPL_AVLSET_H
+#define _AAPL_AVLSET_H
+
+#include "compare.h"
+
+/**
+ * \addtogroup avltree
+ * @{
+ */
+
+/**
+ * \class AvlSet
+ * \brief Key-only oriented tree.
+ *
+ * AvlSet stores only keys in elements that are managed by the tree. AvlSet
+ * requires that a Key type and a class containing a compare() routine
+ * for Key be given. Items are inserted with just a key value.
+ *
+ * AvlSet assumes all elements in the tree are allocated on the heap and are
+ * to be managed by the tree. This means that the class destructor will delete
+ * the contents of the tree. A deep copy will cause existing elements to be
+ * deleted first.
+ *
+ * \include ex_avlset.cpp
+ */
+
+/*@}*/
+
+#define AVLTREE_SET
+#define BASE_EL(name) name
+#define BASEKEY(name) name
+#define AVLMEL_CLASSDEF class Key, class Compare = CmpOrd<Key>
+#define AVLMEL_TEMPDEF class Key, class Compare
+#define AVLMEL_TEMPUSE Key, Compare
+#define AvlTree AvlSet
+#define Element AvlSetEl<Key>
+
+#include "avlcommon.h"
+
+#undef AVLTREE_SET
+#undef BASE_EL
+#undef BASEKEY
+#undef AVLMEL_CLASSDEF
+#undef AVLMEL_TEMPDEF
+#undef AVLMEL_TEMPUSE
+#undef AvlTree
+#undef Element
+
+#endif /* _AAPL_AVLSET_H */
diff --git a/src/aapl/avltree.h b/src/aapl/avltree.h
new file mode 100644
index 00000000..9237810e
--- /dev/null
+++ b/src/aapl/avltree.h
@@ -0,0 +1,74 @@
+/*
+ * Copyright 2002 Adrian Thurston <thurston@colm.net>
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to
+ * deal in the Software without restriction, including without limitation the
+ * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
+ * sell copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+#ifndef _AAPL_AVLTREE_H
+#define _AAPL_AVLTREE_H
+
+#include "compare.h"
+
+/**
+ * \addtogroup avltree
+ * @{
+ */
+
+/**
+ * \class AvlTree
+ * \brief Basic AVL tree.
+ *
+ * AvlTree is the standard by-structure AVL tree. To use this structure the
+ * user must define an element type and give it the necessary properties. At
+ * the very least it must have a getKey() function that will be used to
+ * compare the relative ordering of elements and tree management data
+ * necessary for the AVL algorithm. An element type can acquire the management
+ * data by inheriting the AvlTreeEl class.
+ *
+ * AvlTree does not presume to manage the allocation of elements in the tree.
+ * The destructor will not delete the items in the tree, instead the elements
+ * must be explicitly de-allocated by the user if necessary and when it is
+ * safe to do so. The empty() routine will traverse the tree and delete all
+ * items.
+ *
+ * Since the tree does not manage the elements, it can contain elements that
+ * are allocated statically or that are part of another data structure.
+ *
+ * \include ex_avltree.cpp
+ */
+
+/*@}*/
+
+#define BASE_EL(name) name
+#define BASEKEY(name) name
+#define AVLMEL_CLASSDEF class Element, class Key, class Compare = CmpOrd<Key>
+#define AVLMEL_TEMPDEF class Element, class Key, class Compare
+#define AVLMEL_TEMPUSE Element, Key, Compare
+#define AvlTree AvlTree
+
+#include "avlcommon.h"
+
+#undef BASE_EL
+#undef BASEKEY
+#undef AVLMEL_CLASSDEF
+#undef AVLMEL_TEMPDEF
+#undef AVLMEL_TEMPUSE
+#undef AvlTree
+
+#endif /* _AAPL_AVLTREE_H */
diff --git a/src/aapl/bstcommon.h b/src/aapl/bstcommon.h
new file mode 100644
index 00000000..391b4ff1
--- /dev/null
+++ b/src/aapl/bstcommon.h
@@ -0,0 +1,815 @@
+/*
+ * Copyright 2001 Adrian Thurston <thurston@colm.net>
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to
+ * deal in the Software without restriction, including without limitation the
+ * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
+ * sell copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+/* This header is not wrapped in ifndefs because it is
+ * not intended to be included by users directly. */
+
+#ifdef AAPL_NAMESPACE
+namespace Aapl {
+#endif
+
+/* Binary Search Table */
+template < BST_TEMPL_DECLARE > class BstTable :
+ public Compare,
+ public Vector< Element, Resize >
+{
+ typedef Vector<Element, Resize> BaseVector;
+ typedef Table<Element> BaseTable;
+
+public:
+ /**
+ * \brief Default constructor.
+ *
+ * Create an empty binary search table.
+ */
+ BstTable() { }
+
+ /**
+ * \brief Construct with initial value.
+ *
+ * Constructs a binary search table with an initial item. Uses the default
+ * constructor for initializing Value.
+ */
+ BstTable(const Key &key)
+ { insert(key); }
+
+#if defined( BSTMAP )
+ /**
+ * \brief Construct with initial value.
+ *
+ * Constructs a binary search table with an initial key/value pair.
+ */
+ BstTable(const Key &key, const Value &val)
+ { insert(key, val); }
+#endif
+
+#if ! defined( BSTSET )
+ /**
+ * \brief Construct with initial value.
+ *
+ * Constructs a binary search table with an initial Element.
+ */
+ BstTable(const Element &el)
+ { insert(el); }
+#endif
+
+ Element *insert(const Key &key, Element **lastFound = 0);
+ Element *insertMulti(const Key &key);
+
+ bool insert(const BstTable &other);
+ void insertMulti(const BstTable &other);
+
+#if defined( BSTMAP )
+ Element *insert(const Key &key, const Value &val,
+ Element **lastFound = 0);
+ Element *insertMulti(const Key &key, const Value &val );
+#endif
+
+#if ! defined( BSTSET )
+ Element *insert(const Element &el, Element **lastFound = 0);
+ Element *insertMulti(const Element &el);
+#endif
+
+ Element *find(const Key &key, Element **lastFound = 0) const;
+ bool findMulti( const Key &key, Element *&lower,
+ Element *&upper ) const;
+
+ bool remove(const Key &key);
+ bool remove(Element *item);
+ long removeMulti(const Key &key);
+ long removeMulti(Element *lower, Element *upper);
+
+ /* The following provide access to the underlying insert and remove
+ * functions that my be hidden by the BST insert and remove. The insertDup
+ * and insertNew functions will never be hidden. They are provided for
+ * consistency. The difference between the non-shared and the shared
+ * tables is the documentation reference to the invoked function. */
+
+#if !defined( SHARED_BST )
+ /*@{*/
+
+ /** \brief Call the insert of the underlying vector.
+ *
+ * Provides to access to the vector insert, which may become hidden. Care
+ * should be taken to ensure that after the insert the ordering of
+ * elements is preserved.
+ * Invokes Vector::insert( long pos, const T &val ).
+ */
+ void vinsert(long pos, const Element &val)
+ { Vector< Element, Resize >::insert( pos, &val, 1 ); }
+
+ /** \brief Call the insert of the underlying vector.
+ *
+ * Provides to access to the vector insert, which may become hidden. Care
+ * should be taken to ensure that after the insert the ordering of
+ * elements is preserved.
+ * Invokes Vector::insert( long pos, const T *val, long len ).
+ */
+ void vinsert(long pos, const Element *val, long len)
+ { Vector< Element, Resize >::insert( pos, val, len ); }
+
+ /** \brief Call the insert of the underlying vector.
+ *
+ * Provides to access to the vector insert, which may become hidden. Care
+ * should be taken to ensure that after the insert the ordering of
+ * elements is preserved.
+ * Invokes Vector::insert( long pos, const Vector &v ).
+ */
+ void vinsert(long pos, const BstTable &v)
+ { Vector< Element, Resize >::insert( pos, v.data, v.tabLen ); }
+
+ /*@}*/
+
+ /*@{*/
+
+ /** \brief Call the remove of the underlying vector.
+ *
+ * Provides access to the vector remove, which may become hidden.
+ * Invokes Vector::remove( long pos ).
+ */
+ void vremove(long pos)
+ { Vector< Element, Resize >::remove( pos, 1 ); }
+
+ /** \brief Call the remove of the underlying vector.
+ *
+ * Proves access to the vector remove, which may become hidden.
+ * Invokes Vector::remove( long pos, long len ).
+ */
+ void vremove(long pos, long len)
+ { Vector< Element, Resize >::remove( pos, len ); }
+
+ /*@}*/
+#else /* SHARED_BST */
+ /*@{*/
+
+ /** \brief Call the insert of the underlying vector.
+ *
+ * Provides to access to the vector insert, which may become hidden. Care
+ * should be taken to ensure that after the insert the ordering of
+ * elements is preserved.
+ * Invokes SVector::insert( long pos, const T &val ).
+ */
+ void vinsert(long pos, const Element &val)
+ { Vector< Element, Resize >::insert( pos, &val, 1 ); }
+
+ /** \brief Call the insert of the underlying vector.
+ *
+ * Provides to access to the vector insert, which may become hidden. Care
+ * should be taken to ensure that after the insert the ordering of
+ * elements is preserved.
+ * Invokes SVector::insert( long pos, const T *val, long len ).
+ */
+ void vinsert(long pos, const Element *val, long len)
+ { Vector< Element, Resize >::insert( pos, val, len ); }
+
+ /** \brief Call the insert of the underlying vector.
+ *
+ * Provides to access to the vector insert, which may become hidden. Care
+ * should be taken to ensure that after the insert the ordering of
+ * elements is preserved.
+ * Invokes SVector::insert( long pos, const SVector &v ).
+ */
+ void vinsert(long pos, const BstTable &v)
+ { Vector< Element, Resize >::insert( pos, v.data, v.length() ); }
+
+ /*@}*/
+
+ /*@{*/
+
+ /** \brief Call the remove of the underlying vector.
+ *
+ * Provides access to the vector remove, which may become hidden.
+ * Invokes SVector::remove( long pos ).
+ */
+ void vremove(long pos)
+ { Vector< Element, Resize >::remove( pos, 1 ); }
+
+ /** \brief Call the remove of the underlying vector.
+ *
+ * Proves access to the vector remove, which may become hidden.
+ * Invokes SVector::remove( long pos, long len ).
+ */
+ void vremove(long pos, long len)
+ { Vector< Element, Resize >::remove( pos, len ); }
+
+ /*@}*/
+
+#endif /* SHARED_BST */
+};
+
+
+#if 0
+#if defined( SHARED_BST )
+/**
+ * \brief Construct a binary search table with an initial amount of
+ * allocation.
+ *
+ * The table is initialized to have room for allocLength elements. The
+ * table starts empty.
+ */
+template <BST_TEMPL_DEF> BstTable<BST_TEMPL_USE>::
+ BstTable( long allocLen )
+{
+ /* Allocate the space if we are given a positive allocLen. */
+ if ( allocLen > 0 ) {
+ /* Allocate the data needed. */
+ STabHead *head = (STabHead*)
+ malloc( sizeof(STabHead) + sizeof(Element) * allocLen );
+ if ( head == 0 )
+ throw std::bad_alloc();
+
+ /* Set up the header and save the data pointer. */
+ head->refCount = 1;
+ head->allocLen = allocLen;
+ head->tabLen = 0;
+ BaseTable::data = (Element*) (head + 1);
+ }
+}
+#else
+/**
+ * \brief Construct a binary search table with an initial amount of
+ * allocation.
+ *
+ * The table is initialized to have room for allocLength elements. The
+ * table starts empty.
+ */
+template <BST_TEMPL_DEF> BstTable<BST_TEMPL_USE>::
+ BstTable( long allocLen )
+{
+ /* Allocate the space if we are given a positive allocLen. */
+ BaseTable::allocLen = allocLen;
+ if ( BaseTable::allocLen > 0 ) {
+ BaseTable::data = (Element*) malloc(sizeof(Element) * BaseTable::allocLen);
+ if ( BaseTable::data == NULL )
+ throw std::bad_alloc();
+ }
+}
+
+#endif
+#endif
+
+/**
+ * \brief Find the element with the given key and remove it.
+ *
+ * If multiple elements with the given key exist, then it is unspecified which
+ * element will be removed.
+ *
+ * \returns True if an element is found and consequently removed, false
+ * otherwise.
+ */
+template <BST_TEMPL_DEF> bool BstTable<BST_TEMPL_USE>::
+ remove(const Key &key)
+{
+ Element *el = find(key);
+ if ( el != 0 ) {
+ Vector< Element >::remove(el - BaseTable::data);
+ return true;
+ }
+ return false;
+}
+
+/**
+ * \brief Remove the element pointed to by item.
+ *
+ * If item does not point to an element in the tree, then undefined behaviour
+ * results. If item is null, then remove has no effect.
+ *
+ * \returns True if item is not null, false otherwise.
+ */
+template <BST_TEMPL_DEF> bool BstTable<BST_TEMPL_USE>::
+ remove( Element *item )
+{
+ if ( item != 0 ) {
+ Vector< Element >::remove(item - BaseTable::data);
+ return true;
+ }
+ return false;
+}
+
+/**
+ * \brief Find and remove the entire range of elements with the given key.
+ *
+ * \returns The number of elements removed.
+ */
+template <BST_TEMPL_DEF> long BstTable<BST_TEMPL_USE>::
+ removeMulti(const Key &key)
+{
+ Element *low, *high;
+ if ( findMulti(key, low, high) ) {
+ /* Get the length of the range. */
+ long num = high - low + 1;
+ Vector< Element >::remove(low - BaseTable::data, num);
+ return num;
+ }
+
+ return 0;
+}
+
+template <BST_TEMPL_DEF> long BstTable<BST_TEMPL_USE>::
+ removeMulti(Element *lower, Element *upper)
+{
+ /* Get the length of the range. */
+ long num = upper - lower + 1;
+ Vector< Element >::remove(lower - BaseTable::data, num);
+ return num;
+}
+
+
+/**
+ * \brief Find a range of elements with the given key.
+ *
+ * If any elements with the given key exist then lower and upper are set to
+ * the low and high ends of the continous range of elements with the key.
+ * Lower and upper will point to the first and last elements with the key.
+ *
+ * \returns True if any elements are found, false otherwise.
+ */
+template <BST_TEMPL_DEF> bool BstTable<BST_TEMPL_USE>::
+ findMulti(const Key &key, Element *&low, Element *&high ) const
+{
+ const Element *lower, *mid, *upper;
+ long keyRelation;
+ const long tblLen = BaseTable::length();
+
+ if ( BaseTable::data == 0 )
+ return false;
+
+ lower = BaseTable::data;
+ upper = BaseTable::data + tblLen - 1;
+ while ( true ) {
+ if ( upper < lower ) {
+ /* Did not find the fd in the array. */
+ return false;
+ }
+
+ mid = lower + ((upper-lower)>>1);
+ keyRelation = this->compare(key, GET_KEY(*mid));
+
+ if ( keyRelation < 0 )
+ upper = mid - 1;
+ else if ( keyRelation > 0 )
+ lower = mid + 1;
+ else {
+ Element *lowEnd = BaseTable::data - 1;
+ Element *highEnd = BaseTable::data + tblLen;
+
+ lower = mid - 1;
+ while ( lower != lowEnd &&
+ this->compare(key, GET_KEY(*lower)) == 0 )
+ lower--;
+
+ upper = mid + 1;
+ while ( upper != highEnd &&
+ this->compare(key, GET_KEY(*upper)) == 0 )
+ upper++;
+
+ low = (Element*)lower + 1;
+ high = (Element*)upper - 1;
+ return true;
+ }
+ }
+}
+
+/**
+ * \brief Find an element with the given key.
+ *
+ * If the find succeeds then lastFound is set to the element found. If the
+ * find fails then lastFound is set the location where the key would be
+ * inserted. If there is more than one element in the tree with the given key,
+ * then it is unspecified which element is returned as the match.
+ *
+ * \returns The element found on success, null on failure.
+ */
+template <BST_TEMPL_DEF> Element *BstTable<BST_TEMPL_USE>::
+ find( const Key &key, Element **lastFound ) const
+{
+ const Element *lower, *mid, *upper;
+ long keyRelation;
+ const long tblLen = BaseTable::length();
+
+ if ( BaseTable::data == 0 )
+ return 0;
+
+ lower = BaseTable::data;
+ upper = BaseTable::data + tblLen - 1;
+ while ( true ) {
+ if ( upper < lower ) {
+ /* Did not find the key. Last found gets the insert location. */
+ if ( lastFound != 0 )
+ *lastFound = (Element*)lower;
+ return 0;
+ }
+
+ mid = lower + ((upper-lower)>>1);
+ keyRelation = this->compare(key, GET_KEY(*mid));
+
+ if ( keyRelation < 0 )
+ upper = mid - 1;
+ else if ( keyRelation > 0 )
+ lower = mid + 1;
+ else {
+ /* Key is found. Last found gets the found record. */
+ if ( lastFound != 0 )
+ *lastFound = (Element*)mid;
+ return (Element*)mid;
+ }
+ }
+}
+
+template <BST_TEMPL_DEF> Element *BstTable<BST_TEMPL_USE>::
+ insert(const Key &key, Element **lastFound)
+{
+ const Element *lower, *mid, *upper;
+ long keyRelation, insertPos;
+ const long tblLen = BaseTable::length();
+
+ if ( tblLen == 0 ) {
+ /* If the table is empty then go straight to insert. */
+ lower = BaseTable::data;
+ goto insert;
+ }
+
+ lower = BaseTable::data;
+ upper = BaseTable::data + tblLen - 1;
+ while ( true ) {
+ if ( upper < lower ) {
+ /* Did not find the key in the array.
+ * Place to insert at is lower. */
+ goto insert;
+ }
+
+ mid = lower + ((upper-lower)>>1);
+ keyRelation = this->compare(key, GET_KEY(*mid));
+
+ if ( keyRelation < 0 )
+ upper = mid - 1;
+ else if ( keyRelation > 0 )
+ lower = mid + 1;
+ else {
+ if ( lastFound != 0 )
+ *lastFound = (Element*)mid;
+ return 0;
+ }
+ }
+
+insert:
+ /* Get the insert pos. */
+ insertPos = lower - BaseTable::data;
+
+ /* Do the insert. After makeRawSpaceFor, lower pointer is no good. */
+ BaseVector::makeRawSpaceFor(insertPos, 1);
+ new(BaseTable::data + insertPos) Element(key);
+
+ /* Set lastFound */
+ if ( lastFound != 0 )
+ *lastFound = BaseTable::data + insertPos;
+ return BaseTable::data + insertPos;
+}
+
+
+template <BST_TEMPL_DEF> Element *BstTable<BST_TEMPL_USE>::
+ insertMulti(const Key &key)
+{
+ const Element *lower, *mid, *upper;
+ long keyRelation, insertPos;
+ const long tblLen = BaseTable::length();
+
+ if ( tblLen == 0 ) {
+ /* If the table is empty then go straight to insert. */
+ lower = BaseTable::data;
+ goto insert;
+ }
+
+ lower = BaseTable::data;
+ upper = BaseTable::data + tblLen - 1;
+ while ( true ) {
+ if ( upper < lower ) {
+ /* Did not find the key in the array.
+ * Place to insert at is lower. */
+ goto insert;
+ }
+
+ mid = lower + ((upper-lower)>>1);
+ keyRelation = this->compare(key, GET_KEY(*mid));
+
+ if ( keyRelation < 0 )
+ upper = mid - 1;
+ else if ( keyRelation > 0 )
+ lower = mid + 1;
+ else {
+ lower = mid;
+ goto insert;
+ }
+ }
+
+insert:
+ /* Get the insert pos. */
+ insertPos = lower - BaseTable::data;
+
+ /* Do the insert. */
+ BaseVector::makeRawSpaceFor(insertPos, 1);
+ new(BaseTable::data + insertPos) Element(key);
+
+ /* Return the element inserted. */
+ return BaseTable::data + insertPos;
+}
+
+/**
+ * \brief Insert each element from other.
+ *
+ * Always attempts to insert all elements even if the insert of some item from
+ * other fails.
+ *
+ * \returns True if all items inserted successfully, false if any insert
+ * failed.
+ */
+template <BST_TEMPL_DEF> bool BstTable<BST_TEMPL_USE>::
+ insert(const BstTable &other)
+{
+ bool allSuccess = true;
+ long otherLen = other.length();
+ for ( long i = 0; i < otherLen; i++ ) {
+ Element *el = insert( other.data[i] );
+ if ( el == 0 )
+ allSuccess = false;
+ }
+ return allSuccess;
+}
+
+/**
+ * \brief Insert each element from other even if the elements exist already.
+ *
+ * No individual insertMulti can fail.
+ */
+template <BST_TEMPL_DEF> void BstTable<BST_TEMPL_USE>::
+ insertMulti(const BstTable &other)
+{
+ long otherLen = other.length();
+ for ( long i = 0; i < otherLen; i++ )
+ insertMulti( other.data[i] );
+}
+
+#if ! defined( BSTSET )
+
+/**
+ * \brief Insert the given element.
+ *
+ * If the key in the given element does not already exist in the table then a
+ * new element is inserted. They element copy constructor is used to place the
+ * element into the table. If lastFound is given, it is set to the new element
+ * created. If the insert fails then lastFound is set to the existing element
+ * of the same key.
+ *
+ * \returns The new element created upon success, null upon failure.
+ */
+template <BST_TEMPL_DEF> Element *BstTable<BST_TEMPL_USE>::
+ insert(const Element &el, Element **lastFound )
+{
+ const Element *lower, *mid, *upper;
+ long keyRelation, insertPos;
+ const long tblLen = BaseTable::length();
+
+ if ( tblLen == 0 ) {
+ /* If the table is empty then go straight to insert. */
+ lower = BaseTable::data;
+ goto insert;
+ }
+
+ lower = BaseTable::data;
+ upper = BaseTable::data + tblLen - 1;
+ while ( true ) {
+ if ( upper < lower ) {
+ /* Did not find the key in the array.
+ * Place to insert at is lower. */
+ goto insert;
+ }
+
+ mid = lower + ((upper-lower)>>1);
+ keyRelation = this->compare(GET_KEY(el), GET_KEY(*mid));
+
+ if ( keyRelation < 0 )
+ upper = mid - 1;
+ else if ( keyRelation > 0 )
+ lower = mid + 1;
+ else {
+ if ( lastFound != 0 )
+ *lastFound = (Element*)mid;
+ return 0;
+ }
+ }
+
+insert:
+ /* Get the insert pos. */
+ insertPos = lower - BaseTable::data;
+
+ /* Do the insert. After makeRawSpaceFor, lower pointer is no good. */
+ BaseVector::makeRawSpaceFor(insertPos, 1);
+ new(BaseTable::data + insertPos) Element(el);
+
+ /* Set lastFound */
+ if ( lastFound != 0 )
+ *lastFound = BaseTable::data + insertPos;
+ return BaseTable::data + insertPos;
+}
+
+/**
+ * \brief Insert the given element even if it exists already.
+ *
+ * If the key in the given element exists already then the new element is
+ * placed next to some other element of the same key. InsertMulti cannot fail.
+ * The element copy constructor is used to place the element in the table.
+ *
+ * \returns The new element created.
+ */
+template <BST_TEMPL_DEF> Element *BstTable<BST_TEMPL_USE>::
+ insertMulti(const Element &el)
+{
+ const Element *lower, *mid, *upper;
+ long keyRelation, insertPos;
+ const long tblLen = BaseTable::length();
+
+ if ( tblLen == 0 ) {
+ /* If the table is empty then go straight to insert. */
+ lower = BaseTable::data;
+ goto insert;
+ }
+
+ lower = BaseTable::data;
+ upper = BaseTable::data + tblLen - 1;
+ while ( true ) {
+ if ( upper < lower ) {
+ /* Did not find the fd in the array.
+ * Place to insert at is lower. */
+ goto insert;
+ }
+
+ mid = lower + ((upper-lower)>>1);
+ keyRelation = this->compare(GET_KEY(el), GET_KEY(*mid));
+
+ if ( keyRelation < 0 )
+ upper = mid - 1;
+ else if ( keyRelation > 0 )
+ lower = mid + 1;
+ else {
+ lower = mid;
+ goto insert;
+ }
+ }
+
+insert:
+ /* Get the insert pos. */
+ insertPos = lower - BaseTable::data;
+
+ /* Do the insert. */
+ BaseVector::makeRawSpaceFor(insertPos, 1);
+ new(BaseTable::data + insertPos) Element(el);
+
+ /* Return the element inserted. */
+ return BaseTable::data + insertPos;
+}
+#endif
+
+
+#if defined( BSTMAP )
+
+/**
+ * \brief Insert the given key-value pair.
+ *
+ * If the given key does not already exist in the table then the key-value
+ * pair is inserted. Copy constructors are used to place the pair in the
+ * table. If lastFound is given, it is set to the new entry created. If the
+ * insert fails then lastFound is set to the existing pair of the same key.
+ *
+ * \returns The new element created upon success, null upon failure.
+ */
+template <BST_TEMPL_DEF> Element *BstTable<BST_TEMPL_USE>::
+ insert(const Key &key, const Value &val, Element **lastFound)
+{
+ const Element *lower, *mid, *upper;
+ long keyRelation, insertPos;
+ const long tblLen = BaseTable::length();
+
+ if ( tblLen == 0 ) {
+ /* If the table is empty then go straight to insert. */
+ lower = BaseTable::data;
+ goto insert;
+ }
+
+ lower = BaseTable::data;
+ upper = BaseTable::data + tblLen - 1;
+ while ( true ) {
+ if ( upper < lower ) {
+ /* Did not find the fd in the array.
+ * Place to insert at is lower. */
+ goto insert;
+ }
+
+ mid = lower + ((upper-lower)>>1);
+ keyRelation = Compare::compare(key, mid->key);
+
+ if ( keyRelation < 0 )
+ upper = mid - 1;
+ else if ( keyRelation > 0 )
+ lower = mid + 1;
+ else {
+ if ( lastFound != NULL )
+ *lastFound = (Element*)mid;
+ return 0;
+ }
+ }
+
+insert:
+ /* Get the insert pos. */
+ insertPos = lower - BaseTable::data;
+
+ /* Do the insert. */
+ BaseVector::makeRawSpaceFor(insertPos, 1);
+ new(BaseTable::data + insertPos) Element(key, val);
+
+ /* Set lastFound */
+ if ( lastFound != NULL )
+ *lastFound = BaseTable::data + insertPos;
+ return BaseTable::data + insertPos;
+}
+
+
+/**
+ * \brief Insert the given key-value pair even if the key exists already.
+ *
+ * If the key exists already then the key-value pair is placed next to some
+ * other pair of the same key. InsertMulti cannot fail. Copy constructors are
+ * used to place the pair in the table.
+ *
+ * \returns The new element created.
+ */
+template <BST_TEMPL_DEF> Element *BstTable<BST_TEMPL_USE>::
+ insertMulti(const Key &key, const Value &val)
+{
+ const Element *lower, *mid, *upper;
+ long keyRelation, insertPos;
+ const long tblLen = BaseTable::length();
+
+ if ( tblLen == 0 ) {
+ /* If the table is empty then go straight to insert. */
+ lower = BaseTable::data;
+ goto insert;
+ }
+
+ lower = BaseTable::data;
+ upper = BaseTable::data + tblLen - 1;
+ while ( true ) {
+ if ( upper < lower ) {
+ /* Did not find the key in the array.
+ * Place to insert at is lower. */
+ goto insert;
+ }
+
+ mid = lower + ((upper-lower)>>1);
+ keyRelation = Compare::compare(key, mid->key);
+
+ if ( keyRelation < 0 )
+ upper = mid - 1;
+ else if ( keyRelation > 0 )
+ lower = mid + 1;
+ else {
+ lower = mid;
+ goto insert;
+ }
+ }
+
+insert:
+ /* Get the insert pos. */
+ insertPos = lower - BaseTable::data;
+
+ /* Do the insert. */
+ BaseVector::makeRawSpaceFor(insertPos, 1);
+ new(BaseTable::data + insertPos) Element(key, val);
+
+ /* Return the element inserted. */
+ return BaseTable::data + insertPos;
+}
+
+#endif
+
+#ifdef AAPL_NAMESPACE
+}
+#endif
diff --git a/src/aapl/bstmap.h b/src/aapl/bstmap.h
new file mode 100644
index 00000000..4a5f5310
--- /dev/null
+++ b/src/aapl/bstmap.h
@@ -0,0 +1,114 @@
+/*
+ * Copyright 2002 Adrian Thurston <thurston@colm.net>
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to
+ * deal in the Software without restriction, including without limitation the
+ * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
+ * sell copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+#ifndef _AAPL_BSTMAP_H
+#define _AAPL_BSTMAP_H
+
+#include "compare.h"
+#include "vector.h"
+
+#ifdef AAPL_NAMESPACE
+namespace Aapl {
+#endif
+
+/**
+ * \brief Element for BstMap.
+ *
+ * Stores the key and value pair.
+ */
+template <class Key, class Value> struct BstMapEl
+{
+ BstMapEl() {}
+ BstMapEl(const Key &key) : key(key) {}
+ BstMapEl(const Key &key, const Value &val) : key(key), value(val) {}
+
+ /** \brief The key */
+ Key key;
+
+ /** \brief The value. */
+ Value value;
+};
+
+#ifdef AAPL_NAMESPACE
+}
+#endif
+
+/**
+ * \addtogroup bst
+ * @{
+ */
+
+/**
+ * \class BstMap
+ * \brief Binary search table for key and value pairs.
+ *
+ * BstMap stores key and value pairs in each element. The key and value can be
+ * any type. A compare class for the key must be supplied.
+ */
+
+/*@}*/
+
+#define BST_TEMPL_DECLARE class Key, class Value, \
+ class Compare = CmpOrd<Key>, class Resize = ResizeExpn
+#define BST_TEMPL_DEF class Key, class Value, class Compare, class Resize
+#define BST_TEMPL_USE Key, Value, Compare, Resize
+#define GET_KEY(el) ((el).key)
+#define BstTable BstMap
+#define Element BstMapEl<Key, Value>
+#define BSTMAP
+
+#include "bstcommon.h"
+
+#undef BST_TEMPL_DECLARE
+#undef BST_TEMPL_DEF
+#undef BST_TEMPL_USE
+#undef GET_KEY
+#undef BstTable
+#undef Element
+#undef BSTMAP
+
+/**
+ * \fn BstMap::insert(const Key &key, BstMapEl<Key, Value> **lastFound)
+ * \brief Insert the given key.
+ *
+ * If the given key does not already exist in the table then a new element
+ * having key is inserted. They key copy constructor and value default
+ * constructor are used to place the pair in the table. If lastFound is given,
+ * it is set to the new entry created. If the insert fails then lastFound is
+ * set to the existing pair of the same key.
+ *
+ * \returns The new element created upon success, null upon failure.
+ */
+
+/**
+ * \fn BstMap::insertMulti(const Key &key)
+ * \brief Insert the given key even if it exists already.
+ *
+ * If the key exists already then the new element having key is placed next
+ * to some other pair of the same key. InsertMulti cannot fail. The key copy
+ * constructor and the value default constructor are used to place the pair in
+ * the table.
+ *
+ * \returns The new element created.
+ */
+
+#endif /* _AAPL_BSTMAP_H */
diff --git a/src/aapl/bstset.h b/src/aapl/bstset.h
new file mode 100644
index 00000000..14e0375a
--- /dev/null
+++ b/src/aapl/bstset.h
@@ -0,0 +1,87 @@
+/*
+ * Copyright 2002 Adrian Thurston <thurston@colm.net>
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to
+ * deal in the Software without restriction, including without limitation the
+ * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
+ * sell copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+#ifndef _AAPL_BSTSET_H
+#define _AAPL_BSTSET_H
+
+/**
+ * \addtogroup bst
+ * @{
+ */
+
+/**
+ * \class BstSet
+ * \brief Binary search table for types that are the key.
+ *
+ * BstSet is suitable for types that comprise the entire key. Rather than look
+ * into the element to retrieve the key, the element is the key. A class that
+ * contains a comparison routine for the key must be given.
+ */
+
+/*@}*/
+
+#include "compare.h"
+#include "vector.h"
+
+#define BST_TEMPL_DECLARE class Key, class Compare = CmpOrd<Key>, \
+ class Resize = ResizeExpn
+#define BST_TEMPL_DEF class Key, class Compare, class Resize
+#define BST_TEMPL_USE Key, Compare, Resize
+#define GET_KEY(el) (el)
+#define BstTable BstSet
+#define Element Key
+#define BSTSET
+
+#include "bstcommon.h"
+
+#undef BST_TEMPL_DECLARE
+#undef BST_TEMPL_DEF
+#undef BST_TEMPL_USE
+#undef GET_KEY
+#undef BstTable
+#undef Element
+#undef BSTSET
+
+/**
+ * \fn BstSet::insert(const Key &key, Key **lastFound)
+ * \brief Insert the given key.
+ *
+ * If the given key does not already exist in the table then it is inserted.
+ * The key's copy constructor is used to place the item in the table. If
+ * lastFound is given, it is set to the new entry created. If the insert fails
+ * then lastFound is set to the existing key of the same value.
+ *
+ * \returns The new element created upon success, null upon failure.
+ */
+
+/**
+ * \fn BstSet::insertMulti(const Key &key)
+ * \brief Insert the given key even if it exists already.
+ *
+ * If the key exists already then it is placed next to some other key of the
+ * same value. InsertMulti cannot fail. The key's copy constructor is used to
+ * place the item in the table.
+ *
+ * \returns The new element created.
+ */
+
+#endif /* _AAPL_BSTSET_H */
diff --git a/src/aapl/bsttable.h b/src/aapl/bsttable.h
new file mode 100644
index 00000000..cb9a056a
--- /dev/null
+++ b/src/aapl/bsttable.h
@@ -0,0 +1,85 @@
+/*
+ * Copyright 2002 Adrian Thurston <thurston@colm.net>
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to
+ * deal in the Software without restriction, including without limitation the
+ * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
+ * sell copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+#ifndef _AAPL_BSTTABLE_H
+#define _AAPL_BSTTABLE_H
+
+#include "compare.h"
+#include "vector.h"
+
+/**
+ * \addtogroup bst
+ * @{
+ */
+
+/**
+ * \class BstTable
+ * \brief Binary search table for structures that contain a key.
+ *
+ * This is the basic binary search table. It can be used to contain a
+ * structure that has a key and possibly some data. The key should be a member
+ * of the element class and accessible with getKey(). A class containing the
+ * compare routine must be supplied.
+ */
+
+/*@}*/
+
+#define BST_TEMPL_DECLARE class Element, class Key, \
+ class Compare = CmpOrd<Key>, class Resize = ResizeExpn
+#define BST_TEMPL_DEF class Element, class Key, class Compare, class Resize
+#define BST_TEMPL_USE Element, Key, Compare, Resize
+#define GET_KEY(el) ((el).getKey())
+#define BSTTABLE
+
+#include "bstcommon.h"
+
+#undef BST_TEMPL_DECLARE
+#undef BST_TEMPL_DEF
+#undef BST_TEMPL_USE
+#undef GET_KEY
+#undef BSTTABLE
+
+/**
+ * \fn BstTable::insert(const Key &key, Element **lastFound)
+ * \brief Insert a new element with the given key.
+ *
+ * If the given key does not already exist in the table a new element is
+ * inserted with the given key. A constructor taking only const Key& is used
+ * to initialize the new element. If lastFound is given, it is set to the new
+ * element created. If the insert fails then lastFound is set to the existing
+ * element with the same key.
+ *
+ * \returns The new element created upon success, null upon failure.
+ */
+
+/**
+ * \fn BstTable::insertMulti(const Key &key)
+ * \brief Insert a new element even if the key exists already.
+ *
+ * If the key exists already then the new element is placed next to some
+ * element with the same key. InsertMulti cannot fail. A constructor taking
+ * only const Key& is used to initialize the new element.
+ *
+ * \returns The new element created.
+ */
+
+#endif /* _AAPL_BSTTABLE_H */
diff --git a/src/aapl/bubblesort.h b/src/aapl/bubblesort.h
new file mode 100644
index 00000000..42482991
--- /dev/null
+++ b/src/aapl/bubblesort.h
@@ -0,0 +1,95 @@
+/*
+ * Copyright 2002 Adrian Thurston <thurston@colm.net>
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to
+ * deal in the Software without restriction, including without limitation the
+ * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
+ * sell copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+#ifndef _AAPL_BUBBLESORT_H
+#define _AAPL_BUBBLESORT_H
+
+#ifdef AAPL_NAMESPACE
+namespace Aapl {
+#endif
+
+/**
+ * \addtogroup sort
+ * @{
+ */
+
+/**
+ * \class BubbleSort
+ * \brief Bubble sort an array of data.
+ *
+ * BubbleSort can be used to sort any array of objects of type T provided a
+ * compare class is given. BubbleSort is in-place. It does not require any
+ * temporary storage.
+ *
+ * Objects are not made aware that they are being moved around in memory.
+ * Assignment operators, constructors and destructors are never invoked by the
+ * sort.
+ *
+ * BubbleSort runs in O(n^2) time. It is most useful when sorting arrays that
+ * are nearly sorted. It is best when neighbouring pairs are out of place.
+ * BubbleSort is a stable sort, meaning that objects with the same key have
+ * their relative ordering preserved.
+ */
+
+/*@}*/
+
+/* BubbleSort. */
+template <class T, class Compare> class BubbleSort
+ : public Compare
+{
+public:
+ /* Sorting interface routine. */
+ void sort(T *data, long len);
+};
+
+
+/**
+ * \brief Bubble sort an array of data.
+ */
+template <class T, class Compare> void BubbleSort<T,Compare>::
+ sort(T *data, long len)
+{
+ bool changed = true;
+ for ( long pass = 1; changed && pass < len; pass ++ ) {
+ changed = false;
+ for ( long i = 0; i < len-pass; i++ ) {
+ /* Do we swap pos with the next one? */
+ if ( this->compare( data[i], data[i+1] ) > 0 ) {
+ char tmp[sizeof(T)];
+
+ /* Swap the two items. */
+ memcpy( tmp, data+i, sizeof(T) );
+ memcpy( data+i, data+i+1, sizeof(T) );
+ memcpy( data+i+1, tmp, sizeof(T) );
+
+ /* Note that we made a change. */
+ changed = true;
+ }
+ }
+ }
+}
+
+#ifdef AAPL_NAMESPACE
+}
+#endif
+
+#endif /* _AAPL_BUBBLESORT_H */
diff --git a/src/aapl/buffer.h b/src/aapl/buffer.h
new file mode 100644
index 00000000..2aef08ca
--- /dev/null
+++ b/src/aapl/buffer.h
@@ -0,0 +1,60 @@
+/*
+ * Copyright 2003 Adrian Thurston <thurston@colm.net>
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to
+ * deal in the Software without restriction, including without limitation the
+ * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
+ * sell copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+#ifndef _AAPL_BUFFER_H
+#define _AAPL_BUFFER_H
+
+/* Buffer is an automatically grown buffer for collecting tokens. Always reuses
+ * space. Never down resizes. Clear is a cheap operation. */
+struct Buffer
+{
+ static const int BUFFER_INITIAL_SIZE = 4096;
+
+ Buffer()
+ {
+ data = (char*) malloc( BUFFER_INITIAL_SIZE );
+ allocated = BUFFER_INITIAL_SIZE;
+ length = 0;
+ }
+
+ ~Buffer()
+ {
+ free(data);
+ }
+
+ void append( char p )
+ {
+ if ( length == allocated ) {
+ allocated *= 2;
+ data = (char*) realloc( data, allocated );
+ }
+ data[length++] = p;
+ }
+
+ void clear() { length = 0; }
+
+ char *data;
+ int allocated;
+ int length;
+};
+
+#endif
diff --git a/src/aapl/compare.h b/src/aapl/compare.h
new file mode 100644
index 00000000..bbfa2136
--- /dev/null
+++ b/src/aapl/compare.h
@@ -0,0 +1,269 @@
+/*
+ * Copyright 2001 Adrian Thurston <thurston@colm.net>
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to
+ * deal in the Software without restriction, including without limitation the
+ * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
+ * sell copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+#ifndef _AAPL_COMPARE_H
+#define _AAPL_COMPARE_H
+
+#include <string.h>
+#include <string>
+#include "table.h"
+
+#ifdef AAPL_NAMESPACE
+namespace Aapl {
+#endif
+
+/**
+ * \defgroup compare Compare
+ * \brief Basic compare clases.
+ *
+ * Compare classes are used by data structures that need to know the relative
+ * ordering of elemets. To become a compare class, a class must imlement a
+ * routine long compare(const T &key1, const T &key2) that behaves just like
+ * strcmp.
+ *
+ * Compare classes are passed to the template data structure as a template
+ * parameter and are inherited. In most cases the compare routine will base
+ * the key comparision only on the two keys and the compare routine can
+ * therefore be static. Though sometimes it is useful to include data in the
+ * compare class and use this data in the comparison. For example the compare
+ * class may contain a pointer to some other data structure to which the
+ * comparison is delegated.
+ *
+ * @{
+ */
+
+/**
+ * \brief Compare two null terminated character sequences.
+ *
+ * This comparision class is a wrapper for strcmp.
+ */
+struct CmpStr
+{
+ /**
+ * \brief Compare two null terminated string types.
+ */
+ static inline long compare(const char *k1, const char *k2)
+ { return strcmp(k1, k2); }
+};
+
+struct CmpString
+{
+ static inline long compare(const std::string &k1, const std::string &k2)
+ { return k1.compare( k2 ); }
+};
+
+
+/**
+ * \brief Compare a type for which < and > are implemented.
+ *
+ * CmpOrd is suitable for simple types such as integers and pointers that by
+ * default have the less-than and greater-than operators defined.
+ */
+template <class T> struct CmpOrd
+{
+ /**
+ * \brief Compare two ordinal types.
+ *
+ * This compare routine copies its arguements in by value.
+ */
+ static inline long compare(const T k1, const T k2)
+ {
+ if (k1 < k2)
+ return -1;
+ else if (k1 > k2)
+ return 1;
+ else
+ return 0;
+ }
+};
+
+/**
+ * \brief Compare two tables of type T
+ *
+ * Table comparison is useful for keying a data structure on a vector or
+ * binary search table. T is the element type stored in the table.
+ * CompareT is the comparison structure used to compare the individual values
+ * in the table.
+ */
+template < class T, class CompareT = CmpOrd<T> > struct CmpTable
+ : public CompareT
+{
+ /**
+ * \brief Compare two tables storing type T.
+ */
+ static inline long compare(const Table<T> &t1, const Table<T> &t2)
+ {
+ if ( t1.tabLen < t2.tabLen )
+ return -1;
+ else if ( t1.tabLen > t2.tabLen )
+ return 1;
+ else
+ {
+ T *i1 = t1.data, *i2 = t2.data;
+ long len = t1.tabLen, cmpResult;
+ for ( long pos = 0; pos < len;
+ pos += 1, i1 += 1, i2 += 1 )
+ {
+ cmpResult = CompareT::compare(*i1, *i2);
+ if ( cmpResult != 0 )
+ return cmpResult;
+ }
+ return 0;
+ }
+ }
+};
+
+/**
+ * \brief Compare two tables of type T -- non-static version.
+ *
+ * CmpTableNs is identical to CmpTable, however the compare routine is
+ * non-static. If the CompareT class contains a non-static compare, then this
+ * version must be used because a static member cannot invoke a non-static
+ * member.
+ *
+ * Table comparison is useful for keying a data structure on a vector or binary
+ * search table. T is the element type stored in the table. CompareT
+ * is the comparison structure used to compare the individual values in the
+ * table.
+ */
+template < class T, class CompareT = CmpOrd<T> > struct CmpTableNs
+ : public CompareT
+{
+ /**
+ * \brief Compare two tables storing type T.
+ */
+ inline long compare(const Table<T> &t1, const Table<T> &t2)
+ {
+ if ( t1.tabLen < t2.tabLen )
+ return -1;
+ else if ( t1.tabLen > t2.tabLen )
+ return 1;
+ else
+ {
+ T *i1 = t1.data, *i2 = t2.data;
+ long len = t1.tabLen, cmpResult;
+ for ( long pos = 0; pos < len;
+ pos += 1, i1 += 1, i2 += 1 )
+ {
+ cmpResult = CompareT::compare(*i1, *i2);
+ if ( cmpResult != 0 )
+ return cmpResult;
+ }
+ return 0;
+ }
+ }
+};
+
+/**
+ * \brief Compare two implicitly shared tables of type T
+ *
+ * This table comparison is for data structures based on implicitly
+ * shared tables.
+ *
+ * Table comparison is useful for keying a data structure on a vector or
+ * binary search table. T is the element type stored in the table.
+ * CompareT is the comparison structure used to compare the individual values
+ * in the table.
+ */
+template < class T, class CompareT = CmpOrd<T> > struct CmpSTable : public CompareT
+{
+ /**
+ * \brief Compare two tables storing type T.
+ */
+ static inline long compare(const STable<T> &t1, const STable<T> &t2)
+ {
+ long t1Length = t1.length();
+ long t2Length = t2.length();
+
+ /* Compare lengths. */
+ if ( t1Length < t2Length )
+ return -1;
+ else if ( t1Length > t2Length )
+ return 1;
+ else {
+ /* Compare the table data. */
+ T *i1 = t1.data, *i2 = t2.data;
+ for ( long pos = 0; pos < t1Length;
+ pos += 1, i1 += 1, i2 += 1 )
+ {
+ long cmpResult = CompareT::compare(*i1, *i2);
+ if ( cmpResult != 0 )
+ return cmpResult;
+ }
+ return 0;
+ }
+ }
+};
+
+/**
+ * \brief Compare two implicitly shared tables of type T -- non-static
+ * version.
+ *
+ * This is a non-static table comparison for data structures based on
+ * implicitly shared tables. If the CompareT class contains a non-static
+ * compare, then this version must be used because a static member cannot
+ * invoke a non-static member.
+ *
+ * Table comparison is useful for keying a data structure on a vector or
+ * binary search table. T is the element type stored in the table.
+ * CompareT is the comparison structure used to compare the individual values
+ * in the table.
+ */
+template < class T, class CompareT = CmpOrd<T> > struct CmpSTableNs
+ : public CompareT
+{
+ /**
+ * \brief Compare two tables storing type T.
+ */
+ inline long compare(const STable<T> &t1, const STable<T> &t2)
+ {
+ long t1Length = t1.length();
+ long t2Length = t2.length();
+
+ /* Compare lengths. */
+ if ( t1Length < t2Length )
+ return -1;
+ else if ( t1Length > t2Length )
+ return 1;
+ else {
+ /* Compare the table data. */
+ T *i1 = t1.data, *i2 = t2.data;
+ for ( long pos = 0; pos < t1Length;
+ pos += 1, i1 += 1, i2 += 1 )
+ {
+ long cmpResult = CompareT::compare(*i1, *i2);
+ if ( cmpResult != 0 )
+ return cmpResult;
+ }
+ return 0;
+ }
+ }
+};
+
+
+/*@}*/
+
+#ifdef AAPL_NAMESPACE
+}
+#endif
+
+#endif /* _AAPL_COMPARE_H */
diff --git a/src/aapl/dlcommon.h b/src/aapl/dlcommon.h
new file mode 100644
index 00000000..92d45259
--- /dev/null
+++ b/src/aapl/dlcommon.h
@@ -0,0 +1,791 @@
+/*
+ * Copyright 2001 Adrian Thurston <thurston@colm.net>
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to
+ * deal in the Software without restriction, including without limitation the
+ * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
+ * sell copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+/* This header is not wrapped in ifndef becuase it is not intended to
+ * be included by the user. */
+
+#ifdef AAPL_NAMESPACE
+namespace Aapl {
+#endif
+
+#if defined( DOUBLELIST_VALUE )
+/**
+ * \brief Double list element for DListVal.
+ *
+ * DListValEl stores the type T of DListVal by value.
+ */
+template <class T> struct DListValEl
+{
+ /**
+ * \brief Construct a DListValEl with a given value.
+ *
+ * The only constructor available initializes the value element. This
+ * enforces that DListVal elements are never created without having their
+ * value intialzed by the user. T's copy constructor is used to copy the
+ * value in.
+ */
+ DListValEl( const T &val ) : value(val) { }
+
+ /**
+ * \brief Value stored by the list element.
+ *
+ * Value is always copied into new list elements using the copy
+ * constructor.
+ */
+ T value;
+
+ /**
+ * \brief List previous pointer.
+ *
+ * Points to the previous item in the list. If this is the first item in
+ * the list, then prev is NULL. If this element is not in a list then
+ * prev is undefined.
+ */
+ DListValEl<T> *prev;
+
+ /**
+ * \brief List next pointer.
+ *
+ * Points to the next item in the list. If this is the list item in the
+ * list, then next is NULL. If this element is not in a list then next is
+ * undefined.
+ */
+ DListValEl<T> *next;
+};
+#else
+
+#ifndef __AAPL_DOUBLE_LIST_EL
+#define __AAPL_DOUBLE_LIST_EL
+/**
+ * \brief Double list element properties.
+ *
+ * This class can be inherited to make a class suitable to be a double list
+ * element. It simply provides the next and previous pointers. An alternative
+ * is to put the next and previous pointers in the class directly.
+ */
+template <class Element> struct DListEl
+{
+ /**
+ * \brief List previous pointer.
+ *
+ * Points to the previous item in the list. If this is the first item in
+ * the list, then prev is NULL. If this element is not in a list then
+ * prev is undefined.
+ */
+ Element *prev;
+
+ /**
+ * \brief List next pointer.
+ *
+ * Points to the next item in the list. If this is the list item in the
+ * list, then next is NULL. If this element is not in a list then next is
+ * undefined.
+ */
+ Element *next;
+};
+#endif /* __AAPL_DOUBLE_LIST_EL */
+
+#endif
+
+/* Doubly Linked List */
+template <DLMEL_TEMPDEF> class DList
+{
+public:
+ /** \brief Initialize an empty list. */
+ DList() : head(0), tail(0), listLen(0) {}
+
+ /**
+ * \brief Perform a deep copy of the list.
+ *
+ * The elements of the other list are duplicated and put into this list.
+ * Elements are copied using the copy constructor.
+ */
+ DList(const DList &other);
+
+#ifdef DOUBLELIST_VALUE
+ /**
+ * \brief Clear the double list contents.
+ *
+ * All elements are deleted.
+ */
+ ~DList() { empty(); }
+
+ /**
+ * \brief Assign another list into this list using a deep copy.
+ *
+ * The elements of the other list are duplicated and put into this list.
+ * Each list item is created using the copy constructor. If this list
+ * contains any elements before the copy, they are deleted first.
+ *
+ * \returns A reference to this.
+ */
+ DList &operator=(const DList &other);
+
+ /**
+ * \brief Transfer the contents of another list into this list.
+ *
+ * The elements of the other list moved in. The other list will be empty
+ * afterwards. If this list contains any elements before the copy, then
+ * they are deleted.
+ */
+ void transfer(DList &other);
+#else
+ /**
+ * \brief Abandon all elements in the list.
+ *
+ * List elements are not deleted.
+ */
+ ~DList() {}
+
+ /**
+ * \brief Perform a deep copy of the list.
+ *
+ * The elements of the other list are duplicated and put into this list.
+ * Each list item is created using the copy constructor. If this list
+ * contains any elements before the copy, they are abandoned.
+ *
+ * \returns A reference to this.
+ */
+ DList &operator=(const DList &other);
+
+ /**
+ * \brief Transfer the contents of another list into this list.
+ *
+ * The elements of the other list moved in. The other list will be empty
+ * afterwards. If this list contains any elements before the copy, they
+ * are abandoned.
+ */
+ void transfer(DList &other);
+#endif
+
+
+#ifdef DOUBLELIST_VALUE
+ /**
+ * \brief Make a new element and prepend it to the front of the list.
+ *
+ * The item is copied into the new element using the copy constructor.
+ * Equivalent to list.addBefore(list.head, item).
+ */
+ void prepend(const T &item);
+
+ /**
+ * \brief Make a new element and append it to the end of the list.
+ *
+ * The item is copied into the new element using the copy constructor.
+ * Equivalent to list.addAfter(list.tail, item).
+ */
+ void append(const T &item);
+
+ /**
+ * \brief Make a new element and insert it immediately after an element in
+ * the list.
+ *
+ * The item is copied into the new element using the copy constructor. If
+ * prev_el is NULL then the new element is prepended to the front of the
+ * list. If prev_el is not already in the list then undefined behaviour
+ * results. Equivalent to list.addAfter(prev_el, new DListValEl(item)).
+ */
+ void addAfter(Element *prev_el, const T &item);
+
+ /**
+ * \brief Make a new element and insert it immediately before an element
+ * in the list.
+ *
+ * The item is copied into the new element using the copy construcotor. If
+ * next_el is NULL then the new element is appended to the end of the
+ * list. If next_el is not already in the list then undefined behaviour
+ * results. Equivalent to list.addBefore(next_el, new DListValEl(item)).
+ */
+ void addBefore(Element *next_el, const T &item);
+#endif
+
+ /**
+ * \brief Prepend a single element to the front of the list.
+ *
+ * If new_el is already an element of some list, then undefined behaviour
+ * results. Equivalent to list.addBefore(list.head, new_el).
+ */
+ void prepend(Element *new_el) { addBefore(head, new_el); }
+
+ /**
+ * \brief Append a single element to the end of the list.
+ *
+ * If new_el is alreay an element of some list, then undefined behaviour
+ * results. Equivalent to list.addAfter(list.tail, new_el).
+ */
+ void append(Element *new_el) { addAfter(tail, new_el); }
+
+ /**
+ * \brief Prepend an entire list to the beginning of this list.
+ *
+ * All items are moved, not copied. Afterwards, the other list is emtpy.
+ * All items are prepended at once, so this is an O(1) operation.
+ * Equivalent to list.addBefore(list.head, dl).
+ */
+ void prepend(DList &dl) { addBefore(head, dl); }
+
+ /**
+ * \brief Append an entire list to the end of the list.
+ *
+ * All items are moved, not copied. Afterwards, the other list is empty.
+ * All items are appened at once, so this is an O(1) operation.
+ * Equivalent to list.addAfter(list.tail, dl).
+ */
+ void append(DList &dl) { addAfter(tail, dl); }
+
+ void addAfter(Element *prev_el, Element *new_el);
+ void addBefore(Element *next_el, Element *new_el);
+
+ void addAfter(Element *prev_el, DList &dl);
+ void addBefore(Element *next_el, DList &dl);
+
+ /**
+ * \brief Detach the head of the list
+ *
+ * The element detached is not deleted. If there is no head of the list
+ * (the list is empty) then undefined behaviour results. Equivalent to
+ * list.detach(list.head).
+ *
+ * \returns The element detached.
+ */
+ Element *detachFirst() { return detach(head); }
+
+ /**
+ * \brief Detach the tail of the list
+ *
+ * The element detached is not deleted. If there is no tail of the list
+ * (the list is empty) then undefined behaviour results. Equivalent to
+ * list.detach(list.tail).
+ *
+ * \returns The element detached.
+ */
+ Element *detachLast() { return detach(tail); }
+
+ /* Detaches an element from the list. Does not free any memory. */
+ Element *detach(Element *el);
+
+ /**
+ * \brief Detach and delete the first element in the list.
+ *
+ * If there is no first element (the list is empty) then undefined
+ * behaviour results. Equivalent to delete list.detach(list.head);
+ */
+ void removeFirst() { delete detach( head ); }
+
+ /**
+ * \brief Detach and delete the last element in the list.
+ *
+ * If there is no last element (the list is emtpy) then undefined
+ * behaviour results. Equivalent to delete list.detach(list.tail);
+ */
+ void removeLast() { delete detach( tail ); }
+
+ /**
+ * \brief Detach and delete an element from the list.
+ *
+ * If the element is not in the list, then undefined behaviour results.
+ * Equivalent to delete list.detach(el);
+ */
+ void remove(Element *el) { delete detach( el ); }
+
+ void empty();
+ void abandon();
+
+ /** \brief The number of elements in the list. */
+ long length() const { return listLen; }
+
+ /** \brief Head and tail of the linked list. */
+ Element *head, *tail;
+
+ /** \brief The number of element in the list. */
+ long listLen;
+
+ /* Convenience access. */
+ long size() const { return listLen; }
+
+ /* Forward this so a ref can be used. */
+ struct Iter;
+
+ /* Class for setting the iterator. */
+ struct IterFirst { IterFirst( const DList &l ) : l(l) { } const DList &l; };
+ struct IterLast { IterLast( const DList &l ) : l(l) { } const DList &l; };
+ struct IterNext { IterNext( const Iter &i ) : i(i) { } const Iter &i; };
+ struct IterPrev { IterPrev( const Iter &i ) : i(i) { } const Iter &i; };
+
+ /**
+ * \brief Double List Iterator.
+ * \ingroup iterators
+ */
+ struct Iter
+ {
+ /* Default construct. */
+ Iter() : ptr(0) { }
+
+ /* Construct from a double list. */
+ Iter( const DList &dl ) : ptr(dl.head) { }
+ Iter( Element *el ) : ptr(el) { }
+ Iter( const IterFirst &dlf ) : ptr(dlf.l.head) { }
+ Iter( const IterLast &dll ) : ptr(dll.l.tail) { }
+ Iter( const IterNext &dln ) : ptr(dln.i.ptr->BASE_EL(next)) { }
+ Iter( const IterPrev &dlp ) : ptr(dlp.i.ptr->BASE_EL(prev)) { }
+
+ /* Assign from a double list. */
+ Iter &operator=( const DList &dl ) { ptr = dl.head; return *this; }
+ Iter &operator=( Element *el ) { ptr = el; return *this; }
+ Iter &operator=( const IterFirst &af ) { ptr = af.l.head; return *this; }
+ Iter &operator=( const IterLast &al ) { ptr = al.l.tail; return *this; }
+ Iter &operator=( const IterNext &an ) { ptr = an.i.ptr->BASE_EL(next); return *this; }
+ Iter &operator=( const IterPrev &ap ) { ptr = ap.i.ptr->BASE_EL(prev); return *this; }
+
+ /** \brief Less than end? */
+ bool lte() const { return ptr != 0; }
+
+ /** \brief At end? */
+ bool end() const { return ptr == 0; }
+
+ /** \brief Greater than beginning? */
+ bool gtb() const { return ptr != 0; }
+
+ /** \brief At beginning? */
+ bool beg() const { return ptr == 0; }
+
+ /** \brief At first element? */
+ bool first() const { return ptr && ptr->BASE_EL(prev) == 0; }
+
+ /** \brief At last element? */
+ bool last() const { return ptr && ptr->BASE_EL(next) == 0; }
+
+ /** \brief Implicit cast to Element*. */
+ operator Element*() const { return ptr; }
+
+ /** \brief Dereference operator returns Element&. */
+ Element &operator *() const { return *ptr; }
+
+ /** \brief Arrow operator returns Element*. */
+ Element *operator->() const { return ptr; }
+
+ /** \brief Move to next item. */
+ inline Element *operator++() { return ptr = ptr->BASE_EL(next); }
+
+ /** \brief Move to next item. */
+ inline Element *increment() { return ptr = ptr->BASE_EL(next); }
+
+ /** \brief Move to next item. */
+ inline Element *operator++(int);
+
+ /** \brief Move to previous item. */
+ inline Element *operator--() { return ptr = ptr->BASE_EL(prev); }
+
+ /** \brief Move to previous item. */
+ inline Element *decrement() { return ptr = ptr->BASE_EL(prev); }
+
+ /** \brief Move to previous item. */
+ inline Element *operator--(int);
+
+ /** \brief Return the next item. Does not modify this. */
+ inline IterNext next() const { return IterNext(*this); }
+
+ /** \brief Return the prev item. Does not modify this. */
+ inline IterPrev prev() const { return IterPrev(*this); }
+
+ /** \brief The iterator is simply a pointer. */
+ Element *ptr;
+ };
+
+ /** \brief Return first element. */
+ IterFirst first() { return IterFirst(*this); }
+
+ /** \brief Return last element. */
+ IterLast last() { return IterLast(*this); }
+};
+
+/* Copy constructor, does a deep copy of other. */
+template <DLMEL_TEMPDEF> DList<DLMEL_TEMPUSE>::
+ DList(const DList<DLMEL_TEMPUSE> &other) :
+ head(0), tail(0), listLen(0)
+{
+ Element *el = other.head;
+ while( el != 0 ) {
+ append( new Element(*el) );
+ el = el->BASE_EL(next);
+ }
+}
+
+#ifdef DOUBLELIST_VALUE
+
+/* Assignement operator does deep copy. */
+template <DLMEL_TEMPDEF> DList<DLMEL_TEMPUSE> &DList<DLMEL_TEMPUSE>::
+ operator=(const DList &other)
+{
+ /* Free the old list. The value list assumes items were allocated on the
+ * heap by itself. */
+ empty();
+
+ Element *el = other.head;
+ while( el != 0 ) {
+ append( new Element(*el) );
+ el = el->BASE_EL(next);
+ }
+ return *this;
+}
+
+template <DLMEL_TEMPDEF> void DList<DLMEL_TEMPUSE>::
+ transfer(DList &other)
+{
+ /* Free the old list. The value list assumes items were allocated on the
+ * heap by itself. */
+ empty();
+
+ head = other.head;
+ tail = other.tail;
+ listLen = other.listLen;
+
+ other.abandon();
+}
+
+#else
+
+/* Assignement operator does deep copy. */
+template <DLMEL_TEMPDEF> DList<DLMEL_TEMPUSE> &DList<DLMEL_TEMPUSE>::
+ operator=(const DList &other)
+{
+ Element *el = other.head;
+ while( el != 0 ) {
+ append( new Element(*el) );
+ el = el->BASE_EL(next);
+ }
+ return *this;
+}
+
+template <DLMEL_TEMPDEF> void DList<DLMEL_TEMPUSE>::
+ transfer(DList &other)
+{
+ head = other.head;
+ tail = other.tail;
+ listLen = other.listLen;
+
+ other.abandon();
+}
+
+#endif
+
+#ifdef DOUBLELIST_VALUE
+
+/* Prepend a new item. Inlining this bloats the caller with new overhead. */
+template <DLMEL_TEMPDEF> void DList<DLMEL_TEMPUSE>::
+ prepend(const T &item)
+{
+ addBefore(head, new Element(item));
+}
+
+/* Append a new item. Inlining this bloats the caller with the new overhead. */
+template <DLMEL_TEMPDEF> void DList<DLMEL_TEMPUSE>::
+ append(const T &item)
+{
+ addAfter(tail, new Element(item));
+}
+
+/* Add a new item after a prev element. Inlining this bloats the caller with
+ * the new overhead. */
+template <DLMEL_TEMPDEF> void DList<DLMEL_TEMPUSE>::
+ addAfter(Element *prev_el, const T &item)
+{
+ addAfter(prev_el, new Element(item));
+}
+
+/* Add a new item before a next element. Inlining this bloats the caller with
+ * the new overhead. */
+template <DLMEL_TEMPDEF> void DList<DLMEL_TEMPUSE>::
+ addBefore(Element *next_el, const T &item)
+{
+ addBefore(next_el, new Element(item));
+}
+
+#endif
+
+/*
+ * The larger iterator operators.
+ */
+
+/* Postfix ++ */
+template <DLMEL_TEMPDEF> Element *DList<DLMEL_TEMPUSE>::Iter::
+ operator++(int)
+{
+ Element *rtn = ptr;
+ ptr = ptr->BASE_EL(next);
+ return rtn;
+}
+
+/* Postfix -- */
+template <DLMEL_TEMPDEF> Element *DList<DLMEL_TEMPUSE>::Iter::
+ operator--(int)
+{
+ Element *rtn = ptr;
+ ptr = ptr->BASE_EL(prev);
+ return rtn;
+}
+
+/**
+ * \brief Insert an element immediately after an element in the list.
+ *
+ * If prev_el is NULL then new_el is prepended to the front of the list. If
+ * prev_el is not in the list or if new_el is already in a list, then
+ * undefined behaviour results.
+ */
+template <DLMEL_TEMPDEF> void DList<DLMEL_TEMPUSE>::
+ addAfter(Element *prev_el, Element *new_el)
+{
+ /* Set the previous pointer of new_el to prev_el. We do
+ * this regardless of the state of the list. */
+ new_el->BASE_EL(prev) = prev_el;
+
+ /* Set forward pointers. */
+ if (prev_el == 0) {
+ /* There was no prev_el, we are inserting at the head. */
+ new_el->BASE_EL(next) = head;
+ head = new_el;
+ }
+ else {
+ /* There was a prev_el, we can access previous next. */
+ new_el->BASE_EL(next) = prev_el->BASE_EL(next);
+ prev_el->BASE_EL(next) = new_el;
+ }
+
+ /* Set reverse pointers. */
+ if (new_el->BASE_EL(next) == 0) {
+ /* There is no next element. Set the tail pointer. */
+ tail = new_el;
+ }
+ else {
+ /* There is a next element. Set it's prev pointer. */
+ new_el->BASE_EL(next)->BASE_EL(prev) = new_el;
+ }
+
+ /* Update list length. */
+ listLen++;
+}
+
+/**
+ * \brief Insert an element immediatly before an element in the list.
+ *
+ * If next_el is NULL then new_el is appended to the end of the list. If
+ * next_el is not in the list or if new_el is already in a list, then
+ * undefined behaviour results.
+ */
+template <DLMEL_TEMPDEF> void DList<DLMEL_TEMPUSE>::
+ addBefore(Element *next_el, Element *new_el)
+{
+ /* Set the next pointer of the new element to next_el. We do
+ * this regardless of the state of the list. */
+ new_el->BASE_EL(next) = next_el;
+
+ /* Set reverse pointers. */
+ if (next_el == 0) {
+ /* There is no next elememnt. We are inserting at the tail. */
+ new_el->BASE_EL(prev) = tail;
+ tail = new_el;
+ }
+ else {
+ /* There is a next element and we can access next's previous. */
+ new_el->BASE_EL(prev) = next_el->BASE_EL(prev);
+ next_el->BASE_EL(prev) = new_el;
+ }
+
+ /* Set forward pointers. */
+ if (new_el->BASE_EL(prev) == 0) {
+ /* There is no previous element. Set the head pointer.*/
+ head = new_el;
+ }
+ else {
+ /* There is a previous element, set it's next pointer to new_el. */
+ new_el->BASE_EL(prev)->BASE_EL(next) = new_el;
+ }
+
+ /* Update list length. */
+ listLen++;
+}
+
+/**
+ * \brief Insert an entire list immediatly after an element in this list.
+ *
+ * Elements are moved, not copied. Afterwards, the other list is empty. If
+ * prev_el is NULL then the elements are prepended to the front of the list.
+ * If prev_el is not in the list then undefined behaviour results. All
+ * elements are inserted into the list at once, so this is an O(1) operation.
+ */
+template <DLMEL_TEMPDEF> void DList<DLMEL_TEMPUSE>::
+ addAfter( Element *prev_el, DList<DLMEL_TEMPUSE> &dl )
+{
+ /* Do not bother if dl has no elements. */
+ if ( dl.listLen == 0 )
+ return;
+
+ /* Set the previous pointer of dl.head to prev_el. We do
+ * this regardless of the state of the list. */
+ dl.head->BASE_EL(prev) = prev_el;
+
+ /* Set forward pointers. */
+ if (prev_el == 0) {
+ /* There was no prev_el, we are inserting at the head. */
+ dl.tail->BASE_EL(next) = head;
+ head = dl.head;
+ }
+ else {
+ /* There was a prev_el, we can access previous next. */
+ dl.tail->BASE_EL(next) = prev_el->BASE_EL(next);
+ prev_el->BASE_EL(next) = dl.head;
+ }
+
+ /* Set reverse pointers. */
+ if (dl.tail->BASE_EL(next) == 0) {
+ /* There is no next element. Set the tail pointer. */
+ tail = dl.tail;
+ }
+ else {
+ /* There is a next element. Set it's prev pointer. */
+ dl.tail->BASE_EL(next)->BASE_EL(prev) = dl.tail;
+ }
+
+ /* Update the list length. */
+ listLen += dl.listLen;
+
+ /* Empty out dl. */
+ dl.head = dl.tail = 0;
+ dl.listLen = 0;
+}
+
+/**
+ * \brief Insert an entire list immediately before an element in this list.
+ *
+ * Elements are moved, not copied. Afterwards, the other list is empty. If
+ * next_el is NULL then the elements are appended to the end of the list. If
+ * next_el is not in the list then undefined behaviour results. All elements
+ * are inserted at once, so this is an O(1) operation.
+ */
+template <DLMEL_TEMPDEF> void DList<DLMEL_TEMPUSE>::
+ addBefore( Element *next_el, DList<DLMEL_TEMPUSE> &dl )
+{
+ /* Do not bother if dl has no elements. */
+ if ( dl.listLen == 0 )
+ return;
+
+ /* Set the next pointer of dl.tail to next_el. We do
+ * this regardless of the state of the list. */
+ dl.tail->BASE_EL(next) = next_el;
+
+ /* Set reverse pointers. */
+ if (next_el == 0) {
+ /* There is no next elememnt. We are inserting at the tail. */
+ dl.head->BASE_EL(prev) = tail;
+ tail = dl.tail;
+ }
+ else {
+ /* There is a next element and we can access next's previous. */
+ dl.head->BASE_EL(prev) = next_el->BASE_EL(prev);
+ next_el->BASE_EL(prev) = dl.tail;
+ }
+
+ /* Set forward pointers. */
+ if (dl.head->BASE_EL(prev) == 0) {
+ /* There is no previous element. Set the head pointer.*/
+ head = dl.head;
+ }
+ else {
+ /* There is a previous element, set it's next pointer to new_el. */
+ dl.head->BASE_EL(prev)->BASE_EL(next) = dl.head;
+ }
+
+ /* Update list length. */
+ listLen += dl.listLen;
+
+ /* Empty out dl. */
+ dl.head = dl.tail = 0;
+ dl.listLen = 0;
+}
+
+
+/**
+ * \brief Detach an element from the list.
+ *
+ * The element is not deleted. If the element is not in the list, then
+ * undefined behaviour results.
+ *
+ * \returns The element detached.
+ */
+template <DLMEL_TEMPDEF> Element *DList<DLMEL_TEMPUSE>::
+ detach(Element *el)
+{
+ /* Set forward pointers to skip over el. */
+ if (el->BASE_EL(prev) == 0)
+ head = el->BASE_EL(next);
+ else {
+ el->BASE_EL(prev)->BASE_EL(next) =
+ el->BASE_EL(next);
+ }
+
+ /* Set reverse pointers to skip over el. */
+ if (el->BASE_EL(next) == 0)
+ tail = el->BASE_EL(prev);
+ else {
+ el->BASE_EL(next)->BASE_EL(prev) =
+ el->BASE_EL(prev);
+ }
+
+ /* Update List length and return element we detached. */
+ listLen--;
+ return el;
+}
+
+/**
+ * \brief Clear the list by deleting all elements.
+ *
+ * Each item in the list is deleted. The list is reset to its initial state.
+ */
+template <DLMEL_TEMPDEF> void DList<DLMEL_TEMPUSE>::empty()
+{
+ Element *nextToGo = 0, *cur = head;
+
+ while (cur != 0)
+ {
+ nextToGo = cur->BASE_EL(next);
+ delete cur;
+ cur = nextToGo;
+ }
+ head = tail = 0;
+ listLen = 0;
+}
+
+/**
+ * \brief Clear the list by forgetting all elements.
+ *
+ * All elements are abandoned, not deleted. The list is reset to it's initial
+ * state.
+ */
+template <DLMEL_TEMPDEF> void DList<DLMEL_TEMPUSE>::abandon()
+{
+ head = tail = 0;
+ listLen = 0;
+}
+
+#ifdef AAPL_NAMESPACE
+}
+#endif
diff --git a/src/aapl/dlist.h b/src/aapl/dlist.h
new file mode 100644
index 00000000..9663caca
--- /dev/null
+++ b/src/aapl/dlist.h
@@ -0,0 +1,65 @@
+/*
+ * Copyright 2001 Adrian Thurston <thurston@colm.net>
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to
+ * deal in the Software without restriction, including without limitation the
+ * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
+ * sell copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+#ifndef _AAPL_DLIST_H
+#define _AAPL_DLIST_H
+
+#define BASE_EL(name) name
+#define DLMEL_TEMPDEF class Element
+#define DLMEL_TEMPUSE Element
+#define DList DList
+
+/**
+ * \addtogroup dlist
+ * @{
+ */
+
+/**
+ * \class DList
+ * \brief Basic doubly linked list.
+ *
+ * DList is the standard by-structure list type. This class requires the
+ * programmer to declare a list element type that has the necessary next and
+ * previous pointers in it. This can be achieved by inheriting from the
+ * DListEl class or by simply adding next and previous pointers directly into
+ * the list element class.
+ *
+ * DList does not assume ownership of elements in the list. If the elements
+ * are known to reside on the heap, the provided empty() routine can be used to
+ * delete all elements, however the destructor will not call this routine, it
+ * will simply abandon all the elements. It is up to the programmer to
+ * explicitly de-allocate items when necessary.
+ *
+ * \include ex_dlist.cpp
+ */
+
+/*@}*/
+
+#include "dlcommon.h"
+
+#undef BASE_EL
+#undef DLMEL_TEMPDEF
+#undef DLMEL_TEMPUSE
+#undef DList
+
+#endif /* _AAPL_DLIST_H */
+
diff --git a/src/aapl/dlistmel.h b/src/aapl/dlistmel.h
new file mode 100644
index 00000000..f2004b81
--- /dev/null
+++ b/src/aapl/dlistmel.h
@@ -0,0 +1,72 @@
+/*
+ * Copyright 2001 Adrian Thurston <thurston@colm.net>
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to
+ * deal in the Software without restriction, including without limitation the
+ * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
+ * sell copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+#ifndef _AAPL_DLISTMEL_H
+#define _AAPL_DLISTMEL_H
+
+/**
+ * \addtogroup dlist
+ * @{
+ */
+
+/**
+ * \class DListMel
+ * \brief Doubly linked list for elements that may appear in multiple lists.
+ *
+ * This class is similar to DList, except that the user defined list element
+ * can inherit from multple DListEl classes and consequently be an element in
+ * multiple lists. In other words, DListMel allows a single instance of a data
+ * structure to be an element in multiple lists without the lists interfereing
+ * with one another.
+ *
+ * For each list that an element class is to appear in, the element must have
+ * unique next and previous pointers that can be unambiguously refered to with
+ * some base class name. This name is given to DListMel as a template argument
+ * so it can use the correct next and previous pointers in its list
+ * operations.
+ *
+ * DListMel does not assume ownership of elements in the list. If the elements
+ * are known to reside on the heap and are not contained in any other list or
+ * data structure, the provided empty() routine can be used to delete all
+ * elements, however the destructor will not call this routine, it will simply
+ * abandon all the elements. It is up to the programmer to explicitly
+ * de-allocate items when it is safe to do so.
+ *
+ * \include ex_dlistmel.cpp
+ */
+
+/*@}*/
+
+#define BASE_EL(name) BaseEl::name
+#define DLMEL_TEMPDEF class Element, class BaseEl
+#define DLMEL_TEMPUSE Element, BaseEl
+#define DList DListMel
+
+#include "dlcommon.h"
+
+#undef BASE_EL
+#undef DLMEL_TEMPDEF
+#undef DLMEL_TEMPUSE
+#undef DList
+
+#endif /* _AAPL_DLISTMEL_H */
+
diff --git a/src/aapl/dlistval.h b/src/aapl/dlistval.h
new file mode 100644
index 00000000..efdb1cc1
--- /dev/null
+++ b/src/aapl/dlistval.h
@@ -0,0 +1,72 @@
+/*
+ * Copyright 2002 Adrian Thurston <thurston@colm.net>
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to
+ * deal in the Software without restriction, including without limitation the
+ * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
+ * sell copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+#ifndef _AAPL_DLISTVAL_H
+#define _AAPL_DLISTVAL_H
+
+/**
+ * \addtogroup dlist
+ * @{
+ */
+
+/**
+ * \class DListVal
+ * \brief By-value doubly linked list.
+ *
+ * This class is a doubly linked list that does not require a list element
+ * type to be declared. The user instead gives a type that is to be stored in
+ * the list element. When inserting a new data item, the value is copied into
+ * a newly allocated element. This list is inteded to behave and be utilized
+ * like the list template found in the STL.
+ *
+ * DListVal is different from the other lists in that it allocates elements
+ * itself. The raw element insert interface is still exposed for convenience,
+ * however, the list assumes all elements in the list are allocated on the
+ * heap and are to be managed by the list. The destructor WILL delete the
+ * contents of the list. If the list is ever copied in from another list, the
+ * existing contents are deleted first. This is in contrast to DList and
+ * DListMel, which will never delete their contents to allow for statically
+ * allocated elements.
+ *
+ * \include ex_dlistval.cpp
+ */
+
+/*@}*/
+
+#define BASE_EL(name) name
+#define DLMEL_TEMPDEF class T
+#define DLMEL_TEMPUSE T
+#define DList DListVal
+#define Element DListValEl<T>
+#define DOUBLELIST_VALUE
+
+#include "dlcommon.h"
+
+#undef BASE_EL
+#undef DLMEL_TEMPDEF
+#undef DLMEL_TEMPUSE
+#undef DList
+#undef Element
+#undef DOUBLELIST_VALUE
+
+#endif /* _AAPL_DLISTVAL_H */
+
diff --git a/src/aapl/insertsort.h b/src/aapl/insertsort.h
new file mode 100644
index 00000000..386fd9c6
--- /dev/null
+++ b/src/aapl/insertsort.h
@@ -0,0 +1,95 @@
+/*
+ * Copyright 2002 Adrian Thurston <thurston@colm.net>
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to
+ * deal in the Software without restriction, including without limitation the
+ * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
+ * sell copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+#ifndef _AAPL_INSERTSORT_H
+#define _AAPL_INSERTSORT_H
+
+#ifdef AAPL_NAMESPACE
+namespace Aapl {
+#endif
+
+/**
+ * \addtogroup sort
+ * @{
+ */
+
+/**
+ * \class InsertSort
+ * \brief Insertion sort an array of data.
+ *
+ * InsertSort can be used to sort any array of objects of type T provided a
+ * compare class is given. InsertSort is in-place. It does not require any
+ * temporary storage.
+ *
+ * Objects are not made aware that they are being moved around in memory.
+ * Assignment operators, constructors and destructors are never invoked by the
+ * sort.
+ *
+ * InsertSort runs in O(n^2) time. It is most useful when sorting small arrays.
+ * where it can outperform the O(n*log(n)) sorters due to its simplicity.
+ * InsertSort is a not a stable sort. Elements with the same key will not have
+ * their relative ordering preserved.
+ */
+
+/*@}*/
+
+/* InsertSort. */
+template <class T, class Compare> class InsertSort
+ : public Compare
+{
+public:
+ /* Sorting interface routine. */
+ void sort(T *data, long len);
+};
+
+
+/**
+ * \brief Insertion sort an array of data.
+ */
+template <class T, class Compare>
+ void InsertSort<T,Compare>::sort(T *data, long len)
+{
+ /* For each next largest spot in the sorted array... */
+ for ( T *dest = data; dest < data+len-1; dest++ ) {
+ /* Find the next smallest element in the unsorted array. */
+ T *smallest = dest;
+ for ( T *src = dest+1; src < data+len; src++ ) {
+ /* If src is smaller than the current src, then use it. */
+ if ( this->compare( *src, *smallest ) < 0 )
+ smallest = src;
+ }
+
+ if ( smallest != dest ) {
+ /* Swap dest, smallest. */
+ char tmp[sizeof(T)];
+ memcpy( tmp, dest, sizeof(T) );
+ memcpy( dest, smallest, sizeof(T) );
+ memcpy( smallest, tmp, sizeof(T) );
+ }
+ }
+}
+
+#ifdef AAPL_NAMESPACE
+}
+#endif
+
+#endif /* _AAPL_INSERTSORT_H */
diff --git a/src/aapl/mergesort.h b/src/aapl/mergesort.h
new file mode 100644
index 00000000..83f8b67b
--- /dev/null
+++ b/src/aapl/mergesort.h
@@ -0,0 +1,141 @@
+/*
+ * Copyright 2001, 2002 Adrian Thurston <thurston@colm.net>
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to
+ * deal in the Software without restriction, including without limitation the
+ * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
+ * sell copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+#ifndef _AAPL_MERGESORT_H
+#define _AAPL_MERGESORT_H
+
+#include "bubblesort.h"
+
+#ifdef AAPL_NAMESPACE
+namespace Aapl {
+#endif
+
+/**
+ * \addtogroup sort
+ * @{
+ */
+
+/**
+ * \class MergeSort
+ * \brief Merge sort an array of data.
+ *
+ * MergeSort can be used to sort any array of objects of type T provided a
+ * compare class is given. MergeSort is not in-place, it requires temporary
+ * storage equal to the size of the array. The temporary storage is allocated
+ * on the heap.
+ *
+ * Objects are not made aware that they are being moved around in memory.
+ * Assignment operators, constructors and destructors are never invoked by the
+ * sort.
+ *
+ * MergeSort runs in worst case O(n*log(n)) time. In most cases it is slower
+ * than QuickSort because more copying is neccessary. But on the other hand,
+ * it is a stable sort, meaning that objects with the same key have their
+ * relative ordering preserved. Also, its worst case is better. MergeSort
+ * switches to a BubbleSort when the size of the array being sorted is small.
+ * This happens when directly sorting a small array or when MergeSort calls
+ * itself recursively on a small portion of a larger array.
+ */
+
+/*@}*/
+
+
+/* MergeSort. */
+template <class T, class Compare> class MergeSort
+ : public BubbleSort<T, Compare>
+{
+public:
+ /* Sorting interface routine. */
+ void sort(T *data, long len);
+
+private:
+ /* Recursive worker. */
+ void doSort(T *tmpStor, T *data, long len);
+};
+
+#define _MS_BUBBLE_THRESH 16
+
+/* Recursive mergesort worker. Split data, make recursive calls, merge
+ * results. */
+template< class T, class Compare> void MergeSort<T,Compare>::
+ doSort(T *tmpStor, T *data, long len)
+{
+ if ( len <= 1 )
+ return;
+
+ if ( len <= _MS_BUBBLE_THRESH ) {
+ BubbleSort<T, Compare>::sort( data, len );
+ return;
+ }
+
+ long mid = len / 2;
+
+ doSort( tmpStor, data, mid );
+ doSort( tmpStor + mid, data + mid, len - mid );
+
+ /* Merge the data. */
+ T *endLower = data + mid, *lower = data;
+ T *endUpper = data + len, *upper = data + mid;
+ T *dest = tmpStor;
+ while ( true ) {
+ if ( lower == endLower ) {
+ /* Possibly upper left. */
+ if ( upper != endUpper )
+ memcpy( dest, upper, (endUpper - upper) * sizeof(T) );
+ break;
+ }
+ else if ( upper == endUpper ) {
+ /* Only lower left. */
+ if ( lower != endLower )
+ memcpy( dest, lower, (endLower - lower) * sizeof(T) );
+ break;
+ }
+ else {
+ /* Both upper and lower left. */
+ if ( this->compare(*lower, *upper) <= 0 )
+ memcpy( dest++, lower++, sizeof(T) );
+ else
+ memcpy( dest++, upper++, sizeof(T) );
+ }
+ }
+
+ /* Copy back from the tmpStor array. */
+ memcpy( data, tmpStor, sizeof( T ) * len );
+}
+
+/**
+ * \brief Merge sort an array of data.
+ */
+template< class T, class Compare>
+ void MergeSort<T,Compare>::sort(T *data, long len)
+{
+ /* Allocate the tmp space needed by merge sort, sort and free. */
+ T *tmpStor = (T*) new char[sizeof(T) * len];
+ doSort( tmpStor, data, len );
+ delete[] (char*) tmpStor;
+}
+
+#ifdef AAPL_NAMESPACE
+}
+#endif
+
+#endif /* _AAPL_MERGESORT_H */
diff --git a/src/aapl/quicksort.h b/src/aapl/quicksort.h
new file mode 100644
index 00000000..f23ec2ee
--- /dev/null
+++ b/src/aapl/quicksort.h
@@ -0,0 +1,186 @@
+/*
+ * Copyright 2002 Adrian Thurston <thurston@colm.net>
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to
+ * deal in the Software without restriction, including without limitation the
+ * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
+ * sell copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+#ifndef _AAPL_QUICKSORT_H
+#define _AAPL_QUICKSORT_H
+
+#include "insertsort.h"
+
+#ifdef AAPL_NAMESPACE
+namespace Aapl {
+#endif
+
+/**
+ * \addtogroup sort
+ * @{
+ */
+
+/**
+ * \class QuickSort
+ * \brief Quick sort an array of data.
+ *
+ * QuickSort can be used to sort any array of objects of type T provided a
+ * compare class is given. QuickSort is in-place. It does not require any
+ * temporary storage.
+ *
+ * Objects are not made aware that they are being moved around in memory.
+ * Assignment operators, constructors and destructors are never invoked by the
+ * sort.
+ *
+ * QuickSort runs in O(n*log(n)) time in the average case. It is faster than
+ * mergsort in the average case because it does less moving of data. The
+ * performance of quicksort depends mostly on the choice of pivot. This
+ * implementation picks the pivot as the median of first, middle, last. This
+ * choice of pivot avoids the O(n^2) worst case for input already sorted, but
+ * it is still possible to encounter the O(n^2) worst case. For example an
+ * array of identical elements will run in O(n^2)
+ *
+ * QuickSort is not a stable sort. Elements with the same key will not have
+ * their relative ordering preserved. QuickSort switches to an InsertSort
+ * when the size of the array being sorted is small. This happens when
+ * directly sorting a small array or when QuickSort calls iteself recursively
+ * on a small portion of a larger array.
+ */
+
+/*@}*/
+
+/* QuickSort. */
+template <class T, class Compare> class QuickSort :
+ public InsertSort<T, Compare>
+{
+public:
+ /* Sorting interface routine. */
+ void sort(T *data, long len);
+
+private:
+ /* Recursive worker. */
+ void doSort(T *start, T *end);
+ T *partition(T *start, T *end);
+ inline T *median(T *start, T *end);
+};
+
+#define _QS_INSERTION_THRESH 16
+
+/* Finds the median of start, middle, end. */
+template <class T, class Compare> T *QuickSort<T,Compare>::
+ median(T *start, T *end)
+{
+ T *pivot, *mid = start + (end-start)/2;
+
+ /* CChoose the pivot. */
+ if ( this->compare(*start, *mid) < 0 ) {
+ if ( this->compare(*mid, *end) < 0 )
+ pivot = mid;
+ else if ( this->compare(*start, *end) < 0 )
+ pivot = end;
+ else
+ pivot = start;
+ }
+ else if ( this->compare(*start, *end) < 0 )
+ pivot = start;
+ else if ( this->compare(*mid, *end) < 0 )
+ pivot = end;
+ else
+ pivot = mid;
+
+ return pivot;
+}
+
+template <class T, class Compare> T *QuickSort<T,Compare>::
+ partition(T *start, T *end)
+{
+ /* Use the median of start, middle, end as the pivot. First save
+ * it off then move the last element to the free spot. */
+ char pcPivot[sizeof(T)];
+ T *pivot = median(start, end);
+
+ memcpy( pcPivot, pivot, sizeof(T) );
+ if ( pivot != end )
+ memcpy( pivot, end, sizeof(T) );
+
+ T *first = start-1;
+ T *last = end;
+ pivot = (T*) pcPivot;
+
+ /* Shuffle element to the correct side of the pivot, ending
+ * up with the free spot where the pivot will go. */
+ while ( true ) {
+ /* Throw one element ahead to the free spot at last. */
+ while ( true ) {
+ first += 1;
+ if ( first == last )
+ goto done;
+ if ( this->compare( *first, *pivot ) > 0 ) {
+ memcpy(last, first, sizeof(T));
+ break;
+ }
+ }
+
+ /* Throw one element back to the free spot at first. */
+ while ( true ) {
+ last -= 1;
+ if ( last == first )
+ goto done;
+ if ( this->compare( *last, *pivot ) < 0 ) {
+ memcpy(first, last, sizeof(T));
+ break;
+ }
+ }
+ }
+done:
+ /* Put the pivot into the middle spot for it. */
+ memcpy( first, pivot, sizeof(T) );
+ return first;
+}
+
+
+template< class T, class Compare> void QuickSort<T,Compare>::
+ doSort(T *start, T *end)
+{
+ long len = end - start + 1;
+ if ( len > _QS_INSERTION_THRESH ) {
+ /* Use quicksort. */
+ T *pivot = partition( start, end );
+ doSort(start, pivot-1);
+ doSort(pivot+1, end);
+ }
+ else if ( len > 1 ) {
+ /* Array is small, use insertion sort. */
+ InsertSort<T, Compare>::sort( start, len );
+ }
+}
+
+/**
+ * \brief Quick sort an array of data.
+ */
+template< class T, class Compare>
+ void QuickSort<T,Compare>::sort(T *data, long len)
+{
+ /* Call recursive worker. */
+ doSort(data, data+len-1);
+}
+
+#ifdef AAPL_NAMESPACE
+}
+#endif
+
+#endif /* _AAPL_QUICKSORT_H */
diff --git a/src/aapl/resize.h b/src/aapl/resize.h
new file mode 100644
index 00000000..6cc1090f
--- /dev/null
+++ b/src/aapl/resize.h
@@ -0,0 +1,345 @@
+/*
+ * Copyright 2002 Adrian Thurston <thurston@colm.net>
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to
+ * deal in the Software without restriction, including without limitation the
+ * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
+ * sell copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+#ifndef _AAPL_RESIZE_H
+#define _AAPL_RESIZE_H
+
+#include <assert.h>
+
+#ifdef AAPL_NAMESPACE
+namespace Aapl {
+#endif
+
+/* This step is expressed in units of T. Changing this requires changes to
+ * docs in ResizeLin constructor. */
+#define LIN_DEFAULT_STEP 256
+
+/*
+ * Resizing macros giving different resize methods.
+ */
+
+/* If needed is greater than existing, give twice needed. */
+#define EXPN_UP( existing, needed ) \
+ needed > existing ? (needed<<1) : existing
+
+/* If needed is less than 1 quarter existing, give twice needed. */
+#define EXPN_DOWN( existing, needed ) \
+ needed < (existing>>2) ? (needed<<1) : existing
+
+/* If needed is greater than existing, give needed plus step. */
+#define LIN_UP( existing, needed ) \
+ needed > existing ? (needed+step) : existing
+
+/* If needed is less than existing - 2 * step then give needed plus step. */
+#define LIN_DOWN( existing, needed ) \
+ needed < (existing-(step<<1)) ? (needed+step) : existing
+
+/* Return existing. */
+#define CONST_UP( existing, needed ) existing
+
+/* Return existing. */
+#define CONST_DOWN( existing, needed ) existing
+
+/**
+ * \addtogroup vector
+ * @{
+ */
+
+/** \class ResizeLin
+ * \brief Linear table resizer.
+ *
+ * When an up resize or a down resize is needed, ResizeLin allocates the space
+ * needed plus some user defined step. The result is that when growing the
+ * vector in a linear fashion, the number of resizes is also linear.
+ *
+ * If only up resizing is done, then there will never be more than step unused
+ * spaces in the vector. If down resizing is done as well, there will never be
+ * more than 2*step unused spaces in the vector. The up resizing and down
+ * resizing policies are offset to improve performance when repeatedly
+ * inserting and removing a small number of elements relative to the step.
+ * This scheme guarantees that repetitive inserting and removing of a small
+ * number of elements will never result in repetative reallocation.
+ *
+ * The vectors pass sizes to the resizer in units of T, so the step gets
+ * interpreted as units of T.
+ */
+
+/*@}*/
+
+/* Linear resizing. */
+class ResizeLin
+{
+protected:
+ /**
+ * \brief Default constructor.
+ *
+ * Intializes resize step to 256 units of the table type T.
+ */
+ ResizeLin() : step(LIN_DEFAULT_STEP) { }
+
+ /**
+ * \brief Determine the new table size when up resizing.
+ *
+ * If the existing size is insufficient for the space needed, then allocate
+ * the space needed plus the step. The step is in units of T.
+ */
+ inline long upResize( long existing, long needed )
+ { return LIN_UP(existing, needed); }
+
+ /**
+ * \brief Determine the new table size when down resizing.
+ *
+ * If space needed is less than the existing - 2*step, then allocate the
+ * space needed space plus the step. The step is in units of T.
+ */
+ inline long downResize( long existing, long needed )
+ { return LIN_DOWN(existing, needed); }
+
+public:
+ /**
+ * \brief Step for linear resize.
+ *
+ * Amount of extra space in units of T added each time a resize must take
+ * place. This may be changed at any time. The step should be >= 0.
+ */
+ long step;
+};
+
+/**
+ * \addtogroup vector
+ * @{
+ */
+
+/** \class ResizeCtLin
+ * \brief Linear table resizer with compile time step.
+ *
+ * When an up resize or a down resize is needed, ResizeCtLin allocates the
+ * space needed plus some compile time defined step. The result is that when
+ * growing the vector in a linear fashion, the number of resizes is also
+ * linear.
+ *
+ * If only up resizing is done, then there will never be more than step unused
+ * spaces in the vector. If down resizing is done as well, there will never be
+ * more than 2*step unused spaces in the vector. The up resizing and down
+ * resizing policies are offset to improve performance when repeatedly
+ * inserting and removing a small number of elements relative to the step.
+ * This scheme guarantees that repetitive inserting and removing of a small
+ * number of elements will never result in repetative reallocation.
+ *
+ * The vectors pass sizes to the resizer in units of T, so the step gets
+ * interpreted as units of T.
+ */
+
+/*@}*/
+
+/* Linear resizing. */
+template <long step> class ResizeCtLin
+{
+protected:
+ /**
+ * \brief Determine the new table size when up resizing.
+ *
+ * If the existing size is insufficient for the space needed, then allocate
+ * the space needed plus the step. The step is in units of T.
+ */
+ inline long upResize( long existing, long needed )
+ { return LIN_UP(existing, needed); }
+
+ /**
+ * \brief Determine the new table size when down resizing.
+ *
+ * If space needed is less than the existing - 2*step, then allocate the
+ * space needed space plus the step. The step is in units of T.
+ */
+ inline long downResize( long existing, long needed )
+ { return LIN_DOWN(existing, needed); }
+};
+
+/**
+ * \addtogroup vector
+ * @{
+ */
+
+/** \class ResizeConst
+ * \brief Constant table resizer.
+ *
+ * When an up resize is needed the existing size is always used. ResizeConst
+ * does not allow dynamic resizing. To use ResizeConst, the vector needs to be
+ * constructed with and initial allocation amount otherwise it will be
+ * unusable.
+ */
+
+/*@}*/
+
+/* Constant table resizing. */
+class ResizeConst
+{
+protected:
+ /* Assert don't need more than exists. Return existing. */
+ static inline long upResize( long existing, long needed );
+
+ /**
+ * \brief Determine the new table size when down resizing.
+ *
+ * Always returns the existing table size.
+ */
+ static inline long downResize( long existing, long needed )
+ { return CONST_DOWN(existing, needed); }
+};
+
+/**
+ * \brief Determine the new table size when up resizing.
+ *
+ * If the existing size is insufficient for the space needed, then an assertion
+ * will fail. Otherwise returns the existing size.
+ */
+inline long ResizeConst::upResize( long existing, long needed )
+{
+ assert( needed <= existing );
+ return CONST_UP(existing, needed);
+}
+
+/**
+ * \addtogroup vector
+ * @{
+ */
+
+/** \class ResizeRunTime
+ * \brief Run time settable table resizer.
+ *
+ * ResizeRunTime can have it's up and down resizing policies set at run time.
+ * Both up and down policies can be set independently to one of Exponential,
+ * Linear, or Constant. See the documentation for ResizeExpn, ResizeLin, and
+ * ResizeConst for the details of the resizing policies.
+ *
+ * The policies may be changed at any time. The default policies are
+ * both Exponential.
+ */
+
+/*@}*/
+
+/* Run time resizing. */
+class ResizeRunTime
+{
+protected:
+ /**
+ * \brief Default constuctor.
+ *
+ * The up and down resizing it initialized to Exponetial. The step
+ * defaults to 256 units of T.
+ */
+ inline ResizeRunTime();
+
+ /**
+ * \brief Resizing policies.
+ */
+ enum ResizeType {
+ Exponential, /*!< Exponential resizing. */
+ Linear, /*!< Linear resizing. */
+ Constant /*!< Constant table size. */
+ };
+
+ inline long upResize( long existing, long needed );
+ inline long downResize( long existing, long needed );
+
+public:
+ /**
+ * \brief Step for linear resize.
+ *
+ * Amount of extra space in units of T added each time a resize must take
+ * place. This may be changed at any time. The step should be >= 0.
+ */
+ long step;
+
+ /**
+ * \brief Up resizing policy.
+ */
+ ResizeType upResizeType;
+
+ /**
+ * \brief Down resizing policy.
+ */
+ ResizeType downResizeType;
+};
+
+inline ResizeRunTime::ResizeRunTime()
+:
+ step( LIN_DEFAULT_STEP ),
+ upResizeType( Exponential ),
+ downResizeType( Exponential )
+{
+}
+
+/**
+ * \brief Determine the new table size when up resizing.
+ *
+ * Type of up resizing is determined by upResizeType. Exponential, Linear and
+ * Constant resizing is the same as that of ResizeExpn, ResizeLin and
+ * ResizeConst.
+ */
+inline long ResizeRunTime::upResize( long existing, long needed )
+{
+ switch ( upResizeType ) {
+ case Exponential:
+ return EXPN_UP(existing, needed);
+ case Linear:
+ return LIN_UP(existing, needed);
+ case Constant:
+ assert( needed <= existing );
+ return CONST_UP(existing, needed);
+ }
+ return 0;
+};
+
+/**
+ * \brief Determine the new table size when down resizing.
+ *
+ * Type of down resizing is determined by downResiizeType. Exponential, Linear
+ * and Constant resizing is the same as that of ResizeExpn, ResizeLin and
+ * ResizeConst.
+ */
+inline long ResizeRunTime::downResize( long existing, long needed )
+{
+ switch ( downResizeType ) {
+ case Exponential:
+ return EXPN_DOWN(existing, needed);
+ case Linear:
+ return LIN_DOWN(existing, needed);
+ case Constant:
+ return CONST_DOWN(existing, needed);
+ }
+ return 0;
+}
+
+/* Don't need these anymore. */
+#undef EXPN_UP
+#undef EXPN_DOWN
+#undef LIN_UP
+#undef LIN_DOWN
+#undef CONST_UP
+#undef CONST_DOWN
+
+#ifdef AAPL_NAMESPACE
+}
+#endif
+
+#endif /* _AAPL_RESIZE_H */
diff --git a/src/aapl/rope.h b/src/aapl/rope.h
new file mode 100644
index 00000000..7a5e7b58
--- /dev/null
+++ b/src/aapl/rope.h
@@ -0,0 +1,237 @@
+/*
+ * Copyright 2016 Adrian Thurston <thurston@colm.net>
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to
+ * deal in the Software without restriction, including without limitation the
+ * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
+ * sell copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+#ifndef _AAPL_ROPE_H
+#define _AAPL_ROPE_H
+
+#include <string.h>
+#include <iostream>
+#include <stdio.h>
+
+struct RopeBlock
+{
+ static const int BLOCK_SZ = 8192;
+
+ RopeBlock()
+ :
+ size(BLOCK_SZ),
+ hoff(0),
+ toff(0)
+ {
+ }
+
+ int size;
+ int hoff;
+ int toff;
+ RopeBlock *next;
+};
+
+struct Rope
+{
+ Rope()
+ :
+ hblk(0),
+ tblk(0),
+ ropeLen(0)
+ {
+ }
+
+ /* Write to the tail block, at tail offset. */
+ RopeBlock *hblk;
+ RopeBlock *tblk;
+
+ /* Number of bytes in rope. */
+ int ropeLen;
+
+ RopeBlock *allocateBlock( int supporting )
+ {
+ int size = ( supporting > RopeBlock::BLOCK_SZ ) ? supporting : RopeBlock::BLOCK_SZ;
+ char *bd = new char[sizeof(RopeBlock) + size];
+ RopeBlock *block = (RopeBlock*) bd;
+ block->size = size;
+ block->hoff = 0;
+ block->toff = 0;
+ block->next = 0;
+ return block;
+ }
+
+ char *data( RopeBlock *rb )
+ { return (char*)rb + sizeof( RopeBlock ) + rb->hoff; }
+
+ char *writeTo( RopeBlock *rb )
+ { return (char*)rb + sizeof( RopeBlock ) + rb->toff; }
+
+ int length( RopeBlock *rb )
+ { return rb->toff - rb->hoff; }
+
+ int length()
+ { return ropeLen; }
+
+ int available( RopeBlock *rb )
+ { return rb->size - rb->toff; }
+
+ char *append( const char *src, int len )
+ {
+ if ( tblk == 0 ) {
+ /* There are no blocks. */
+ hblk = tblk = allocateBlock( len );
+ }
+ else {
+ int avail = available( tblk );
+
+ /* Move to the next block? */
+ if ( len > avail ) {
+ RopeBlock *block = allocateBlock( len );
+ tblk->next = block;
+ tblk = block;
+ }
+ }
+
+ char *ret = writeTo(tblk);
+ tblk->toff += len;
+ ropeLen += len;
+
+ if ( src != 0 )
+ memcpy( ret, src, len );
+ return ret;
+ }
+
+ char *appendBlock( int len )
+ {
+ if ( tblk == 0 ) {
+ /* There are no blocks. */
+ hblk = tblk = allocateBlock( len );
+ }
+ else {
+ RopeBlock *block = allocateBlock( len );
+ tblk->next = block;
+ tblk = block;
+ }
+
+ char *ret = writeTo(tblk);
+ tblk->toff += len;
+ ropeLen += len;
+ return ret;
+ }
+
+ /* Transfer data from other. Leaves it empty. */
+ void append( Rope &other )
+ {
+ if ( hblk == 0 ) {
+ transfer( other );
+ }
+ else if ( other.hblk == 0 ) {
+ /* nothing to do, other list empty. */
+ }
+ else {
+ tblk->next = other.hblk;
+ tblk = other.tblk;
+ ropeLen += other.ropeLen;
+ }
+
+ other.abandon();
+ }
+
+ void empty()
+ {
+ RopeBlock *blk = hblk;
+ while ( blk != 0 ) {
+ RopeBlock *next = blk->next;
+ delete[] (char*)blk;
+ blk = next;
+ }
+
+ hblk = 0;
+ tblk = 0;
+ ropeLen = 0;
+ }
+
+ void abandon()
+ {
+ hblk = 0;
+ tblk = 0;
+ ropeLen = 0;
+ }
+
+ void transfer( Rope &from )
+ {
+ empty();
+
+ this->hblk = from.hblk;
+ this->tblk = from.tblk;
+ this->ropeLen = from.ropeLen;
+
+ from.hblk = from.tblk = 0;
+ from.ropeLen = 0;
+ }
+};
+
+
+/*
+ * StringStream for appending to streams with an ostream.
+ */
+struct RopeOutBuf
+:
+ public std::streambuf
+{
+ RopeOutBuf( Rope &r )
+ :
+ r(r)
+ {
+ }
+
+ int_type overflow( int_type c )
+ {
+ if ( c != EOF ) {
+ char z = c;
+ r.append( &z, 1 );
+ }
+ return c;
+ }
+
+ std::streamsize xsputn( const char *data, std::streamsize num )
+ {
+ r.append( data, num );
+ return num;
+ }
+
+ Rope &r;
+};
+
+struct RopeStream
+:
+ public std::ostream
+{
+ RopeStream( Rope &r )
+ :
+ std::ostream( 0 ),
+ buf( r )
+ {
+ rdbuf( &buf );
+ }
+
+ RopeOutBuf buf;
+};
+
+
+#endif
+
diff --git a/src/aapl/sbstmap.h b/src/aapl/sbstmap.h
new file mode 100644
index 00000000..3e159ab2
--- /dev/null
+++ b/src/aapl/sbstmap.h
@@ -0,0 +1,122 @@
+/*
+ * Copyright 2002 Adrian Thurston <thurston@colm.net>
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to
+ * deal in the Software without restriction, including without limitation the
+ * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
+ * sell copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+#ifndef _AAPL_SBSTMAP_H
+#define _AAPL_SBSTMAP_H
+
+#include "compare.h"
+#include "svector.h"
+
+#ifdef AAPL_NAMESPACE
+namespace Aapl {
+#endif
+
+/**
+ * \brief Element for BstMap.
+ *
+ * Stores the key and value pair.
+ */
+template <class Key, class Value> struct SBstMapEl
+{
+ SBstMapEl() {}
+ SBstMapEl(const Key &key) : key(key) {}
+ SBstMapEl(const Key &key, const Value &val) : key(key), value(val) {}
+
+ /** \brief The key */
+ Key key;
+
+ /** \brief The value. */
+ Value value;
+};
+
+#ifdef AAPL_NAMESPACE
+}
+#endif
+
+/**
+ * \addtogroup bst
+ * @{
+ */
+
+/**
+ * \class SBstMap
+ * \brief Copy-on-write binary search table for key and value pairs.
+ *
+ * This is a map style binary search table that employs the copy-on-write
+ * mechanism for table data. BstMap stores key and value pairs in each
+ * element. The key and value can be any type. A compare class for the key
+ * must be supplied.
+ */
+
+/*@}*/
+
+#define BST_TEMPL_DECLARE class Key, class Value, \
+ class Compare = CmpOrd<Key>, class Resize = ResizeExpn
+#define BST_TEMPL_DEF class Key, class Value, class Compare, class Resize
+#define BST_TEMPL_USE Key, Value, Compare, Resize
+#define GET_KEY(el) ((el).key)
+#define BstTable SBstMap
+#define Vector SVector
+#define Table STable
+#define Element SBstMapEl<Key, Value>
+#define BSTMAP
+#define SHARED_BST
+
+#include "bstcommon.h"
+
+#undef BST_TEMPL_DECLARE
+#undef BST_TEMPL_DEF
+#undef BST_TEMPL_USE
+#undef GET_KEY
+#undef BstTable
+#undef Vector
+#undef Table
+#undef Element
+#undef BSTMAP
+#undef SHARED_BST
+
+/**
+ * \fn SBstMap::insert(const Key &key, BstMapEl<Key, Value> **lastFound)
+ * \brief Insert the given key.
+ *
+ * If the given key does not already exist in the table then a new element
+ * having key is inserted. They key copy constructor and value default
+ * constructor are used to place the pair in the table. If lastFound is given,
+ * it is set to the new entry created. If the insert fails then lastFound is
+ * set to the existing pair of the same key.
+ *
+ * \returns The new element created upon success, null upon failure.
+ */
+
+/**
+ * \fn SBstMap::insertMulti(const Key &key)
+ * \brief Insert the given key even if it exists already.
+ *
+ * If the key exists already then the new element having key is placed next
+ * to some other pair of the same key. InsertMulti cannot fail. The key copy
+ * constructor and the value default constructor are used to place the pair in
+ * the table.
+ *
+ * \returns The new element created.
+ */
+
+#endif /* _AAPL_SBSTMAP_H */
diff --git a/src/aapl/sbstset.h b/src/aapl/sbstset.h
new file mode 100644
index 00000000..947f78dc
--- /dev/null
+++ b/src/aapl/sbstset.h
@@ -0,0 +1,95 @@
+/*
+ * Copyright 2002 Adrian Thurston <thurston@colm.net>
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to
+ * deal in the Software without restriction, including without limitation the
+ * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
+ * sell copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+#ifndef _AAPL_SBSTSET_H
+#define _AAPL_SBSTSET_H
+
+/**
+ * \addtogroup bst
+ * @{
+ */
+
+/**
+ * \class SBstSet
+ * \brief Copy-on-write binary search table for types that are the key.
+ *
+ * This is a set style binary search table that employs the copy-on-write
+ * mechanism for storing table data. BstSet is suitable for types that
+ * comprise the entire key. Rather than look into the element to retrieve the
+ * key, the element is the key. A class that contains a comparison routine
+ * for the key must be given.
+ */
+
+/*@}*/
+
+#include "compare.h"
+#include "svector.h"
+
+#define BST_TEMPL_DECLARE class Key, class Compare = CmpOrd<Key>, \
+ class Resize = ResizeExpn
+#define BST_TEMPL_DEF class Key, class Compare, class Resize
+#define BST_TEMPL_USE Key, Compare, Resize
+#define GET_KEY(el) (el)
+#define BstTable SBstSet
+#define Vector SVector
+#define Table STable
+#define Element Key
+#define BSTSET
+#define SHARED_BST
+
+#include "bstcommon.h"
+
+#undef BST_TEMPL_DECLARE
+#undef BST_TEMPL_DEF
+#undef BST_TEMPL_USE
+#undef GET_KEY
+#undef BstTable
+#undef Vector
+#undef Table
+#undef Element
+#undef BSTSET
+#undef SHARED_BST
+
+/**
+ * \fn SBstSet::insert(const Key &key, Key **lastFound)
+ * \brief Insert the given key.
+ *
+ * If the given key does not already exist in the table then it is inserted.
+ * The key's copy constructor is used to place the item in the table. If
+ * lastFound is given, it is set to the new entry created. If the insert fails
+ * then lastFound is set to the existing key of the same value.
+ *
+ * \returns The new element created upon success, null upon failure.
+ */
+
+/**
+ * \fn SBstSet::insertMulti(const Key &key)
+ * \brief Insert the given key even if it exists already.
+ *
+ * If the key exists already then it is placed next to some other key of the
+ * same value. InsertMulti cannot fail. The key's copy constructor is used to
+ * place the item in the table.
+ *
+ * \returns The new element created.
+ */
+
+#endif /* _AAPL_SBSTSET_H */
diff --git a/src/aapl/sbsttable.h b/src/aapl/sbsttable.h
new file mode 100644
index 00000000..9cfed437
--- /dev/null
+++ b/src/aapl/sbsttable.h
@@ -0,0 +1,94 @@
+/*
+ * Copyright 2002 Adrian Thurston <thurston@colm.net>
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to
+ * deal in the Software without restriction, including without limitation the
+ * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
+ * sell copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+#ifndef _AAPL_SBSTTABLE_H
+#define _AAPL_SBSTTABLE_H
+
+#include "compare.h"
+#include "svector.h"
+
+/**
+ * \addtogroup bst
+ * @{
+ */
+
+/**
+ * \class SBstTable
+ * \brief Copy-on-write binary search table for structures that contain a key.
+ *
+ * This is a basic binary search table that employs a copy-on-write data
+ * storage mechanism. It can be used to contain a structure that has a key and
+ * possibly some data. The key should be a member of the element class and
+ * accessible with getKey(). A class containing the compare routine must be
+ * supplied.
+ */
+
+/*@}*/
+
+#define BST_TEMPL_DECLARE class Element, class Key, \
+ class Compare = CmpOrd<Key>, class Resize = ResizeExpn
+#define BST_TEMPL_DEF class Element, class Key, class Compare, class Resize
+#define BST_TEMPL_USE Element, Key, Compare, Resize
+#define GET_KEY(el) ((el).getKey())
+#define BstTable SBstTable
+#define Vector SVector
+#define Table STable
+#define BSTTABLE
+#define SHARED_BST
+
+#include "bstcommon.h"
+
+#undef BST_TEMPL_DECLARE
+#undef BST_TEMPL_DEF
+#undef BST_TEMPL_USE
+#undef GET_KEY
+#undef BstTable
+#undef Vector
+#undef Table
+#undef BSTTABLE
+#undef SHARED_BST
+
+/**
+ * \fn SBstTable::insert(const Key &key, Element **lastFound)
+ * \brief Insert a new element with the given key.
+ *
+ * If the given key does not already exist in the table a new element is
+ * inserted with the given key. A constructor taking only const Key& is used
+ * to initialize the new element. If lastFound is given, it is set to the new
+ * element created. If the insert fails then lastFound is set to the existing
+ * element with the same key.
+ *
+ * \returns The new element created upon success, null upon failure.
+ */
+
+/**
+ * \fn SBstTable::insertMulti(const Key &key)
+ * \brief Insert a new element even if the key exists already.
+ *
+ * If the key exists already then the new element is placed next to some
+ * element with the same key. InsertMulti cannot fail. A constructor taking
+ * only const Key& is used to initialize the new element.
+ *
+ * \returns The new element created.
+ */
+
+#endif /* _AAPL_SBSTTABLE_H */
diff --git a/src/aapl/svector.h b/src/aapl/svector.h
new file mode 100644
index 00000000..54db2007
--- /dev/null
+++ b/src/aapl/svector.h
@@ -0,0 +1,1351 @@
+/*
+ * Copyright 2002, 2006 Adrian Thurston <thurston@colm.net>
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to
+ * deal in the Software without restriction, including without limitation the
+ * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
+ * sell copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+#ifndef _AAPL_SVECTOR_H
+#define _AAPL_SVECTOR_H
+
+#include <new>
+#include <string.h>
+#include <stdlib.h>
+#include <assert.h>
+#include "table.h"
+
+#ifdef AAPL_NAMESPACE
+namespace Aapl {
+#endif
+
+/**
+ * \addtogroup vector
+ * @{
+ */
+
+/** \class SVector
+ * \brief Copy-on-write dynamic array.
+ *
+ * SVector is a variant of Vector that employs copy-on-write behaviour. The
+ * SVector copy constructor and = operator make shallow copies. If a vector
+ * that references shared data is modified with insert, replace, append,
+ * prepend, setAs or remove, a new copy is made so as not to interfere with
+ * the shared data. However, shared individual elements may be modified by
+ * bypassing the SVector interface.
+ *
+ * SVector is a dynamic array that can be used to contain complex data
+ * structures that have constructors and destructors as well as simple types
+ * such as integers and pointers.
+ *
+ * SVector supports inserting, overwriting, and removing single or multiple
+ * elements at once. Constructors and destructors are called wherever
+ * appropriate. For example, before an element is overwritten, it's
+ * destructor is called.
+ *
+ * SVector provides automatic resizing of allocated memory as needed and
+ * offers different allocation schemes for controlling how the automatic
+ * allocation is done. Two senses of the the length of the data is
+ * maintained: the amount of raw memory allocated to the vector and the number
+ * of actual elements in the vector. The various allocation schemes control
+ * how the allocated space is changed in relation to the number of elements in
+ * the vector.
+ */
+
+/*@}*/
+
+/* SVector */
+template < class T, class Resize = ResizeExpn > class SVector :
+ public STable<T>, public Resize
+{
+private:
+ typedef STable<T> BaseTable;
+
+public:
+ /**
+ * \brief Initialize an empty vector with no space allocated.
+ *
+ * If a linear resizer is used, the step defaults to 256 units of T. For a
+ * runtime vector both up and down allocation schemes default to
+ * Exponential.
+ */
+ SVector() { }
+
+ /**
+ * \brief Create a vector that contains an initial element.
+ *
+ * The vector becomes one element in length. The element's copy
+ * constructor is used to place the value in the vector.
+ */
+ SVector(const T &val) { setAs(&val, 1); }
+
+ /**
+ * \brief Create a vector that contains an array of elements.
+ *
+ * The vector becomes len elements in length. Copy constructors are used
+ * to place the new elements in the vector.
+ */
+ SVector(const T *val, long len) { setAs(val, len); }
+
+ /* Shallow copy. */
+ SVector( const SVector &v );
+
+ /**
+ * \brief Free all memory used by the vector.
+ *
+ * The vector is reset to zero elements. Destructors are called on all
+ * elements in the vector. The space allocated for the vector is freed.
+ */
+ ~SVector() { empty(); }
+
+ /* Delete all items. */
+ void empty();
+
+ /**
+ * \brief Deep copy another vector into this vector.
+ *
+ * Copies the entire contents of the other vector into this vector. Any
+ * existing contents are first deleted. Equivalent to setAs.
+ */
+ void deepCopy( const SVector &v ) { setAs(v.data, v.length()); }
+
+ /* Perform a shallow copy of another vector. */
+ SVector &operator=( const SVector &v );
+
+
+ /*@{*/
+ /**
+ * \brief Insert one element at position pos.
+ *
+ * Elements in the vector from pos onward are shifted one space to the
+ * right. The copy constructor is used to place the element into this
+ * vector. If pos is greater than the length of the vector then undefined
+ * behaviour results. If pos is negative then it is treated as an offset
+ * relative to the length of the vector.
+ */
+ void insert(long pos, const T &val) { insert(pos, &val, 1); }
+
+ /* Insert an array of values. */
+ void insert(long pos, const T *val, long len);
+
+ /**
+ * \brief Insert all the elements from another vector at position pos.
+ *
+ * Elements in this vector from pos onward are shifted v.length() spaces
+ * to the right. The element's copy constructor is used to copy the items
+ * into this vector. The other vector is left unchanged. If pos is off the
+ * end of the vector, then undefined behaviour results. If pos is negative
+ * then it is treated as an offset relative to the length of the vector.
+ * Equivalent to vector.insert(pos, other.data, other.length()).
+ */
+ void insert(long pos, const SVector &v) { insert(pos, v.data, v.length()); }
+
+ /* Insert len copies of val into the vector. */
+ void insertDup(long pos, const T &val, long len);
+
+ /**
+ * \brief Insert one new element using the default constrcutor.
+ *
+ * Elements in the vector from pos onward are shifted one space to the right.
+ * The default constructor is used to init the new element. If pos is greater
+ * than the length of the vector then undefined behaviour results. If pos is
+ * negative then it is treated as an offset relative to the length of the
+ * vector.
+ */
+ void insertNew(long pos) { insertNew(pos, 1); }
+
+ /* Insert len new items using default constructor. */
+ void insertNew(long pos, long len);
+ /*@}*/
+
+ /*@{*/
+ /**
+ * \brief Remove one element at position pos.
+ *
+ * The element's destructor is called. Elements to the right of pos are
+ * shifted one space to the left to take up the free space. If pos is greater
+ * than or equal to the length of the vector then undefined behavior results.
+ * If pos is negative then it is treated as an offset relative to the length
+ * of the vector.
+ */
+ void remove(long pos) { remove(pos, 1); }
+
+ /* Delete a number of elements. */
+ void remove(long pos, long len);
+ /*@}*/
+
+ /*@{*/
+ /**
+ * \brief Replace one element at position pos.
+ *
+ * If there is an existing element at position pos (if pos is less than the
+ * length of the vector) then its destructor is called before the space is
+ * used. The copy constructor is used to place the element into the vector.
+ * If pos is greater than the length of the vector then undefined behaviour
+ * results. If pos is negative then it is treated as an offset relative to
+ * the length of the vector.
+ */
+ void replace(long pos, const T &val) { replace(pos, &val, 1); }
+
+ /* Replace with an array of values. */
+ void replace(long pos, const T *val, long len);
+
+ /**
+ * \brief Replace at position pos with all the elements of another vector.
+ *
+ * Replace at position pos with all the elements of another vector. The other
+ * vector is left unchanged. If there are existing elements at the positions
+ * to be replaced, then destructors are called before the space is used. Copy
+ * constructors are used to place the elements into this vector. It is
+ * allowable for the pos and length of the other vector to specify a
+ * replacement that overwrites existing elements and creates new ones. If pos
+ * is greater than the length of the vector then undefined behaviour results.
+ * If pos is negative, then it is treated as an offset relative to the length
+ * of the vector.
+ */
+ void replace(long pos, const SVector &v) { replace(pos, v.data, v.length()); }
+
+ /* Replace len items with len copies of val. */
+ void replaceDup(long pos, const T &val, long len);
+
+ /**
+ * \brief Replace at position pos with one new element.
+ *
+ * If there is an existing element at the position to be replaced (pos is
+ * less than the length of the vector) then the element's destructor is
+ * called before the space is used. The default constructor is used to
+ * initialize the new element. If pos is greater than the length of the
+ * vector then undefined behaviour results. If pos is negative, then it is
+ * treated as an offset relative to the length of the vector.
+ */
+ void replaceNew(long pos) { replaceNew(pos, 1); }
+
+ /* Replace len items at pos with newly constructed objects. */
+ void replaceNew(long pos, long len);
+ /*@}*/
+
+ /*@{*/
+
+ /**
+ * \brief Set the contents of the vector to be val exactly.
+ *
+ * The vector becomes one element in length. Destructors are called on any
+ * existing elements in the vector. The element's copy constructor is used to
+ * place the val in the vector.
+ */
+ void setAs(const T &val) { setAs(&val, 1); }
+
+ /* Set to the contents of an array. */
+ void setAs(const T *val, long len);
+
+ /**
+ * \brief Set the vector to exactly the contents of another vector.
+ *
+ * The vector becomes v.length() elements in length. Destructors are called
+ * on any existing elements. Copy constructors are used to place the new
+ * elements in the vector.
+ */
+ void setAs(const SVector &v) { setAs(v.data, v.length()); }
+
+ /* Set as len copies of item. */
+ void setAsDup(const T &item, long len);
+
+ /**
+ * \brief Set the vector to exactly one new item.
+ *
+ * The vector becomes one element in length. Destructors are called on any
+ * existing elements in the vector. The default constructor is used to
+ * init the new item.
+ */
+ void setAsNew() { setAsNew(1); }
+
+ /* Set as newly constructed objects using the default constructor. */
+ void setAsNew(long len);
+ /*@}*/
+
+ /*@{*/
+ /**
+ * \brief Append one elment to the end of the vector.
+ *
+ * Copy constructor is used to place the element in the vector.
+ */
+ void append(const T &val) { replace(BaseTable::length(), &val, 1); }
+
+ /**
+ * \brief Append len elements to the end of the vector.
+ *
+ * Copy constructors are used to place the elements in the vector.
+ */
+ void append(const T *val, long len) { replace(BaseTable::length(), val, len); }
+
+ /**
+ * \brief Append the contents of another vector.
+ *
+ * The other vector is left unchanged. Copy constructors are used to place
+ * the elements in the vector.
+ */
+ void append(const SVector &v)
+ { replace(BaseTable::length(), v.data, v.length()); }
+
+ /**
+ * \brief Append len copies of item.
+ *
+ * The copy constructor is used to place the item in the vector.
+ */
+ void appendDup(const T &item, long len) { replaceDup(BaseTable::length(), item, len); }
+
+ /**
+ * \brief Append a single newly created item.
+ *
+ * The new element is initialized with the default constructor.
+ */
+ void appendNew() { replaceNew(BaseTable::length(), 1); }
+
+ /**
+ * \brief Append len newly created items.
+ *
+ * The new elements are initialized with the default constructor.
+ */
+ void appendNew(long len) { replaceNew(BaseTable::length(), len); }
+ /*@}*/
+
+
+ /*@{*/
+ /**
+ * \brief Prepend one elment to the front of the vector.
+ *
+ * Copy constructor is used to place the element in the vector.
+ */
+ void prepend(const T &val) { insert(0, &val, 1); }
+
+ /**
+ * \brief Prepend len elements to the front of the vector.
+ *
+ * Copy constructors are used to place the elements in the vector.
+ */
+ void prepend(const T *val, long len) { insert(0, val, len); }
+
+ /**
+ * \brief Prepend the contents of another vector.
+ *
+ * The other vector is left unchanged. Copy constructors are used to place
+ * the elements in the vector.
+ */
+ void prepend(const SVector &v) { insert(0, v.data, v.length()); }
+
+ /**
+ * \brief Prepend len copies of item.
+ *
+ * The copy constructor is used to place the item in the vector.
+ */
+ void prependDup(const T &item, long len) { insertDup(0, item, len); }
+
+ /**
+ * \brief Prepend a single newly created item.
+ *
+ * The new element is initialized with the default constructor.
+ */
+ void prependNew() { insertNew(0, 1); }
+
+ /**
+ * \brief Prepend len newly created items.
+ *
+ * The new elements are initialized with the default constructor.
+ */
+ void prependNew(long len) { insertNew(0, len); }
+ /*@}*/
+
+ /* Convenience access. */
+ T &operator[](int i) const { return BaseTable::data[i]; }
+ long size() const { return BaseTable::length(); }
+
+ /* Various classes for setting the iterator */
+ struct Iter;
+ struct IterFirst { IterFirst( const SVector &v ) : v(v) { } const SVector &v; };
+ struct IterLast { IterLast( const SVector &v ) : v(v) { } const SVector &v; };
+ struct IterNext { IterNext( const Iter &i ) : i(i) { } const Iter &i; };
+ struct IterPrev { IterPrev( const Iter &i ) : i(i) { } const Iter &i; };
+
+ /**
+ * \brief Shared Vector Iterator.
+ * \ingroup iterators
+ */
+ struct Iter
+ {
+ /* Construct, assign. */
+ Iter() : ptr(0), ptrBeg(0), ptrEnd(0) { }
+
+ /* Construct. */
+ Iter( const SVector &v );
+ Iter( const IterFirst &vf );
+ Iter( const IterLast &vl );
+ inline Iter( const IterNext &vn );
+ inline Iter( const IterPrev &vp );
+
+ /* Assign. */
+ Iter &operator=( const SVector &v );
+ Iter &operator=( const IterFirst &vf );
+ Iter &operator=( const IterLast &vl );
+ inline Iter &operator=( const IterNext &vf );
+ inline Iter &operator=( const IterPrev &vl );
+
+ /** \brief Less than end? */
+ bool lte() const { return ptr != ptrEnd; }
+
+ /** \brief At end? */
+ bool end() const { return ptr == ptrEnd; }
+
+ /** \brief Greater than beginning? */
+ bool gtb() const { return ptr != ptrBeg; }
+
+ /** \brief At beginning? */
+ bool beg() const { return ptr == ptrBeg; }
+
+ /** \brief At first element? */
+ bool first() const { return ptr == ptrBeg+1; }
+
+ /** \brief At last element? */
+ bool last() const { return ptr == ptrEnd-1; }
+
+ /* Return the position. */
+ long pos() const { return ptr - ptrBeg - 1; }
+ T &operator[](int i) const { return ptr[i]; }
+
+ /** \brief Implicit cast to T*. */
+ operator T*() const { return ptr; }
+
+ /** \brief Dereference operator returns T&. */
+ T &operator *() const { return *ptr; }
+
+ /** \brief Arrow operator returns T*. */
+ T *operator->() const { return ptr; }
+
+ /** \brief Move to next item. */
+ T *operator++() { return ++ptr; }
+
+ /** \brief Move to next item. */
+ T *operator++(int) { return ptr++; }
+
+ /** \brief Move to next item. */
+ T *increment() { return ++ptr; }
+
+ /** \brief Move to previous item. */
+ T *operator--() { return --ptr; }
+
+ /** \brief Move to previous item. */
+ T *operator--(int) { return ptr--; }
+
+ /** \brief Move to previous item. */
+ T *decrement() { return --ptr; }
+
+ /** \brief Return the next item. Does not modify this. */
+ inline IterNext next() const { return IterNext(*this); }
+
+ /** \brief Return the previous item. Does not modify this. */
+ inline IterPrev prev() const { return IterPrev(*this); }
+
+ /** \brief The iterator is simply a pointer. */
+ T *ptr;
+
+ /* For testing endpoints. */
+ T *ptrBeg, *ptrEnd;
+ };
+
+ /** \brief Return first element. */
+ IterFirst first() { return IterFirst( *this ); }
+
+ /** \brief Return last element. */
+ IterLast last() { return IterLast( *this ); }
+
+protected:
+ void makeRawSpaceFor(long pos, long len);
+
+ void setAsCommon(long len);
+ long replaceCommon(long pos, long len);
+ long insertCommon(long pos, long len);
+
+ void upResize(long len);
+ void upResizeDup(long len);
+ void upResizeFromEmpty(long len);
+ void downResize(long len);
+ void downResizeDup(long len);
+};
+
+/**
+ * \brief Perform a shallow copy of the vector.
+ *
+ * Takes a reference to the contents of the other vector.
+ */
+template <class T, class Resize> SVector<T, Resize>::
+ SVector(const SVector<T, Resize> &v)
+{
+ /* Take a reference to other, if any data is allocated. */
+ if ( v.data == 0 )
+ BaseTable::data = 0;
+ else {
+ /* Get the source header, up the refcount and ref it. */
+ STabHead *srcHead = ((STabHead*) v.data) - 1;
+ srcHead->refCount += 1;
+ BaseTable::data = (T*) (srcHead + 1);
+ }
+}
+
+/**
+ * \brief Shallow copy another vector into this vector.
+ *
+ * Takes a reference to the other vector. The contents of this vector are
+ * first emptied.
+ *
+ * \returns A reference to this.
+ */
+template <class T, class Resize> SVector<T, Resize> &
+ SVector<T, Resize>:: operator=( const SVector &v )
+{
+ /* First clean out the current contents. */
+ empty();
+
+ /* Take a reference to other, if any data is allocated. */
+ if ( v.data == 0 )
+ BaseTable::data = 0;
+ else {
+ /* Get the source header, up the refcount and ref it. */
+ STabHead *srcHead = ((STabHead*) v.data) - 1;
+ srcHead->refCount += 1;
+ BaseTable::data = (T*) (srcHead + 1);
+ }
+ return *this;
+}
+
+/* Init a vector iterator with just a vector. */
+template <class T, class Resize> SVector<T, Resize>::
+ Iter::Iter( const SVector &v )
+{
+ long length;
+ if ( v.data == 0 || (length=(((STabHead*)v.data)-1)->tabLen) == 0 )
+ ptr = ptrBeg = ptrEnd = 0;
+ else {
+ ptr = v.data;
+ ptrBeg = v.data-1;
+ ptrEnd = v.data+length;
+ }
+}
+
+/* Init a vector iterator with the first of a vector. */
+template <class T, class Resize> SVector<T, Resize>::
+ Iter::Iter( const IterFirst &vf )
+{
+ long length;
+ if ( vf.v.data == 0 || (length=(((STabHead*)vf.v.data)-1)->tabLen) == 0 )
+ ptr = ptrBeg = ptrEnd = 0;
+ else {
+ ptr = vf.v.data;
+ ptrBeg = vf.v.data-1;
+ ptrEnd = vf.v.data+length;
+ }
+}
+
+/* Init a vector iterator with the last of a vector. */
+template <class T, class Resize> SVector<T, Resize>::
+ Iter::Iter( const IterLast &vl )
+{
+ long length;
+ if ( vl.v.data == 0 || (length=(((STabHead*)vl.v.data)-1)->tabLen) == 0 )
+ ptr = ptrBeg = ptrEnd = 0;
+ else {
+ ptr = vl.v.data+length-1;
+ ptrBeg = vl.v.data-1;
+ ptrEnd = vl.v.data+length;
+ }
+}
+
+/* Init a vector iterator with the next of some other iterator. */
+template <class T, class Resize> SVector<T, Resize>::
+ Iter::Iter( const IterNext &vn )
+:
+ ptr(vn.i.ptr+1),
+ ptrBeg(vn.i.ptrBeg),
+ ptrEnd(vn.i.ptrEnd)
+{
+}
+
+/* Init a vector iterator with the prev of some other iterator. */
+template <class T, class Resize> SVector<T, Resize>::
+ Iter::Iter( const IterPrev &vp )
+:
+ ptr(vp.i.ptr-1),
+ ptrBeg(vp.i.ptrBeg),
+ ptrEnd(vp.i.ptrEnd)
+{
+}
+
+/* Set a vector iterator with some vector. */
+template <class T, class Resize> typename SVector<T, Resize>::Iter &
+ SVector<T, Resize>::Iter::operator=( const SVector &v )
+{
+ long length;
+ if ( v.data == 0 || (length=(((STabHead*)v.data)-1)->tabLen) == 0 )
+ ptr = ptrBeg = ptrEnd = 0;
+ else {
+ ptr = v.data;
+ ptrBeg = v.data-1;
+ ptrEnd = v.data+length;
+ }
+ return *this;
+}
+
+/* Set a vector iterator with the first element in a vector. */
+template <class T, class Resize> typename SVector<T, Resize>::Iter &
+ SVector<T, Resize>::Iter::operator=( const IterFirst &vf )
+{
+ long length;
+ if ( vf.v.data == 0 || (length=(((STabHead*)vf.v.data)-1)->tabLen) == 0 )
+ ptr = ptrBeg = ptrEnd = 0;
+ else {
+ ptr = vf.v.data;
+ ptrBeg = vf.v.data-1;
+ ptrEnd = vf.v.data+length;
+ }
+ return *this;
+}
+
+/* Set a vector iterator with the last element in a vector. */
+template <class T, class Resize> typename SVector<T, Resize>::Iter &
+ SVector<T, Resize>::Iter::operator=( const IterLast &vl )
+{
+ long length;
+ if ( vl.v.data == 0 || (length=(((STabHead*)vl.v.data)-1)->tabLen) == 0 )
+ ptr = ptrBeg = ptrEnd = 0;
+ else {
+ ptr = vl.v.data+length-1;
+ ptrBeg = vl.v.data-1;
+ ptrEnd = vl.v.data+length;
+ }
+ return *this;
+}
+
+/* Set a vector iterator with the next of some other iterator. */
+template <class T, class Resize> typename SVector<T, Resize>::Iter &
+ SVector<T, Resize>::Iter::operator=( const IterNext &vn )
+{
+ ptr = vn.i.ptr+1;
+ ptrBeg = vn.i.ptrBeg;
+ ptrEnd = vn.i.ptrEnd;
+ return *this;
+}
+
+/* Set a vector iterator with the prev of some other iterator. */
+template <class T, class Resize> typename SVector<T, Resize>::Iter &
+ SVector<T, Resize>::Iter::operator=( const IterPrev &vp )
+{
+ ptr = vp.i.ptr-1;
+ ptrBeg = vp.i.ptrBeg;
+ ptrEnd = vp.i.ptrEnd;
+ return *this;
+}
+
+/* Up resize the data for len elements using Resize::upResize to tell us the
+ * new length. Reads and writes allocLen. Does not read or write length.
+ * Assumes that there is some data allocated already. */
+template <class T, class Resize> void SVector<T, Resize>::
+ upResize(long len)
+{
+ /* Get the current header. */
+ STabHead *head = ((STabHead*)BaseTable::data) - 1;
+
+ /* Ask the resizer what the new length will be. */
+ long newLen = Resize::upResize(head->allocLen, len);
+
+ /* Did the data grow? */
+ if ( newLen > head->allocLen ) {
+ head->allocLen = newLen;
+
+ /* Table exists already, resize it up. */
+ head = (STabHead*) realloc( head, sizeof(STabHead) +
+ sizeof(T) * newLen );
+ if ( head == 0 )
+ throw std::bad_alloc();
+
+ /* Save the data pointer. */
+ BaseTable::data = (T*) (head + 1);
+ }
+}
+
+/* Allocates a new buffer for an up resize that requires a duplication of the
+ * data. Uses Resize::upResize to get the allocation length. Reads and writes
+ * allocLen. This upResize does write the new length. Assumes that there is
+ * some data allocated already. */
+template <class T, class Resize> void SVector<T, Resize>::
+ upResizeDup(long len)
+{
+ /* Get the current header. */
+ STabHead *head = ((STabHead*)BaseTable::data) - 1;
+
+ /* Ask the resizer what the new length will be. */
+ long newLen = Resize::upResize(head->allocLen, len);
+
+ /* Dereferencing the existing data, decrement the refcount. */
+ head->refCount -= 1;
+
+ /* Table exists already, resize it up. */
+ head = (STabHead*) malloc( sizeof(STabHead) + sizeof(T) * newLen );
+ if ( head == 0 )
+ throw std::bad_alloc();
+
+ head->refCount = 1;
+ head->allocLen = newLen;
+ head->tabLen = len;
+
+ /* Save the data pointer. */
+ BaseTable::data = (T*) (head + 1);
+}
+
+/* Up resize the data for len elements using Resize::upResize to tell us the
+ * new length. Reads and writes allocLen. This upresize DOES write length.
+ * Assumes that no data is allocated. */
+template <class T, class Resize> void SVector<T, Resize>::
+ upResizeFromEmpty(long len)
+{
+ /* There is no table yet. If the len is zero, then there is no need to
+ * create a table. */
+ if ( len > 0 ) {
+ /* Ask the resizer what the new length will be. */
+ long newLen = Resize::upResize(0, len);
+
+ /* If len is greater than zero then we are always allocating the table. */
+ STabHead *head = (STabHead*) malloc( sizeof(STabHead) +
+ sizeof(T) * newLen );
+ if ( head == 0 )
+ throw std::bad_alloc();
+
+ /* Set up the header and save the data pointer. Note that we set the
+ * length here. This differs from the other upResizes. */
+ head->refCount = 1;
+ head->allocLen = newLen;
+ head->tabLen = len;
+ BaseTable::data = (T*) (head + 1);
+ }
+}
+
+/* Down resize the data for len elements using Resize::downResize to determine
+ * the new length. Reads and writes allocLen. Does not read or write length. */
+template <class T, class Resize> void SVector<T, Resize>::
+ downResize(long len)
+{
+ /* If there is already no length, then there is nothing we can do. */
+ if ( BaseTable::data != 0 ) {
+ /* Get the current header. */
+ STabHead *head = ((STabHead*)BaseTable::data) - 1;
+
+ /* Ask the resizer what the new length will be. */
+ long newLen = Resize::downResize( head->allocLen, len );
+
+ /* Did the data shrink? */
+ if ( newLen < head->allocLen ) {
+ if ( newLen == 0 ) {
+ /* Simply free the data. */
+ free( head );
+ BaseTable::data = 0;
+ }
+ else {
+ /* Save the new allocated length. */
+ head->allocLen = newLen;
+
+ /* Not shrinking to size zero, realloc it to the smaller size. */
+ head = (STabHead*) realloc( head, sizeof(STabHead) +
+ sizeof(T) * newLen );
+ if ( head == 0 )
+ throw std::bad_alloc();
+
+ /* Save the new data ptr. */
+ BaseTable::data = (T*) (head + 1);
+ }
+ }
+ }
+}
+
+/* Allocate a new buffer for a down resize and duplication of the array. The
+ * new array will be len long and allocation size will be determined using
+ * Resize::downResize with the old array's allocLen. Does not actually copy
+ * any data. Reads and writes allocLen and writes the new len. */
+template <class T, class Resize> void SVector<T, Resize>::
+ downResizeDup(long len)
+{
+ /* If there is already no length, then there is nothing we can do. */
+ if ( BaseTable::data != 0 ) {
+ /* Get the current header. */
+ STabHead *head = ((STabHead*)BaseTable::data) - 1;
+
+ /* Ask the resizer what the new length will be. */
+ long newLen = Resize::downResize( head->allocLen, len );
+
+ /* Detaching from the existing head, decrement the refcount. */
+ head->refCount -= 1;
+
+ /* Not shrinking to size zero, malloc it to the smaller size. */
+ head = (STabHead*) malloc( sizeof(STabHead) + sizeof(T) * newLen );
+ if ( head == 0 )
+ throw std::bad_alloc();
+
+ /* Save the new allocated length. */
+ head->refCount = 1;
+ head->allocLen = newLen;
+ head->tabLen = len;
+
+ /* Save the data pointer. */
+ BaseTable::data = (T*) (head + 1);
+ }
+}
+
+/**
+ * \brief Free all memory used by the vector.
+ *
+ * The vector is reset to zero elements. Destructors are called on all
+ * elements in the vector. The space allocated for the vector is freed.
+ */
+template <class T, class Resize> void SVector<T, Resize>::
+ empty()
+{
+ if ( BaseTable::data != 0 ) {
+ /* Get the header and drop the refcount on the data. */
+ STabHead *head = ((STabHead*) BaseTable::data) - 1;
+ head->refCount -= 1;
+
+ /* If the refcount just went down to zero nobody else is referencing
+ * the data. */
+ if ( head->refCount == 0 ) {
+ /* Call All destructors. */
+ T *pos = BaseTable::data;
+ for ( long i = 0; i < head->tabLen; pos++, i++ )
+ pos->~T();
+
+ /* Free the data space. */
+ free( head );
+ }
+
+ /* Clear the pointer. */
+ BaseTable::data = 0;
+ }
+}
+
+/* Prepare for setting the contents of the vector to some array len long.
+ * Handles reusing the existing space, detaching from a common space or
+ * growing from zero length automatically. */
+template <class T, class Resize> void SVector<T, Resize>::
+ setAsCommon(long len)
+{
+ if ( BaseTable::data != 0 ) {
+ /* Get the header. */
+ STabHead *head = ((STabHead*)BaseTable::data) - 1;
+
+ /* If the refCount is one, then we can reuse the space. Otherwise we
+ * must detach from the referenced data create new space. */
+ if ( head->refCount == 1 ) {
+ /* Call All destructors. */
+ T *pos = BaseTable::data;
+ for ( long i = 0; i < head->tabLen; pos++, i++ )
+ pos->~T();
+
+ /* Adjust the allocated length. */
+ if ( len < head->tabLen )
+ downResize( len );
+ else if ( len > head->tabLen )
+ upResize( len );
+
+ if ( BaseTable::data != 0 ) {
+ /* Get the header again and set the length. */
+ head = ((STabHead*)BaseTable::data) - 1;
+ head->tabLen = len;
+ }
+ }
+ else {
+ /* Just detach from the data. */
+ head->refCount -= 1;
+ BaseTable::data = 0;
+
+ /* Make enough space. This will set the length. */
+ upResizeFromEmpty( len );
+ }
+ }
+ else {
+ /* The table is currently empty. Make enough space. This will set the
+ * length. */
+ upResizeFromEmpty( len );
+ }
+}
+
+/**
+ * \brief Set the contents of the vector to be len elements exactly.
+ *
+ * The vector becomes len elements in length. Destructors are called on any
+ * existing elements in the vector. Copy constructors are used to place the
+ * new elements in the vector.
+ */
+template <class T, class Resize> void SVector<T, Resize>::
+ setAs(const T *val, long len)
+{
+ /* Common stuff for setting the array to len long. */
+ setAsCommon( len );
+
+ /* Copy data in. */
+ T *dst = BaseTable::data;
+ const T *src = val;
+ for ( long i = 0; i < len; i++, dst++, src++ )
+ new(dst) T(*src);
+}
+
+
+/**
+ * \brief Set the vector to len copies of item.
+ *
+ * The vector becomes len elements in length. Destructors are called on any
+ * existing elements in the vector. The element's copy constructor is used to
+ * copy the item into the vector.
+ */
+template <class T, class Resize> void SVector<T, Resize>::
+ setAsDup(const T &item, long len)
+{
+ /* Do the common stuff for setting the array to len long. */
+ setAsCommon( len );
+
+ /* Copy item in one spot at a time. */
+ T *dst = BaseTable::data;
+ for ( long i = 0; i < len; i++, dst++ )
+ new(dst) T(item);
+}
+
+/**
+ * \brief Set the vector to exactly len new items.
+ *
+ * The vector becomes len elements in length. Destructors are called on any
+ * existing elements in the vector. Default constructors are used to init the
+ * new items.
+ */
+template <class T, class Resize> void SVector<T, Resize>::
+ setAsNew(long len)
+{
+ /* Do the common stuff for setting the array to len long. */
+ setAsCommon( len );
+
+ /* Create items using default constructor. */
+ T *dst = BaseTable::data;
+ for ( long i = 0; i < len; i++, dst++ )
+ new(dst) T();
+}
+
+/* Make space in vector for a replacement at pos of len items. Handles reusing
+ * existing space, detaching or growing from zero space. */
+template <class T, class Resize> long SVector<T, Resize>::
+ replaceCommon(long pos, long len)
+{
+ if ( BaseTable::data != 0 ) {
+ /* Get the header. */
+ STabHead *head = ((STabHead*)BaseTable::data) - 1;
+
+ /* If we are given a negative position to replace at then treat it as
+ * a position relative to the length. This doesn't have any meaning
+ * unless the length is at least one. */
+ if ( pos < 0 )
+ pos = head->tabLen + pos;
+
+ /* The end is the one past the last item that we want to write to. */
+ long i, endPos = pos + len;
+
+ if ( head->refCount == 1 ) {
+ /* We can reuse the space. Make sure we have enough space. */
+ if ( endPos > head->tabLen ) {
+ upResize( endPos );
+
+ /* Get the header again, whose addr may have changed after
+ * resizing. */
+ head = ((STabHead*)BaseTable::data) - 1;
+
+ /* Delete any objects we need to delete. */
+ T *item = BaseTable::data + pos;
+ for ( i = pos; i < head->tabLen; i++, item++ )
+ item->~T();
+
+ /* We are extending the vector, set the new data length. */
+ head->tabLen = endPos;
+ }
+ else {
+ /* Delete any objects we need to delete. */
+ T *item = BaseTable::data + pos;
+ for ( i = pos; i < endPos; i++, item++ )
+ item->~T();
+ }
+ }
+ else {
+ /* Use endPos to calc the end of the vector. */
+ long newLen = endPos;
+ if ( newLen < head->tabLen )
+ newLen = head->tabLen;
+
+ /* Duplicate and grow up to endPos. This will set the length. */
+ upResizeDup( newLen );
+
+ /* Copy from src up to pos. */
+ const T *src = (T*) (head + 1);
+ T *dst = BaseTable::data;
+ for ( i = 0; i < pos; i++, dst++, src++)
+ new(dst) T(*src);
+
+ /* Copy any items after the replace range. */
+ for ( i += len, src += len, dst += len;
+ i < head->tabLen; i++, dst++, src++ )
+ new(dst) T(*src);
+ }
+ }
+ else {
+ /* There is no data initially, must grow from zero. This will set the
+ * new length. */
+ upResizeFromEmpty( len );
+ }
+
+ return pos;
+}
+
+
+/**
+ * \brief Replace len elements at position pos.
+ *
+ * If there are existing elements at the positions to be replaced, then
+ * destructors are called before the space is used. Copy constructors are used
+ * to place the elements into the vector. It is allowable for the pos and
+ * length to specify a replacement that overwrites existing elements and
+ * creates new ones. If pos is greater than the length of the vector then
+ * undefined behaviour results. If pos is negative, then it is treated as an
+ * offset relative to the length of the vector.
+ */
+template <class T, class Resize> void SVector<T, Resize>::
+ replace(long pos, const T *val, long len)
+{
+ /* Common work for replacing in the vector. */
+ pos = replaceCommon( pos, len );
+
+ /* Copy data in using copy constructor. */
+ T *dst = BaseTable::data + pos;
+ const T *src = val;
+ for ( long i = 0; i < len; i++, dst++, src++ )
+ new(dst) T(*src);
+}
+
+/**
+ * \brief Replace at position pos with len copies of an item.
+ *
+ * If there are existing elements at the positions to be replaced, then
+ * destructors are called before the space is used. The copy constructor is
+ * used to place the element into this vector. It is allowable for the pos and
+ * length to specify a replacement that overwrites existing elements and
+ * creates new ones. If pos is greater than the length of the vector then
+ * undefined behaviour results. If pos is negative, then it is treated as an
+ * offset relative to the length of the vector.
+ */
+template <class T, class Resize> void SVector<T, Resize>::
+ replaceDup(long pos, const T &val, long len)
+{
+ /* Common replacement stuff. */
+ pos = replaceCommon( pos, len );
+
+ /* Copy data in using copy constructor. */
+ T *dst = BaseTable::data + pos;
+ for ( long i = 0; i < len; i++, dst++ )
+ new(dst) T(val);
+}
+
+/**
+ * \brief Replace at position pos with len new elements.
+ *
+ * If there are existing elements at the positions to be replaced, then
+ * destructors are called before the space is used. The default constructor is
+ * used to initialize the new elements. It is allowable for the pos and length
+ * to specify a replacement that overwrites existing elements and creates new
+ * ones. If pos is greater than the length of the vector then undefined
+ * behaviour results. If pos is negative, then it is treated as an offset
+ * relative to the length of the vector.
+ */
+template <class T, class Resize> void SVector<T, Resize>::
+ replaceNew(long pos, long len)
+{
+ /* Do the common replacement stuff. */
+ pos = replaceCommon( pos, len );
+
+ /* Copy data in using copy constructor. */
+ T *dst = BaseTable::data + pos;
+ for ( long i = 0; i < len; i++, dst++ )
+ new(dst) T();
+}
+
+/**
+ * \brief Remove len elements at position pos.
+ *
+ * Destructor is called on all elements removed. Elements to the right of pos
+ * are shifted len spaces to the left to take up the free space. If pos is
+ * greater than or equal to the length of the vector then undefined behavior
+ * results. If pos is negative then it is treated as an offset relative to the
+ * length of the vector.
+ */
+template <class T, class Resize> void SVector<T, Resize>::
+ remove(long pos, long len)
+{
+ /* If there is no data, we can't delete anything anyways. */
+ if ( BaseTable::data != 0 ) {
+ /* Get the header. */
+ STabHead *head = ((STabHead*)BaseTable::data) - 1;
+
+ /* If we are given a negative position to remove at then
+ * treat it as a position relative to the length. */
+ if ( pos < 0 )
+ pos = head->tabLen + pos;
+
+ /* The first position after the last item deleted. */
+ long endPos = pos + len;
+
+ /* The New data length. */
+ long i, newLen = head->tabLen - len;
+
+ if ( head->refCount == 1 ) {
+ /* We are the only ones using the data. We can reuse
+ * the existing space. */
+
+ /* The place in the data we are deleting at. */
+ T *dst = BaseTable::data + pos;
+
+ /* Call Destructors. */
+ T *item = BaseTable::data + pos;
+ for ( i = 0; i < len; i += 1, item += 1 )
+ item->~T();
+
+ /* Shift data over if necessary. */
+ long lenToSlideOver = head->tabLen - endPos;
+ if ( len > 0 && lenToSlideOver > 0 )
+ memmove(BaseTable::data + pos, dst + len, sizeof(T)*lenToSlideOver);
+
+ /* Shrink the data if necessary. */
+ downResize( newLen );
+
+ if ( BaseTable::data != 0 ) {
+ /* Get the header again (because of the resize) and set the
+ * new data length. */
+ head = ((STabHead*)BaseTable::data) - 1;
+ head->tabLen = newLen;
+ }
+ }
+ else {
+ /* Must detach from the common data. Just copy the non-deleted
+ * items from the common data. */
+
+ /* Duplicate and grow down to newLen. This will set the length. */
+ downResizeDup( newLen );
+
+ /* Copy over just the non-deleted parts. */
+ const T *src = (T*) (head + 1);
+ T *dst = BaseTable::data;
+ for ( i = 0; i < pos; i++, dst++, src++ )
+ new(dst) T(*src);
+
+ /* ... and the second half. */
+ for ( i += len, src += len; i < head->tabLen; i++, src++, dst++ )
+ new(dst) T(*src);
+ }
+ }
+}
+
+/* Shift over existing data. Handles reusing existing space, detaching or
+ * growing from zero space. */
+template <class T, class Resize> long SVector<T, Resize>::
+ insertCommon(long pos, long len)
+{
+ if ( BaseTable::data != 0 ) {
+ /* Get the header. */
+ STabHead *head = ((STabHead*)BaseTable::data) - 1;
+
+ /* If we are given a negative position to insert at then treat it as a
+ * position relative to the length. This only has meaning if there is
+ * existing data. */
+ if ( pos < 0 )
+ pos = head->tabLen + pos;
+
+ /* Calculate the new length. */
+ long i, newLen = head->tabLen + len;
+
+ if ( head->refCount == 1 ) {
+ /* Up resize, we are growing. */
+ upResize( newLen );
+
+ /* Get the header again, (the addr may have changed after
+ * resizing). */
+ head = ((STabHead*)BaseTable::data) - 1;
+
+ /* Shift over data at insert spot if needed. */
+ if ( len > 0 && pos < head->tabLen ) {
+ memmove( BaseTable::data + pos + len, BaseTable::data + pos,
+ sizeof(T)*(head->tabLen - pos) );
+ }
+
+ /* Grow the length by the len inserted. */
+ head->tabLen += len;
+ }
+ else {
+ /* Need to detach from the existing array. Copy over the other
+ * parts. This will set the length. */
+ upResizeDup( newLen );
+
+ /* Copy over the parts around the insert. */
+ const T *src = (T*) (head + 1);
+ T *dst = BaseTable::data;
+ for ( i = 0; i < pos; i++, dst++, src++ )
+ new(dst) T(*src);
+
+ /* ... and the second half. */
+ for ( dst += len; i < head->tabLen; i++, src++, dst++ )
+ new(dst) T(*src);
+ }
+ }
+ else {
+ /* There is no existing data. Start from zero. This will set the
+ * length. */
+ upResizeFromEmpty( len );
+ }
+
+ return pos;
+}
+
+
+/**
+ * \brief Insert len elements at position pos.
+ *
+ * Elements in the vector from pos onward are shifted len spaces to the right.
+ * The copy constructor is used to place the elements into this vector. If pos
+ * is greater than the length of the vector then undefined behaviour results.
+ * If pos is negative then it is treated as an offset relative to the length
+ * of the vector.
+ */
+template <class T, class Resize> void SVector<T, Resize>::
+ insert(long pos, const T *val, long len)
+{
+ /* Do the common insertion stuff. */
+ pos = insertCommon( pos, len );
+
+ /* Copy data in element by element. */
+ T *dst = BaseTable::data + pos;
+ const T *src = val;
+ for ( long i = 0; i < len; i++, dst++, src++ )
+ new(dst) T(*src);
+}
+
+/**
+ * \brief Insert len copies of item at position pos.
+ *
+ * Elements in the vector from pos onward are shifted len spaces to the right.
+ * The copy constructor is used to place the element into this vector. If pos
+ * is greater than the length of the vector then undefined behaviour results.
+ * If pos is negative then it is treated as an offset relative to the length
+ * of the vector.
+ */
+template <class T, class Resize> void SVector<T, Resize>::
+ insertDup(long pos, const T &item, long len)
+{
+ /* Do the common insertion stuff. */
+ pos = insertCommon( pos, len );
+
+ /* Copy the data item in one at a time. */
+ T *dst = BaseTable::data + pos;
+ for ( long i = 0; i < len; i++, dst++ )
+ new(dst) T(item);
+}
+
+
+/**
+ * \brief Insert len new elements using the default constructor.
+ *
+ * Elements in the vector from pos onward are shifted len spaces to the right.
+ * Default constructors are used to init the new elements. If pos is off the
+ * end of the vector then undefined behaviour results. If pos is negative then
+ * it is treated as an offset relative to the length of the vector.
+ */
+template <class T, class Resize> void SVector<T, Resize>::
+ insertNew(long pos, long len)
+{
+ /* Do the common insertion stuff. */
+ pos = insertCommon( pos, len );
+
+ /* Init new data with default constructors. */
+ T *dst = BaseTable::data + pos;
+ for ( long i = 0; i < len; i++, dst++ )
+ new(dst) T();
+}
+
+/* Makes space for len items, Does not init the items in any way. If pos is
+ * greater than the length of the vector then undefined behaviour results.
+ * Updates the length of the vector. */
+template <class T, class Resize> void SVector<T, Resize>::
+ makeRawSpaceFor(long pos, long len)
+{
+ if ( BaseTable::data != 0 ) {
+ /* Get the header. */
+ STabHead *head = ((STabHead*)BaseTable::data) - 1;
+
+ /* Calculate the new length. */
+ long i, newLen = head->tabLen + len;
+
+ if ( head->refCount == 1 ) {
+ /* Up resize, we are growing. */
+ upResize( newLen );
+
+ /* Get the header again, (the addr may have changed after
+ * resizing). */
+ head = ((STabHead*)BaseTable::data) - 1;
+
+ /* Shift over data at insert spot if needed. */
+ if ( len > 0 && pos < head->tabLen ) {
+ memmove( BaseTable::data + pos + len, BaseTable::data + pos,
+ sizeof(T)*(head->tabLen - pos) );
+ }
+
+ /* Grow the length by the len inserted. */
+ head->tabLen += len;
+ }
+ else {
+ /* Need to detach from the existing array. Copy over the other
+ * parts. This will set the length. */
+ upResizeDup( newLen );
+
+ /* Copy over the parts around the insert. */
+ const T *src = (T*) (head + 1);
+ T *dst = BaseTable::data;
+ for ( i = 0; i < pos; i++, dst++, src++ )
+ new(dst) T(*src);
+
+ /* ... and the second half. */
+ for ( dst += len; i < head->tabLen; i++, src++, dst++ )
+ new(dst) T(*src);
+ }
+ }
+ else {
+ /* There is no existing data. Start from zero. This will set the
+ * length. */
+ upResizeFromEmpty( len );
+ }
+}
+
+
+#ifdef AAPL_NAMESPACE
+}
+#endif
+
+
+#endif /* _AAPL_SVECTOR_H */
diff --git a/src/aapl/table.h b/src/aapl/table.h
new file mode 100644
index 00000000..303f473e
--- /dev/null
+++ b/src/aapl/table.h
@@ -0,0 +1,253 @@
+/*
+ * Copyright 2001, 2002 Adrian Thurston <thurston@colm.net>
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to
+ * deal in the Software without restriction, including without limitation the
+ * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
+ * sell copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+#ifndef _AAPL_TABLE_H
+#define _AAPL_TABLE_H
+
+#ifdef AAPL_NAMESPACE
+namespace Aapl {
+#endif
+
+/**
+ * \addtogroup vector
+ * @{
+ */
+
+/** \class Table
+ * \brief Base class for dynamic arrays.
+ *
+ * Table is used as the common data storage class for vectors. It does not
+ * provide any methods to operate on the data and as such it is not intended
+ * to be used directly. It exists so that algorithms that operatate on dynamic
+ * arrays can be written without knowing about the various vector classes that
+ * my exist.
+ */
+
+/*@}*/
+
+/* Table class. */
+template <class T> class Table
+{
+public:
+ /* Default Constructor. */
+ inline Table();
+
+ /**
+ * \brief Get the length of the vector.
+ *
+ * \returns the length of the vector.
+ */
+ long length() const
+ { return tabLen; }
+
+ /**
+ * \brief Table data.
+ *
+ * The pointer to the elements in the vector. Modifying the vector may
+ * cause this pointer to change.
+ */
+ T *data;
+
+ /**
+ * \brief Table length.
+ *
+ * The number of items of type T in the table.
+ */
+ long tabLen;
+
+ /**
+ * \brief Allocated length.
+ *
+ * The number of items for which there is room in the current allocation.
+ */
+ long allocLen;
+};
+
+/**
+ * \brief Default constructor
+ *
+ * Initialize table data to empty.
+ */
+template <class T> inline Table<T>::Table()
+:
+ data(0),
+ tabLen(0),
+ allocLen(0)
+{
+}
+
+/* Default shared table header class. */
+struct STabHead
+{
+ /**
+ * \brief Table length.
+ *
+ * The number of items of type T in the table.
+ */
+ long tabLen;
+
+ /**
+ * \brief Allocated length.
+ *
+ * The number of items for which there is room in the current allocation.
+ */
+ long allocLen;
+
+ /**
+ * \brief Ref Count.
+ *
+ * The number of shared vectors referencing this data.
+ */
+ long refCount;
+};
+
+/**
+ * \addtogroup vector
+ * @{
+ */
+
+/** \class STable
+ * \brief Base class for implicitly shared dynamic arrays.
+ *
+ * STable is used as the common data storage class for shared vectors. It does
+ * not provide any methods to operate on the data and as such it is not
+ * intended to be used directly. It exists so that algorithms that operatate
+ * on dynamic arrays can be written without knowing about the various shared
+ * vector classes that my exist.
+ */
+
+/*@}*/
+
+/* STable class. */
+template <class T> class STable
+{
+public:
+ /* Default Constructor. */
+ inline STable();
+
+ /**
+ * \brief Get the length of the shared vector.
+ *
+ * \returns the length of the shared vector.
+ */
+ long length() const
+ { return data == 0 ? 0 : (((STabHead*)data) - 1)->tabLen; }
+
+ /**
+ * \brief Get header of the shared vector.
+ *
+ * \returns the header of the shared vector.
+ */
+ STabHead *header() const
+ { return data == 0 ? 0 : (((STabHead*)data) - 1); }
+
+ /**
+ * \brief Table data.
+ *
+ * The pointer to the elements in the vector. The shared table header is
+ * located just behind the data. Modifying the vector may cause this
+ * pointer to change.
+ */
+ T *data;
+};
+
+/**
+ * \brief Default constructor
+ *
+ * Initialize shared table data to empty.
+ */
+template <class T> inline STable<T>::STable()
+:
+ data(0)
+{
+}
+
+/* If needed is greater than existing, give twice needed. */
+#define EXPN_UP( existing, needed ) \
+ needed > existing ? (needed<<1) : existing
+
+/* If needed is less than 1 quarter existing, give twice needed. */
+#define EXPN_DOWN( existing, needed ) \
+ needed < (existing>>2) ? (needed<<1) : existing
+
+/**
+ * \addtogroup vector
+ * @{
+ */
+
+/** \class ResizeExpn
+ * \brief Exponential table resizer.
+ *
+ * ResizeExpn is the default table resizer. When an up resize is needed, space
+ * is doubled. When a down resize is needed, space is halved. The result is
+ * that when growing the vector in a linear fashion, the number of resizes of
+ * the allocated space behaves logarithmically.
+ *
+ * If only up resizes are done, there will never be more than 2 times the
+ * needed space allocated. If down resizes are done as well, there will never
+ * be more than 4 times the needed space allocated. ResizeExpn uses this 50%
+ * usage policy on up resizing and 25% usage policy on down resizing to
+ * improve performance when repeatedly inserting and removing a small number
+ * of elements relative to the size of the array. This scheme guarantees that
+ * repetitive inserting and removing of a small number of elements will never
+ * result in repetative reallocation.
+ *
+ * The sizes passed to the resizer from the vectors are in units of T.
+ */
+
+/*@}*/
+
+/* Exponential resizer. */
+class ResizeExpn
+{
+protected:
+ /**
+ * \brief Determine the new table size when up resizing.
+ *
+ * If the existing size is insufficient for the space needed then allocate
+ * twice the space needed. Otherwise use the existing size.
+ *
+ * \returns The new table size.
+ */
+ static inline long upResize( long existing, long needed )
+ { return EXPN_UP( existing, needed ); }
+
+ /**
+ * \brief Determine the new table size when down resizing.
+ *
+ * If the space needed is less than one quarter of the existing size then
+ * allocate twice the space needed. Otherwise use the exitsing size.
+ *
+ * \returns The new table size.
+ */
+ static inline long downResize( long existing, long needed )
+ { return EXPN_DOWN( existing, needed ); }
+};
+
+#undef EXPN_UP
+#undef EXPN_DOWN
+
+#ifdef AAPL_NAMESPACE
+}
+#endif
+
+#endif /* _AAPL_TABLE_H */
diff --git a/src/aapl/vector.h b/src/aapl/vector.h
new file mode 100644
index 00000000..0ec385d5
--- /dev/null
+++ b/src/aapl/vector.h
@@ -0,0 +1,1190 @@
+/*
+ * Copyright 2002, 2006 Adrian Thurston <thurston@colm.net>
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to
+ * deal in the Software without restriction, including without limitation the
+ * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
+ * sell copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+#ifndef _AAPL_VECTOR_H
+#define _AAPL_VECTOR_H
+
+#include <new>
+#include <string.h>
+#include <stdlib.h>
+#include <assert.h>
+#include "table.h"
+
+#ifdef AAPL_NAMESPACE
+namespace Aapl {
+#endif
+
+/**
+ * \addtogroup vector
+ * @{
+ */
+
+/** \class Vector
+ * \brief Dynamic array.
+ *
+ * This is typical vector implementation. It is a dynamic array that can be
+ * used to contain complex data structures that have constructors and
+ * destructors as well as simple types such as integers and pointers.
+ *
+ * Vector supports inserting, overwriting, and removing single or multiple
+ * elements at once. Constructors and destructors are called wherever
+ * appropriate. For example, before an element is overwritten, it's
+ * destructor is called.
+ *
+ * Vector provides automatic resizing of allocated memory as needed and offers
+ * different allocation schemes for controlling how the automatic allocation
+ * is done. Two senses of the the length of the data is maintained: the
+ * amount of raw memory allocated to the vector and the number of actual
+ * elements in the vector. The various allocation schemes control how the
+ * allocated space is changed in relation to the number of elements in the
+ * vector.
+ *
+ * \include ex_vector.cpp
+ */
+
+/*@}*/
+
+template < class T, class Resize = ResizeExpn > class Vector
+ : public Table<T>, public Resize
+{
+private:
+ typedef Table<T> BaseTable;
+
+public:
+ /**
+ * \brief Initialize an empty vector with no space allocated.
+ *
+ * If a linear resizer is used, the step defaults to 256 units of T. For a
+ * runtime vector both up and down allocation schemes default to
+ * Exponential.
+ */
+ Vector() { }
+
+ /**
+ * \brief Create a vector that contains an initial element.
+ *
+ * The vector becomes one element in length. The element's copy
+ * constructor is used to place the value in the vector.
+ */
+ Vector(const T &val) { setAs(&val, 1); }
+
+ /**
+ * \brief Create a vector that contains an array of elements.
+ *
+ * The vector becomes len elements in length. Copy constructors are used
+ * to place the new elements in the vector.
+ */
+ Vector(const T *val, long len) { setAs(val, len); }
+
+ /* Deep copy. */
+ Vector( const Vector &v );
+
+ /* Free all mem used by the vector. */
+ ~Vector() { empty(); }
+
+ /* Delete all items. */
+ void empty();
+
+ /* Abandon the contents of the vector without deleteing. */
+ void abandon();
+
+ /* Transfers the elements of another vector into this vector. First emptys
+ * the current vector. */
+ void transfer( Vector &v );
+
+ /* Perform a deep copy of another vector into this vector. */
+ Vector &operator=( const Vector &v );
+
+ /* Stack operations. */
+ void push( const T &t ) { append( t ); }
+ void pop() { remove( BaseTable::tabLen - 1 ); }
+ T &top() { return BaseTable::data[BaseTable::tabLen - 1]; }
+
+ /*@{*/
+ /**
+ * \brief Insert one element at position pos.
+ *
+ * Elements in the vector from pos onward are shifted one space to the
+ * right. The copy constructor is used to place the element into this
+ * vector. If pos is greater than the length of the vector then undefined
+ * behaviour results. If pos is negative then it is treated as an offset
+ * relative to the length of the vector.
+ */
+ void insert(long pos, const T &val) { insert(pos, &val, 1); }
+
+ /* Insert an array of values. */
+ void insert(long pos, const T *val, long len);
+
+ /**
+ * \brief Insert all the elements from another vector at position pos.
+ *
+ * Elements in this vector from pos onward are shifted v.tabLen spaces to
+ * the right. The element's copy constructor is used to copy the items
+ * into this vector. The other vector is left unchanged. If pos is off the
+ * end of the vector, then undefined behaviour results. If pos is negative
+ * then it is treated as an offset relative to the length of the vector.
+ * Equivalent to vector.insert(pos, other.data, other.tabLen).
+ */
+ void insert(long pos, const Vector &v) { insert(pos, v.data, v.tabLen); }
+
+ /* Insert len copies of val into the vector. */
+ void insertDup(long pos, const T &val, long len);
+
+ /**
+ * \brief Insert one new element using the default constrcutor.
+ *
+ * Elements in the vector from pos onward are shifted one space to the
+ * right. The default constructor is used to init the new element. If pos
+ * is greater than the length of the vector then undefined behaviour
+ * results. If pos is negative then it is treated as an offset relative to
+ * the length of the vector.
+ */
+ void insertNew(long pos) { insertNew(pos, 1); }
+
+ /* Insert len new items using default constructor. */
+ void insertNew(long pos, long len);
+ /*@}*/
+
+ /*@{*/
+ /**
+ * \brief Remove one element at position pos.
+ *
+ * The element's destructor is called. Elements to the right of pos are
+ * shifted one space to the left to take up the free space. If pos is greater
+ * than or equal to the length of the vector then undefined behavior results.
+ * If pos is negative then it is treated as an offset relative to the length
+ * of the vector.
+ */
+ void remove(long pos) { remove(pos, 1); }
+
+ /* Delete a number of elements. */
+ void remove(long pos, long len);
+ /*@}*/
+
+ /*@{*/
+ /**
+ * \brief Replace one element at position pos.
+ *
+ * If there is an existing element at position pos (if pos is less than
+ * the length of the vector) then its destructor is called before the
+ * space is used. The copy constructor is used to place the element into
+ * the vector. If pos is greater than the length of the vector then
+ * undefined behaviour results. If pos is negative then it is treated as
+ * an offset relative to the length of the vector.
+ */
+ void replace(long pos, const T &val) { replace(pos, &val, 1); }
+
+ /* Replace with an array of values. */
+ void replace(long pos, const T *val, long len);
+
+ /**
+ * \brief Replace at position pos with all the elements of another vector.
+ *
+ * Replace at position pos with all the elements of another vector. The
+ * other vector is left unchanged. If there are existing elements at the
+ * positions to be replaced, then destructors are called before the space
+ * is used. Copy constructors are used to place the elements into this
+ * vector. It is allowable for the pos and length of the other vector to
+ * specify a replacement that overwrites existing elements and creates new
+ * ones. If pos is greater than the length of the vector then undefined
+ * behaviour results. If pos is negative, then it is treated as an offset
+ * relative to the length of the vector.
+ */
+ void replace(long pos, const Vector &v) { replace(pos, v.data, v.tabLen); }
+
+ /* Replace len items with len copies of val. */
+ void replaceDup(long pos, const T &val, long len);
+
+ /**
+ * \brief Replace at position pos with one new element.
+ *
+ * If there is an existing element at the position to be replaced (pos is
+ * less than the length of the vector) then the element's destructor is
+ * called before the space is used. The default constructor is used to
+ * initialize the new element. If pos is greater than the length of the
+ * vector then undefined behaviour results. If pos is negative, then it is
+ * treated as an offset relative to the length of the vector.
+ */
+ void replaceNew(long pos) { replaceNew(pos, 1); }
+
+ /* Replace len items at pos with newly constructed objects. */
+ void replaceNew(long pos, long len);
+ /*@}*/
+
+ /*@{*/
+ /**
+ * \brief Set the contents of the vector to be val exactly.
+ *
+ * The vector becomes one element in length. Destructors are called on any
+ * existing elements in the vector. The element's copy constructor is used
+ * to place the val in the vector.
+ */
+ void setAs(const T &val) { setAs(&val, 1); }
+
+ /* Set to the contents of an array. */
+ void setAs(const T *val, long len);
+
+ /**
+ * \brief Set the vector to exactly the contents of another vector.
+ *
+ * The vector becomes v.tabLen elements in length. Destructors are called
+ * on any existing elements. Copy constructors are used to place the new
+ * elements in the vector.
+ */
+ void setAs(const Vector &v) { setAs(v.data, v.tabLen); }
+
+ /* Set as len copies of item. */
+ void setAsDup(const T &item, long len);
+
+ /**
+ * \brief Set the vector to exactly one new item.
+ *
+ * The vector becomes one element in length. Destructors are called on any
+ * existing elements in the vector. The default constructor is used to
+ * init the new item.
+ */
+ void setAsNew() { setAsNew(1); }
+
+ /* Set as newly constructed objects using the default constructor. */
+ void setAsNew(long len);
+ /*@}*/
+
+ /*@{*/
+ /**
+ * \brief Append one elment to the end of the vector.
+ *
+ * Copy constructor is used to place the element in the vector.
+ */
+ void append(const T &val) { replace(BaseTable::tabLen, &val, 1); }
+
+ /**
+ * \brief Append len elements to the end of the vector.
+ *
+ * Copy constructors are used to place the elements in the vector.
+ */
+ void append(const T *val, long len) { replace(BaseTable::tabLen, val, len); }
+
+ /**
+ * \brief Append the contents of another vector.
+ *
+ * The other vector is left unchanged. Copy constructors are used to place the
+ * elements in the vector.
+ */
+ void append(const Vector &v) { replace(BaseTable::tabLen, v.data, v.tabLen); }
+
+ /**
+ * \brief Append len copies of item.
+ *
+ * The copy constructor is used to place the item in the vector.
+ */
+ void appendDup(const T &item, long len) { replaceDup(BaseTable::tabLen, item, len); }
+
+ /**
+ * \brief Append a single newly created item.
+ *
+ * The new element is initialized with the default constructor.
+ */
+ void appendNew() { replaceNew(BaseTable::tabLen, 1); }
+
+ /**
+ * \brief Append len newly created items.
+ *
+ * The new elements are initialized with the default constructor.
+ */
+ void appendNew(long len) { replaceNew(BaseTable::tabLen, len); }
+ /*@}*/
+
+ /*@{*/
+ /** \fn Vector::prepend(const T &val)
+ * \brief Prepend one elment to the front of the vector.
+ *
+ * Copy constructor is used to place the element in the vector.
+ */
+ void prepend(const T &val) { insert(0, &val, 1); }
+
+ /**
+ * \brief Prepend len elements to the front of the vector.
+ *
+ * Copy constructors are used to place the elements in the vector.
+ */
+ void prepend(const T *val, long len) { insert(0, val, len); }
+
+ /**
+ * \brief Prepend the contents of another vector.
+ *
+ * The other vector is left unchanged. Copy constructors are used to place the
+ * elements in the vector.
+ */
+ void prepend(const Vector &v) { insert(0, v.data, v.tabLen); }
+
+ /**
+ * \brief Prepend len copies of item.
+ *
+ * The copy constructor is used to place the item in the vector.
+ */
+ void prependDup(const T &item, long len) { insertDup(0, item, len); }
+
+ /**
+ * \brief Prepend a single newly created item.
+ *
+ * The new element is initialized with the default constructor.
+ */
+ void prependNew() { insertNew(0, 1); }
+
+ /**
+ * \brief Prepend len newly created items.
+ *
+ * The new elements are initialized with the default constructor.
+ */
+ void prependNew(long len) { insertNew(0, len); }
+ /*@}*/
+
+ /* Convenience access. */
+ T &operator[](int i) const { return BaseTable::data[i]; }
+ long size() const { return BaseTable::tabLen; }
+
+ /* Forward this so a ref can be used. */
+ struct Iter;
+
+ /* Various classes for setting the iterator */
+ struct IterFirst { IterFirst( const Vector &v ) : v(v) { } const Vector &v; };
+ struct IterLast { IterLast( const Vector &v ) : v(v) { } const Vector &v; };
+ struct IterNext { IterNext( const Iter &i ) : i(i) { } const Iter &i; };
+ struct IterPrev { IterPrev( const Iter &i ) : i(i) { } const Iter &i; };
+
+ /**
+ * \brief Vector Iterator.
+ * \ingroup iterators
+ */
+ struct Iter
+ {
+ /* Construct, assign. */
+ Iter() : ptr(0), ptrBeg(0), ptrEnd(0) { }
+
+ /* Construct. */
+ Iter( const Vector &v );
+ Iter( const IterFirst &vf );
+ Iter( const IterLast &vl );
+ inline Iter( const IterNext &vn );
+ inline Iter( const IterPrev &vp );
+
+ /* Assign. */
+ Iter &operator=( const Vector &v );
+ Iter &operator=( const IterFirst &vf );
+ Iter &operator=( const IterLast &vl );
+ inline Iter &operator=( const IterNext &vf );
+ inline Iter &operator=( const IterPrev &vl );
+
+ /** \brief Less than end? */
+ bool lte() const { return ptr != ptrEnd; }
+
+ /** \brief At end? */
+ bool end() const { return ptr == ptrEnd; }
+
+ /** \brief Greater than beginning? */
+ bool gtb() const { return ptr != ptrBeg; }
+
+ /** \brief At beginning? */
+ bool beg() const { return ptr == ptrBeg; }
+
+ /** \brief At first element? */
+ bool first() const { return ptr == ptrBeg+1; }
+
+ /** \brief At last element? */
+ bool last() const { return ptr == ptrEnd-1; }
+
+ /* Return the position. */
+ long pos() const { return ptr - ptrBeg - 1; }
+ T &operator[](int i) const { return ptr[i]; }
+
+ /** \brief Implicit cast to T*. */
+ operator T*() const { return ptr; }
+
+ /** \brief Dereference operator returns T&. */
+ T &operator *() const { return *ptr; }
+
+ /** \brief Arrow operator returns T*. */
+ T *operator->() const { return ptr; }
+
+ /** \brief Move to next item. */
+ T *operator++() { return ++ptr; }
+
+ /** \brief Move to next item. */
+ T *operator++(int) { return ptr++; }
+
+ /** \brief Move to next item. */
+ T *increment() { return ++ptr; }
+
+ /** \brief Move n items forward. */
+ T *operator+=(long n) { return ptr+=n; }
+
+ /** \brief Move to previous item. */
+ T *operator--() { return --ptr; }
+
+ /** \brief Move to previous item. */
+ T *operator--(int) { return ptr--; }
+
+ /** \brief Move to previous item. */
+ T *decrement() { return --ptr; }
+
+ /** \brief Move n items back. */
+ T *operator-=(long n) { return ptr-=n; }
+
+ /** \brief Return the next item. Does not modify this. */
+ inline IterNext next() const { return IterNext(*this); }
+
+ /** \brief Return the previous item. Does not modify this. */
+ inline IterPrev prev() const { return IterPrev(*this); }
+
+ /** \brief The iterator is simply a pointer. */
+ T *ptr;
+
+ /* For testing endpoints. */
+ T *ptrBeg, *ptrEnd;
+ };
+
+ /** \brief Return first element. */
+ IterFirst first() { return IterFirst( *this ); }
+
+ /** \brief Return last element. */
+ IterLast last() { return IterLast( *this ); }
+
+protected:
+ void makeRawSpaceFor(long pos, long len);
+
+ void upResize(long len);
+ void downResize(long len);
+};
+
+/* Init a vector iterator with just a vector. */
+template <class T, class Resize> Vector<T, Resize>::Iter::Iter( const Vector &v )
+{
+ if ( v.tabLen == 0 )
+ ptr = ptrBeg = ptrEnd = 0;
+ else {
+ ptr = v.data;
+ ptrBeg = v.data-1;
+ ptrEnd = v.data+v.tabLen;
+ }
+}
+
+/* Init a vector iterator with the first of a vector. */
+template <class T, class Resize> Vector<T, Resize>::Iter::Iter(
+ const IterFirst &vf )
+{
+ if ( vf.v.tabLen == 0 )
+ ptr = ptrBeg = ptrEnd = 0;
+ else {
+ ptr = vf.v.data;
+ ptrBeg = vf.v.data-1;
+ ptrEnd = vf.v.data+vf.v.tabLen;
+ }
+}
+
+/* Init a vector iterator with the last of a vector. */
+template <class T, class Resize> Vector<T, Resize>::Iter::Iter(
+ const IterLast &vl )
+{
+ if ( vl.v.tabLen == 0 )
+ ptr = ptrBeg = ptrEnd = 0;
+ else {
+ ptr = vl.v.data+vl.v.tabLen-1;
+ ptrBeg = vl.v.data-1;
+ ptrEnd = vl.v.data+vl.v.tabLen;
+ }
+}
+
+/* Init a vector iterator with the next of some other iterator. */
+template <class T, class Resize> Vector<T, Resize>::Iter::Iter(
+ const IterNext &vn )
+:
+ ptr(vn.i.ptr+1),
+ ptrBeg(vn.i.ptrBeg),
+ ptrEnd(vn.i.ptrEnd)
+{
+}
+
+/* Init a vector iterator with the prev of some other iterator. */
+template <class T, class Resize> Vector<T, Resize>::Iter::Iter(
+ const IterPrev &vp )
+:
+ ptr(vp.i.ptr-1),
+ ptrBeg(vp.i.ptrBeg),
+ ptrEnd(vp.i.ptrEnd)
+{
+}
+
+/* Set a vector iterator with some vector. */
+template <class T, class Resize> typename Vector<T, Resize>::Iter &
+ Vector<T, Resize>::Iter::operator=( const Vector &v )
+{
+ if ( v.tabLen == 0 )
+ ptr = ptrBeg = ptrEnd = 0;
+ else {
+ ptr = v.data;
+ ptrBeg = v.data-1;
+ ptrEnd = v.data+v.tabLen;
+ }
+ return *this;
+}
+
+/* Set a vector iterator with the first element in a vector. */
+template <class T, class Resize> typename Vector<T, Resize>::Iter &
+ Vector<T, Resize>::Iter::operator=( const IterFirst &vf )
+{
+ if ( vf.v.tabLen == 0 )
+ ptr = ptrBeg = ptrEnd = 0;
+ else {
+ ptr = vf.v.data;
+ ptrBeg = vf.v.data-1;
+ ptrEnd = vf.v.data+vf.v.tabLen;
+ }
+ return *this;
+}
+
+/* Set a vector iterator with the last element in a vector. */
+template <class T, class Resize> typename Vector<T, Resize>::Iter &
+ Vector<T, Resize>::Iter::operator=( const IterLast &vl )
+{
+ if ( vl.v.tabLen == 0 )
+ ptr = ptrBeg = ptrEnd = 0;
+ else {
+ ptr = vl.v.data+vl.v.tabLen-1;
+ ptrBeg = vl.v.data-1;
+ ptrEnd = vl.v.data+vl.v.tabLen;
+ }
+ return *this;
+}
+
+/* Set a vector iterator with the next of some other iterator. */
+template <class T, class Resize> typename Vector<T, Resize>::Iter &
+ Vector<T, Resize>::Iter::operator=( const IterNext &vn )
+{
+ ptr = vn.i.ptr+1;
+ ptrBeg = vn.i.ptrBeg;
+ ptrEnd = vn.i.ptrEnd;
+ return *this;
+}
+
+/* Set a vector iterator with the prev of some other iterator. */
+template <class T, class Resize> typename Vector<T, Resize>::Iter &
+ Vector<T, Resize>::Iter::operator=( const IterPrev &vp )
+{
+ ptr = vp.i.ptr-1;
+ ptrBeg = vp.i.ptrBeg;
+ ptrEnd = vp.i.ptrEnd;
+ return *this;
+}
+
+/**
+ * \brief Forget all elements in the vector.
+ *
+ * The contents of the vector are reset to null without without the space
+ * being freed.
+ */
+template<class T, class Resize> void Vector<T, Resize>::
+ abandon()
+{
+ BaseTable::data = 0;
+ BaseTable::tabLen = 0;
+ BaseTable::allocLen = 0;
+}
+
+/**
+ * \brief Transfer the contents of another vector into this vector.
+ *
+ * The dynamic array of the other vector is moved into this vector by
+ * reference. If this vector is non-empty then its contents are first deleted.
+ * Afterward the other vector will be empty.
+ */
+template<class T, class Resize> void Vector<T, Resize>::
+ transfer( Vector &v )
+{
+ empty();
+
+ BaseTable::data = v.data;
+ BaseTable::tabLen = v.tabLen;
+ BaseTable::allocLen = v.allocLen;
+
+ v.abandon();
+}
+
+/**
+ * \brief Deep copy another vector into this vector.
+ *
+ * Copies the entire contents of the other vector into this vector. Any
+ * existing contents are first deleted. Equivalent to setAs.
+ *
+ * \returns A reference to this.
+ */
+template<class T, class Resize> Vector<T, Resize> &Vector<T, Resize>::
+ operator=( const Vector &v )
+{
+ setAs(v.data, v.tabLen);
+ return *this;
+}
+
+/* Up resize the data for len elements using Resize::upResize to tell us the
+ * new tabLen. Reads and writes allocLen. Does not read or write tabLen. */
+template<class T, class Resize> void Vector<T, Resize>::
+ upResize(long len)
+{
+ /* Ask the resizer what the new tabLen will be. */
+ long newLen = Resize::upResize(BaseTable::allocLen, len);
+
+ /* Did the data grow? */
+ if ( newLen > BaseTable::allocLen ) {
+ BaseTable::allocLen = newLen;
+ if ( BaseTable::data != 0 ) {
+ /* Table exists already, resize it up. */
+ BaseTable::data = (T*) realloc( BaseTable::data, sizeof(T) * newLen );
+ if ( BaseTable::data == 0 )
+ throw std::bad_alloc();
+ }
+ else {
+ /* Create the data. */
+ BaseTable::data = (T*) malloc( sizeof(T) * newLen );
+ if ( BaseTable::data == 0 )
+ throw std::bad_alloc();
+ }
+ }
+}
+
+/* Down resize the data for len elements using Resize::downResize to determine
+ * the new tabLen. Reads and writes allocLen. Does not read or write tabLen. */
+template<class T, class Resize> void Vector<T, Resize>::
+ downResize(long len)
+{
+ /* Ask the resizer what the new tabLen will be. */
+ long newLen = Resize::downResize( BaseTable::allocLen, len );
+
+ /* Did the data shrink? */
+ if ( newLen < BaseTable::allocLen ) {
+ BaseTable::allocLen = newLen;
+ if ( newLen == 0 ) {
+ /* Simply free the data. */
+ free( BaseTable::data );
+ BaseTable::data = 0;
+ }
+ else {
+ /* Not shrinking to size zero, realloc it to the smaller size. */
+ BaseTable::data = (T*) realloc( BaseTable::data, sizeof(T) * newLen );
+ if ( BaseTable::data == 0 )
+ throw std::bad_alloc();
+ }
+ }
+}
+
+/**
+ * \brief Perform a deep copy of the vector.
+ *
+ * The contents of the other vector are copied into this vector. This vector
+ * gets the same allocation size as the other vector. All items are copied
+ * using the element's copy constructor.
+ */
+template<class T, class Resize> Vector<T, Resize>::
+ Vector(const Vector<T, Resize> &v)
+{
+ BaseTable::tabLen = v.tabLen;
+ BaseTable::allocLen = v.allocLen;
+
+ if ( BaseTable::allocLen > 0 ) {
+ /* Allocate needed space. */
+ BaseTable::data = (T*) malloc(sizeof(T) * BaseTable::allocLen);
+ if ( BaseTable::data == 0 )
+ throw std::bad_alloc();
+
+ /* If there are any items in the src data, copy them in. */
+ T *dst = BaseTable::data, *src = v.data;
+ for (long pos = 0; pos < BaseTable::tabLen; pos++, dst++, src++ )
+ new(dst) T(*src);
+ }
+ else {
+ /* Nothing allocated. */
+ BaseTable::data = 0;
+ }
+}
+
+/** \fn Vector::~Vector()
+ * \brief Free all memory used by the vector.
+ *
+ * The vector is reset to zero elements. Destructors are called on all
+ * elements in the vector. The space allocated for the vector is freed.
+ */
+
+
+/**
+ * \brief Free all memory used by the vector.
+ *
+ * The vector is reset to zero elements. Destructors are called on all
+ * elements in the vector. The space allocated for the vector is freed.
+ */
+template<class T, class Resize> void Vector<T, Resize>::
+ empty()
+{
+ if ( BaseTable::data != 0 ) {
+ /* Call All destructors. */
+ T *pos = BaseTable::data;
+ for ( long i = 0; i < BaseTable::tabLen; pos++, i++ )
+ pos->~T();
+
+ /* Free the data space. */
+ free( BaseTable::data );
+ BaseTable::data = 0;
+ BaseTable::tabLen = BaseTable::allocLen = 0;
+ }
+}
+
+/**
+ * \brief Set the contents of the vector to be len elements exactly.
+ *
+ * The vector becomes len elements in length. Destructors are called on any
+ * existing elements in the vector. Copy constructors are used to place the
+ * new elements in the vector.
+ */
+template<class T, class Resize> void Vector<T, Resize>::
+ setAs(const T *val, long len)
+{
+ /* Call All destructors. */
+ long i;
+ T *pos = BaseTable::data;
+ for ( i = 0; i < BaseTable::tabLen; pos++, i++ )
+ pos->~T();
+
+ /* Adjust the allocated length. */
+ if ( len < BaseTable::tabLen )
+ downResize( len );
+ else if ( len > BaseTable::tabLen )
+ upResize( len );
+
+ /* Set the new data length to exactly len. */
+ BaseTable::tabLen = len;
+
+ /* Copy data in. */
+ T *dst = BaseTable::data;
+ const T *src = val;
+ for ( i = 0; i < len; i++, dst++, src++ )
+ new(dst) T(*src);
+}
+
+/**
+ * \brief Set the vector to len copies of item.
+ *
+ * The vector becomes len elements in length. Destructors are called on any
+ * existing elements in the vector. The element's copy constructor is used to
+ * copy the item into the vector.
+ */
+template<class T, class Resize> void Vector<T, Resize>::
+ setAsDup(const T &item, long len)
+{
+ /* Call All destructors. */
+ T *pos = BaseTable::data;
+ for ( long i = 0; i < BaseTable::tabLen; pos++, i++ )
+ pos->~T();
+
+ /* Adjust the allocated length. */
+ if ( len < BaseTable::tabLen )
+ downResize( len );
+ else if ( len > BaseTable::tabLen )
+ upResize( len );
+
+ /* Set the new data length to exactly len. */
+ BaseTable::tabLen = len;
+
+ /* Copy item in one spot at a time. */
+ T *dst = BaseTable::data;
+ for ( long i = 0; i < len; i++, dst++ )
+ new(dst) T(item);
+}
+
+/**
+ * \brief Set the vector to exactly len new items.
+ *
+ * The vector becomes len elements in length. Destructors are called on any
+ * existing elements in the vector. Default constructors are used to init the
+ * new items.
+ */
+template<class T, class Resize> void Vector<T, Resize>::
+ setAsNew(long len)
+{
+ /* Call All destructors. */
+ T *pos = BaseTable::data;
+ for ( long i = 0; i < BaseTable::tabLen; pos++, i++ )
+ pos->~T();
+
+ /* Adjust the allocated length. */
+ if ( len < BaseTable::tabLen )
+ downResize( len );
+ else if ( len > BaseTable::tabLen )
+ upResize( len );
+
+ /* Set the new data length to exactly len. */
+ BaseTable::tabLen = len;
+
+ /* Create items using default constructor. */
+ T *dst = BaseTable::data;
+ for ( long i = 0; i < len; i++, dst++ )
+ new(dst) T();
+}
+
+
+/**
+ * \brief Replace len elements at position pos.
+ *
+ * If there are existing elements at the positions to be replaced, then
+ * destructors are called before the space is used. Copy constructors are used
+ * to place the elements into the vector. It is allowable for the pos and
+ * length to specify a replacement that overwrites existing elements and
+ * creates new ones. If pos is greater than the length of the vector then
+ * undefined behaviour results. If pos is negative, then it is treated as an
+ * offset relative to the length of the vector.
+ */
+template<class T, class Resize> void Vector<T, Resize>::
+ replace(long pos, const T *val, long len)
+{
+ long endPos, i;
+ T *item;
+
+ /* If we are given a negative position to replace at then
+ * treat it as a position relative to the length. */
+ if ( pos < 0 )
+ pos = BaseTable::tabLen + pos;
+
+ /* The end is the one past the last item that we want
+ * to write to. */
+ endPos = pos + len;
+
+ /* Make sure we have enough space. */
+ if ( endPos > BaseTable::tabLen ) {
+ upResize( endPos );
+
+ /* Delete any objects we need to delete. */
+ item = BaseTable::data + pos;
+ for ( i = pos; i < BaseTable::tabLen; i++, item++ )
+ item->~T();
+
+ /* We are extending the vector, set the new data length. */
+ BaseTable::tabLen = endPos;
+ }
+ else {
+ /* Delete any objects we need to delete. */
+ item = BaseTable::data + pos;
+ for ( i = pos; i < endPos; i++, item++ )
+ item->~T();
+ }
+
+ /* Copy data in using copy constructor. */
+ T *dst = BaseTable::data + pos;
+ const T *src = val;
+ for ( i = 0; i < len; i++, dst++, src++ )
+ new(dst) T(*src);
+}
+
+/**
+ * \brief Replace at position pos with len copies of an item.
+ *
+ * If there are existing elements at the positions to be replaced, then
+ * destructors are called before the space is used. The copy constructor is
+ * used to place the element into this vector. It is allowable for the pos and
+ * length to specify a replacement that overwrites existing elements and
+ * creates new ones. If pos is greater than the length of the vector then
+ * undefined behaviour results. If pos is negative, then it is treated as an
+ * offset relative to the length of the vector.
+ */
+template<class T, class Resize> void Vector<T, Resize>::
+ replaceDup(long pos, const T &val, long len)
+{
+ long endPos, i;
+ T *item;
+
+ /* If we are given a negative position to replace at then
+ * treat it as a position relative to the length. */
+ if ( pos < 0 )
+ pos = BaseTable::tabLen + pos;
+
+ /* The end is the one past the last item that we want
+ * to write to. */
+ endPos = pos + len;
+
+ /* Make sure we have enough space. */
+ if ( endPos > BaseTable::tabLen ) {
+ upResize( endPos );
+
+ /* Delete any objects we need to delete. */
+ item = BaseTable::data + pos;
+ for ( i = pos; i < BaseTable::tabLen; i++, item++ )
+ item->~T();
+
+ /* We are extending the vector, set the new data length. */
+ BaseTable::tabLen = endPos;
+ }
+ else {
+ /* Delete any objects we need to delete. */
+ item = BaseTable::data + pos;
+ for ( i = pos; i < endPos; i++, item++ )
+ item->~T();
+ }
+
+ /* Copy data in using copy constructor. */
+ T *dst = BaseTable::data + pos;
+ for ( long i = 0; i < len; i++, dst++ )
+ new(dst) T(val);
+}
+
+/**
+ * \brief Replace at position pos with len new elements.
+ *
+ * If there are existing elements at the positions to be replaced, then
+ * destructors are called before the space is used. The default constructor is
+ * used to initialize the new elements. It is allowable for the pos and length
+ * to specify a replacement that overwrites existing elements and creates new
+ * ones. If pos is greater than the length of the vector then undefined
+ * behaviour results. If pos is negative, then it is treated as an offset
+ * relative to the length of the vector.
+ */
+template<class T, class Resize> void Vector<T, Resize>::
+ replaceNew(long pos, long len)
+{
+ long endPos, i;
+ T *item;
+
+ /* If we are given a negative position to replace at then
+ * treat it as a position relative to the length. */
+ if ( pos < 0 )
+ pos = BaseTable::tabLen + pos;
+
+ /* The end is the one past the last item that we want
+ * to write to. */
+ endPos = pos + len;
+
+ /* Make sure we have enough space. */
+ if ( endPos > BaseTable::tabLen ) {
+ upResize( endPos );
+
+ /* Delete any objects we need to delete. */
+ item = BaseTable::data + pos;
+ for ( i = pos; i < BaseTable::tabLen; i++, item++ )
+ item->~T();
+
+ /* We are extending the vector, set the new data length. */
+ BaseTable::tabLen = endPos;
+ }
+ else {
+ /* Delete any objects we need to delete. */
+ item = BaseTable::data + pos;
+ for ( i = pos; i < endPos; i++, item++ )
+ item->~T();
+ }
+
+ /* Copy data in using copy constructor. */
+ T *dst = BaseTable::data + pos;
+ for ( long i = 0; i < len; i++, dst++ )
+ new(dst) T();
+}
+
+/**
+ * \brief Remove len elements at position pos.
+ *
+ * Destructor is called on all elements removed. Elements to the right of pos
+ * are shifted len spaces to the left to take up the free space. If pos is
+ * greater than or equal to the length of the vector then undefined behavior
+ * results. If pos is negative then it is treated as an offset relative to the
+ * length of the vector.
+ */
+template<class T, class Resize> void Vector<T, Resize>::
+ remove(long pos, long len)
+{
+ long newLen, lenToSlideOver, endPos;
+ T *dst, *item;
+
+ /* If we are given a negative position to remove at then
+ * treat it as a position relative to the length. */
+ if ( pos < 0 )
+ pos = BaseTable::tabLen + pos;
+
+ /* The first position after the last item deleted. */
+ endPos = pos + len;
+
+ /* The new data length. */
+ newLen = BaseTable::tabLen - len;
+
+ /* The place in the data we are deleting at. */
+ dst = BaseTable::data + pos;
+
+ /* Call Destructors. */
+ item = dst;
+ for ( long i = 0; i < len; i += 1, item += 1 )
+ item->~T();
+
+ /* Shift data over if necessary. */
+ lenToSlideOver = BaseTable::tabLen - endPos;
+ if ( len > 0 && lenToSlideOver > 0 )
+ memmove(dst, dst + len, sizeof(T)*lenToSlideOver);
+
+ /* Shrink the data if necessary. */
+ downResize( newLen );
+
+ /* Set the new data length. */
+ BaseTable::tabLen = newLen;
+}
+
+/**
+ * \brief Insert len elements at position pos.
+ *
+ * Elements in the vector from pos onward are shifted len spaces to the right.
+ * The copy constructor is used to place the elements into this vector. If pos
+ * is greater than the length of the vector then undefined behaviour results.
+ * If pos is negative then it is treated as an offset relative to the length
+ * of the vector.
+ */
+template<class T, class Resize> void Vector<T, Resize>::
+ insert(long pos, const T *val, long len)
+{
+ /* If we are given a negative position to insert at then
+ * treat it as a position relative to the length. */
+ if ( pos < 0 )
+ pos = BaseTable::tabLen + pos;
+
+ /* Calculate the new length. */
+ long newLen = BaseTable::tabLen + len;
+
+ /* Up resize, we are growing. */
+ upResize( newLen );
+
+ /* Shift over data at insert spot if needed. */
+ if ( len > 0 && pos < BaseTable::tabLen ) {
+ memmove(BaseTable::data + pos + len, BaseTable::data + pos,
+ sizeof(T)*(BaseTable::tabLen-pos));
+ }
+
+ /* Copy data in element by element. */
+ T *dst = BaseTable::data + pos;
+ const T *src = val;
+ for ( long i = 0; i < len; i++, dst++, src++ )
+ new(dst) T(*src);
+
+ /* Set the new length. */
+ BaseTable::tabLen = newLen;
+}
+
+/**
+ * \brief Insert len copies of item at position pos.
+ *
+ * Elements in the vector from pos onward are shifted len spaces to the right.
+ * The copy constructor is used to place the element into this vector. If pos
+ * is greater than the length of the vector then undefined behaviour results.
+ * If pos is negative then it is treated as an offset relative to the length
+ * of the vector.
+ */
+template<class T, class Resize> void Vector<T, Resize>::
+ insertDup(long pos, const T &item, long len)
+{
+ /* If we are given a negative position to insert at then
+ * treat it as a position relative to the length. */
+ if ( pos < 0 )
+ pos = BaseTable::tabLen + pos;
+
+ /* Calculate the new length. */
+ long newLen = BaseTable::tabLen + len;
+
+ /* Up resize, we are growing. */
+ upResize( newLen );
+
+ /* Shift over data at insert spot if needed. */
+ if ( len > 0 && pos < BaseTable::tabLen ) {
+ memmove(BaseTable::data + pos + len, BaseTable::data + pos,
+ sizeof(T)*(BaseTable::tabLen-pos));
+ }
+
+ /* Copy the data item in one at a time. */
+ T *dst = BaseTable::data + pos;
+ for ( long i = 0; i < len; i++, dst++ )
+ new(dst) T(item);
+
+ /* Set the new length. */
+ BaseTable::tabLen = newLen;
+}
+
+/**
+ * \brief Insert len new elements using the default constructor.
+ *
+ * Elements in the vector from pos onward are shifted len spaces to the right.
+ * Default constructors are used to init the new elements. If pos is off the
+ * end of the vector then undefined behaviour results. If pos is negative then
+ * it is treated as an offset relative to the length of the vector.
+ */
+template<class T, class Resize> void Vector<T, Resize>::
+ insertNew(long pos, long len)
+{
+ /* If we are given a negative position to insert at then
+ * treat it as a position relative to the length. */
+ if ( pos < 0 )
+ pos = BaseTable::tabLen + pos;
+
+ /* Calculate the new length. */
+ long newLen = BaseTable::tabLen + len;
+
+ /* Up resize, we are growing. */
+ upResize( newLen );
+
+ /* Shift over data at insert spot if needed. */
+ if ( len > 0 && pos < BaseTable::tabLen ) {
+ memmove(BaseTable::data + pos + len, BaseTable::data + pos,
+ sizeof(T)*(BaseTable::tabLen-pos));
+ }
+
+ /* Init new data with default constructors. */
+ T *dst = BaseTable::data + pos;
+ for ( long i = 0; i < len; i++, dst++ )
+ new(dst) T();
+
+ /* Set the new length. */
+ BaseTable::tabLen = newLen;
+}
+
+/* Makes space for len items, Does not init the items in any way. If pos is
+ * greater than the length of the vector then undefined behaviour results.
+ * Updates the length of the vector. */
+template<class T, class Resize> void Vector<T, Resize>::
+ makeRawSpaceFor(long pos, long len)
+{
+ /* Calculate the new length. */
+ long newLen = BaseTable::tabLen + len;
+
+ /* Up resize, we are growing. */
+ upResize( newLen );
+
+ /* Shift over data at insert spot if needed. */
+ if ( len > 0 && pos < BaseTable::tabLen ) {
+ memmove(BaseTable::data + pos + len, BaseTable::data + pos,
+ sizeof(T)*(BaseTable::tabLen-pos));
+ }
+
+ /* Save the new length. */
+ BaseTable::tabLen = newLen;
+}
+
+#ifdef AAPL_NAMESPACE
+}
+#endif
+
+#endif /* _AAPL_VECTOR_H */
diff --git a/src/aapl/version.mk b/src/aapl/version.mk
new file mode 100644
index 00000000..fa74770a
--- /dev/null
+++ b/src/aapl/version.mk
@@ -0,0 +1,2 @@
+VERSION = 2.14
+PUBDATE = March 2006