WvLinkList allows you to create type-safe lists of objects, along with appropriate iterators. Lists are used all over the Weaver and WvStreams, and the best way to learn about them is by example--so read the source code and look at the sample program in testlist.cc.
You can create a WvLinkList of any data type you want. An example: WCVCMD(DeclareWvList(WvString);) This will create a linked list that will contain data of WvString type.
To use it:
WvStringList l;
To fill the list, you may use
l.append(address of data, false);
which appends the element to the end of the list, or
l.add(address of data, false);
which is exactly the same as append, or
l.prepend(address of data, false);
which prepends the element to the beginning of the list.
The false as the second argument is "autofree". If it is true, the list takes ownership of the element.
The actual prototype of these functions are:
void append(T *data, bool autofree, char *id = NULL) void add(T *data, bool autofree, char *id = NULL) void prepend(T *data, bool autofree, char *id = NULL)
To quickly determines if the list is empty,
t.isempty();
returns true if empty.
You can also count the number of words in the list with:
l.count();
We also have an iterator through the list, which is declare as follows
WvStringList::Iter i(l);
Before using, it must be reset using rewind().
i.rewind()
rewinds the iterator so that it points to the first element of the list.
i.next()
moves the iterator along the list to point to the next element, returns: the current WvLink pointer, or null if there were no more elements remaining in the traversal sequence
WCVCMD(l.cur()) returns a pointer to the WvLink at the iterator's current location.
l.find(const void *data)
rewinds the iterator and repositions it over the element that matches the specified value, and returns the current WvLink pointer, or null if no such element was found
l.zap()
destroys the list.
l.zap(true)
destroys any elements that were added with autofree == true.
l.first()
returns a pointer to the first element in the linked list, possibly null if it is empty.
l.last()
returns a pointer to the last element in the linked list, possibly null if it is empty.
l.add_after(WvLink *after, T *data, bool autofree, char *id = NULL )
adds the element after the specified link in the list.
- "link" is the link preceeding the desired location of the element to be inserted, non-null - "data" is the element pointer, may be null - "autofree" is if true, takes ownership of the element - "id" is an optional string to associate with the element, or null
l.unlink(address to data)
unlinks the specified element from the list.
l.unlink_first()
unlinks the first element from the list.
l.unlink_after(WvLink *after, bool destroy = true)
unlinks the element that follows the specified link in the list.
You might also want to read the top of wvlinklist.h for some implementation details.
A typical use of WvLinkList would be something like this:
/* * A WvStringList example. * * Some text about this example... */ #include "wvstring.h" #include "wvlinklist.h" DeclareWvList(WvString); // creates class WvStringList int main() { WvStringList l; WvStringList::Iter i(l); WvString autostr("bork bork"); l.append(new WvString("blah blah"), true); // auto-free enabled l.append(&autostr, false); // auto-free disabled: C++ will do this one // etc for (i.rewind(); i.next(); ) { // we will learn a nicer way to do this with WvStream later. // we could typecast i() to (const char *), but the cstr() member // function is nicer (we all avoid typecasts when possible, right?) printf("%s\n", i().cstr()); } printf("Is the list empty? %s\n",l.isempty() ? "Yes" : "No"); printf("The first element is: %s\n", l.first()->cstr()); printf("The last element is: %s\n", l.last()->cstr()); // exiting this function will have C++ auto-free the list, which // causes the list to auto-free the "blah blah" string. C++ also // auto-frees the "bork bork" string automatically. It doesn't matter // that "bork bork" is freed before the list destructor is called; the // list doesn't refer to its members during destruction, unless it // needs to free the elements by itself. }
The result is:
blah blah bork bork Is the list empty? No The first element is: blah blah The last element is: bork bork
Here is another example, with a list of integers.
#include "wvstringlist.h" #include "wvhashtable.h" #include <stdio.h> DeclareWvList(int); //Declaration of list of integers int main() { int a=5, b=6; intList l; //the list intList::Iter i(l); //the iterator l.add(&a, false); l.add(&b, false); for (i.rewind(); (i.next()) ; ) printf("Foo: %d\n", i()); //prints: //Foo: 5 //Foo: 6 return 0; }
Some rather horrible macros are used to declare actual concrete list types. List type construction is facilitated by the following macros:
- DeclareWvList(Type): creates a subclass named WvListType that contains pointers to Type. - DeclareWvList2(name, Type): as the above, but calls the resulting class by the specified name.