ArpIndexedList
This is a list class with increased performance for accessing the events in the list:  Events are stored in a series of 'chains,' the head of each chain having a predetermined index.  For example, if the list is set up for chain sizes of 10, then the data structure might look something like:

	headNode0	<->	node2		<->	node6	<->	node9	<->
	headNode10	<->	node18	<->
	headNode24	<->	node25

What is going on might well not be immediately apparent.  The <-> signify that each node is linked to its previous and next node.  The numbers after each node signify the index they are storing.  The headNodes and nodes are each the same kind of object  (this lists are homogenous), but the term 'headNode' is used to signify the nodes that the ArpIndexedList has a direct handle on -- they are the nodes that are actually stored in the array of ArpIndexedNodes.  The other, non-head nodes, are simply the nodes that each headNode is linked to.  The term 'chain' is used to mean each of the head nodes and all that follow it --hence, we said that for this example the chain size is 10, and we are only allowing nodes indexed up to nine units over their headNode to be in a chain.

The point of this obtuseness is purely performance.  The original intention was a list to store MIDI objects that could be accessed as quickly at the 8943 element as it could at the first.  Better designs are, as always, welcome.

This design raises a problem that I have an unimplemented solution for:  Since note off information is stored with note on events, we might have events that start before a chain and cross over its boundaries, but we have no way of knowing it crosses over, therefore it does not get drawn.  The solution is to use 'GhostNotes' that store a pointer to the original note event and are placed at the beginning of each chain.  These notes are simply placeholders for drawing information, and so do not get played, written to a file, etc.



PROTECTED CHAIN ACCESSING METHODS

status_t HeadNode(ArpIndexedNode *node)
Finds the first node in the list and places it in *node.  If nothing goes wrong, B_OK is returned.  Otherwise B_ERROR is returned.

status_t TailNode(ArpIndexedNode *node)
Finds the last node in the list and places it in *node.  If nothing goes wrong, B_OK is returned.  Otherwise B_ERROR is returned.

status_t ChainHeadFrom(int32 index, ArpIndexedNode **node)
Given the index, it finds the head node in the chain containing index, and places that node in **node.  If nothing goes wrong, B_OK is returned.  Otherwise B_ERROR is answered.

status_t NodeAt(int32 index, ArpIndexedNode **node,
				int32 findNode = 0, int32 direction = ARP_FORWARDS)
This method finds the node at the specified index and places it in *node.  If no node could be found B_ERROR is returned, otherwise B_OK is returned.
	The direction argument determines what to do if there is no node exactly the supplied index: ARP_FORWARDS increases the index until one is found, ARP_BACKWARDS decreases the index until one is found.
	The findNode argument determines what to do if there is more than one node at the supplied index.  With the default of 0, the first node at the index is always returned.  With a value of 1, the second node at the index is always returned.  In this manner all nodes at a given index can be accessed.

status_t NodeFor(int32 index = 0, void *rawData, ArpIndexedNode **answer
Find the node wrapper around rawData and place it in **node.  Answer with B_OK if a node was found, otherwise B_ERROR.  The index argument is optional, but can greatly speed up the search if used.  If it isn't used (ie, the value entered does not accurately reflect where the data is in the list), then the entire list will be searched.  First the list is searched starting with the suggested index and moving forwards.  Next the list is searched starting from the suggested index and moving backwards.

int32 Count()
The number of nodes in the list is returned.

int32 ChainIndexes()
Answer the number of indexes that can exist in a single chain.  Not that this is not the number of nodes that can exist in a single chain:  Since multiple nodes can share the same index, an endless (well, theoretically) number of nodes might be in the same chain.


PROTECTED CHAIN MANIPULATION METHODS

status_t AddNode(ArpIndexedNode *node)
Add the node at its appropriate place in the list.  Answer B_OK if everything is fine, B_ERROR otherwise.

status_t RemoveNode(ArpIndexedNode *node)
Remove the node from the list, but do not delete it.  Answer B_OK if everything is fine, B_ERROR otherwise.  This method should be only used by knowledgeable clients or subclasses -- generally speaking, a node should only exist inside its list and be deleted when removed.

status_t DeleteNode(ArpIndexedNode *node)
Remove the node from the list and delete it, but leave its contents intact.  Answer B_OK if everything is fine, B_ERROR otherwise.

void AddedNode(ArpIndexedNode *node)
This virtual method is notification that a node has been added.  The implementation uses this method to keep the tailNode in sync, so any subclasses overriding this call should call the superclass method.  This method is called AFTER the node has actually been added, so all connections (prev, next, etc) are valid.

void RemovingNode(ArpIndexedNode *node)
This virtual method is notification that a node has been removed.  The implementation uses this method to keep the tailNode in sync, so any subclasses overriding this call should call the superclass method.  This method is called BEFORE the node has actually be removed, so all connections (prev, next, etc) are valid.

void GrowToAtLeast(int32 countArg)
This method is called when an event is being added beyond the current bounds of the chain array.  The chain array will grow at least to the size supplied in countArg, and possibly larger, if growing to countArg is below the ARP_CHAIN_INCREMENT.  Logically, it seems like this method should be private.  I think it probably will be once the dust settles and subclasses are written.

void DeleteOnlyNodes()
Delete all the ArpIndexedNodes stored in the list, but leave the data they wrap intact.  This should only be used by knowledgeable clients who know the wrapped data is held elsewhere.


PROTECTED UTILITY METHODS

ArpIndexedList* Copy()
Answer a new ArpIndexedList.  No nodes (and therefore data that they wrap) are copied.

void ReplaceWith(ArpIndexedList *ail)
Replace the all data (chain information, primarily) with that stored in *ail.  This was written as a convenience for file IO and ideally should not be necessary, but at the very lesat should not be used by anyone else.

void Print()
Write information about this list to stdout.


PRIVATE CHAIN MANIPULATION METHODS

status_t pAddNode(ArpIndexedNode *node)
Add the node at its appropriate place in the list.  Answer B_OK if everything is fine, B_ERROR otherwise.  This method makes sure the node is linked up properly in the list andthat the tailNode variable stays accurate.

status_t pAddNodeToIndexNearest(ArpIndexedNode *node, int32 index)
Small auxiliary method to pAddNode() that makes sure the node is linked up under certain conditions.
