Sprocket Linked List 1
Volume Number: 11
Issue Number: 2
Column Tag: Getting Started
Adding Your Own Class to Sprocket
Part 1 - A Linked List Class
By Dave Mark, MacTech Magazine Regular Contributing Author
Note: Source code files accompanying article are located on MacTech CD-ROM or
source code disks.
Last month, we finally got into our new (and ever evolving) framework, Sprocket. In
the next few columns, we’re going to create a new set of classes designed to add
functionality to Sprocket. This month, we’ll create and test our new classes and next
month we’ll step through the process of adding the classes to Sprocket.
I know, I know. Last month I said we were going to take a closer look at
Sprocket’s window classes. Bear with me. Every time I dig into this C++ framework
stuff, my perspective changes and I get a new sense of the direction in which I should
be heading. We’ll get to the window classes eventually.
A Linked List Class
Every framework needs some sort of linked list class. You might want to maintain a list
of CDs or your favorite movies. You might be building some sort of network server that
maintains a list of network service requests. Whatever your need, there are probably
a million ways to design a linked list class that fits the bill. In some cases, you’ll adopt
a general approach, designing a set of classes intended for many different applications.
In other cases, you’ll have a specific functional or performance need and you’ll design
a class that might not be of much use to anyone else, but will solve your problem.
Dave Falkenburg (Sprocket’s daddy) and I were chatting a few weeks ago about
some of the features Dave envisioned for Sprocket’s future. One of these features
centered around a method for keeping track of your application’s documents. As an
example, when the user quits your application, you need to step through each of your
open documents, calling each document’s close method. Some applications solve this
problem by stepping through the window list maintained by the system for every open
application. Besides the technical mumbo-jumbo you have to go through to maintain
compatibility with older versions of the MacOS, there are two basic problems with
this approach. Some of your windows may not be associated with a document, and some
of your documents may require more than a single window.
The linked list classes we’re going to explore this month were designed
specifically to maintain a list of document object pointers. As you’ll see, I tried to
generalize the linked list classes so that you could use them to store pointers to any
objects you like, but the member functions (aka, methods) were designed with
document management in mind. We’ll get into the specifics of maintaining a list of
document object pointers next month when we add the classes to Sprocket. This month
we’re going to enter the classes, then take them for a test drive.
The List Tester Project
This month’s source code was tested using both CodeWarrior and Symantec C++. Pick
your favorite compiler and build a new iostream-based project. Figure 1 shows my
CodeWarrior project window. Be sure you add the three libraries shown. If you intend
on generating PowerPC code, you’ll need to swap the two 68K-specific libraries for
those appropriate to the PowerPC.
Figure 1. The CodeWarrior version of the ListTester project.
Figure 2 shows the Symantec C++ version of the ListTester project window. If
you are using Symantec C++, be sure to add the three libraries CPlusLib, ANSI++,
and IOStreams to your project. You can have this done automatically by selecting
“C++ IoStreams Project” from the list of project types that appear when you select
New Project from the THINK Project Manager’s File menu.
Figure 2. The Symantec C++ version of the ListTester project.
As you can see from the two figures, you’ll be adding 3 source code files to the project.
In addition, you’ll be creating 2 additional include files, bringing the grand total to 5.
The next five sections contain the source code for each of these five files. Type in the
code (assuming you haven’t already downloaded it), save it under the appropriate file
name, and add each of the 3 “.cp” files to the project.
Main.cp
#include
#include "LinkedList.h
void CountAndDisplayLinks( TLinkedList *listPtr );
int main()
{
TLinkedList *listPtr;
char *string;
char *s1 = "Frank Zappa",
*s2 = "Violent Femmes",
*s3 = "Jane Siberry";

listPtr = new TLinkedList;

listPtr->CreateAndAddLink( s1 );
listPtr->CreateAndAddLink( s2 );
listPtr->CreateAndAddLink( s3 );

CountAndDisplayLinks( listPtr );

cout << "-----\n";

string = (char *)listPtr->GetNthLinkObject( 2UL );
listPtr->FindAndDeleteLink( string );

CountAndDisplayLinks( listPtr );

return 0;
}
CountAndDisplayLinks
void CountAndDisplayLinks( TLinkedList *listPtr )
{
unsigned long counter, numLinks;
char *string;

numLinks = listPtr->CountLinks();
cout << "This list has ";
cout << numLinks;
cout << " links...\n";

for ( counter = 1; counter <= numLinks; counter++ )
{
cout << "Link #" << counter << ": ";
string = (char *)listPtr->GetNthLinkObject( counter );

cout << string << "\n";
}
}
LinkedList.h
#ifndef _LINKEDLIST_
#define _LINKEDLIST_
#ifndef _LINK_
#include "Link.h
#endif
const OSErr kLinkedList_LinkNotFoundErr = -2;
const OSErr kLinkedList_CouldNotDeleteLinkErr = -3;
class TLinkedList
class TLinkedList
{
public:
TLinkedList();
virtual ~TLinkedList();
virtual OSErr CreateAndAddLink(void *objectPtr);
virtual OSErr FindAndDeleteLink(void *objectPtr);
virtual unsigned long CountLinks();
virtual void *GetNthLinkObject(unsigned long linkIndex);
protected:
virtual void DeleteAllLinks();
TLink *FindLink( void *objectPtr );
virtual OSErr DeleteLink( TLink *linkPtr );

TLink *fFirstLinkPtr;
TLink *fLastLinkPtr;
};
#endif
LinkedList.cp
#include "LinkedList.h
#include "Link.h
TLinkedList::TLinkedList()
{
fFirstLinkPtr = nil;
fLastLinkPtr = nil;
}
TLinkedList::~TLinkedList
TLinkedList::~TLinkedList()
{
DeleteAllLinks();
}
TLinkedList::CreateAndAddLink
OSErr TLinkedList::CreateAndAddLink( void *objectPtr )
{
TLink *newLinkPtr;

newLinkPtr = new TLink( objectPtr );

if ( newLinkPtr == nil )
return kLink_BadLinkErr;
if ( fFirstLinkPtr == nil )
fFirstLinkPtr = newLinkPtr;

if ( fLastLinkPtr != nil )
fLastLinkPtr->SetNextLink( newLinkPtr );
newLinkPtr->SetPrevLink( fLastLinkPtr );