Introduction to RogueWave Tools.h++ C++ Libraries
for Irix 6.2

Summary
This article shows how to get started with the Tools.h++ collection and utility classes available in the Irix 6.2 compiler configuration, including the ANSI Class library support via Tools.h++. This is a draft article to be published later in Dev News.


By Kent Sandvik


The C++ development environment in Iris 6.2 includes the Rogue Wave Tools.h++ collection and utility classes. Tools.h++ is a C++ class library that provides a lot of the standard structures needed in common programming exersizes. Examples of such classes are Time classes, String classes, collections, iterators, Time classes, singly- and doubly-linked lists and so on. All together Tools.h++ contains 120 various classes. In addition, Tools.h++ provide interfaces to the draft Standard C++ libraries including ANSI C++ String classes. The Standard Template Library (STL) support in 6.2 compilers are based on Tools.h++ collection classes.

The Tools.h++ classes support persistance, so you could save and retrieve objects from and to disk, or over a network. This works even cross-platform, as Tools.h++ has been ported to various platforms including Windows and MacOS. All Tools.h++ classes are multi-thread safe. Each class is not derived from a single root class, this means that it's easy to combine the classes with other C++ classes, using HAS-A relationships or multiple inheritance.

Getting Started

You should have installed the c++_dev system, especially the Rogue Wave related subsystems such as c++_dev.hdr.librw, c++_dev.man.librw, c++_dev.sw.librw and c++_dev.sw32.librw.

The RogueWave libraries are called librwtool.a, so when you compile code using these libraries, you need to include these using -lrwtool . The actual header files are placed inside /usr/include/CC/rw , but when you write code you include these using the normal path names, as in:

#include <rw/rwtime.h>
#include <rw/rwdate.h>
#include <rw/rstream.h>

Note that various Tools.h++ classes have overrides concerning the C++ streams io libraries, so you need to include the specific rstream.h header file in order to use these.

First Simple Example

Here's a simple example of how to use the RWTime class:

#include <rw/rwtime.h>
#include <rw/rwdate.h>
#include <rw/rstream.h>

void main(void) {
        RWTime t;       // current time
        RWTime d(RWTime::beginDST(1990, RWZone::local()));

        cout << "current time: " << RWDate(t) << " " << t << endl;
        cout << "Start of DST, 1990: " << RWDate(d) << " " << d << endl;
}

This example is also explained in the man RWTime entry. You compile 
this example using:

% CC time.c++ -lrwtool -o time_example


What's Available in Tools.h++

The first thing when we explore a framework is to find out what's available in the libraries, what classes are present, how to use these classes and so on. For example, we want to look at existing sample code to get a better feeling what we need from Tools.h++.

Rogue Wave has a class reference available at their web site: http://www.roguewave.com/support/tools/toolsamp.html You could also find examples showing how the libraries map to the ANSI C++ Standard library from http://www.roguewave.com/products/tools/code.html. Finally, the class reference is available from http://www.roguewave.com/products/abbrevcr/tools70cr.abbrev.htm. This document describes all the classes and functions, and has a class hierarchy diagram.

Also, if you know the name of the class you could do a lookup using the man entry; note that many of the man entries have small code snippets showing how to use the actual class.

Each RogueWave class starts with RW, as in RWCString. This should eliminate some of the problems with name space collisions. All classes use the same member function name to make it easier to learn the framework. For example, the member functions returning the number of items in various collection classes are always called entries().

Most classes are lightweight in that they have low cost initializer and copy constructors. Tools.h++ uses an error model that divides errors up to four different categories:

It also has various assert and pre/postcondition macros that you could use for debugging purposes.

ANSI C++ Support

Tools.h++ implements the current standard C++ libraries defined by ANSI and ISO. This is a fairly large collection of classes and functions, such as:

Iterator Example

Here's an example how to create a double-linked list with string elements, and how to iterate through these entries.

#include <iostream.h>
#include <rw/cstring.h>
#include <rw/regexp.h>
#include <rw/tvdlist.h>


void main(void)
{
    RWTValDlist <RWCString> stringList;
    RWTValDlistIterator <RWCString> it(stringList);

    stringList.insert("First");
    stringList.insert("Second");
    stringList.insert("Third");
    stringList.insert("Fourth");

    RWCString newString;

    it.reset();
    it.findNext(RWCString("Third"));
    cout << newString << endl;
}

You have to carefully read the man entries for RWTValDlistIterator as it has certain operator overloaded functions that should be used for iteration. I used the operator()() overload that will traverse along the linked list, until it finds the last one and returns FALSE in this case. You could insert, remove, find next entries and so on using this iterator.

Other Examples



Tools.h++ has regular expression classes that could be used for pattern matching. Here's a simple example showing this feature:


#include <rw/regexp.h>
#include <rw/cstring.h>
#include <rw/rstream.h>

void main(void)
{
    RWCString aString("This is a test");

    // Create a regular expression that matches any
    // lower case words starting with 't'.
    RWCRegexp reg("t[a-z]*");

    cout << aString(reg) << endl; // prints out 'test'
}

The following example shows how to create a Hash table using specific so called RWCollection objects. You could install ints, strings, Time classes, Date classes, or generic objects into the hash table:


#include <rw/hashtab.h>
#include <rw/cstring.h>
#include <rw/collstr.h>
#include <rw/rstream.h>

void main(void){
    RWHashTable table;

    table.insert(new RWCollectableString("First"));
    table.insert(new RWCollectableString("Second"));
    table.insert(new RWCollectableString("Third"));

    cout << aString(reg) << endl; // prints out 'test'
}


Here's an example showing how you could break down strings using the RWCTokenizer class:


#include <rw/ctoken.h>
#include <rw/rstream.h>

void main(void)
{
    RWCString aString("This is an example of a string.");

    RWCTokenizer tokenizer(aString); // Tokenize the string.
    RWCString item;

    while(!(item=tokenizer()).isNull())
        cout << "Table contains the key: " << key << endl;
}


Finally here's an example how to use the persistant storage system using specific RW virtual streams:



#include <rw/collstr.h>
#include <rw/ordcltn.h>
#include <rw/rstream.h>
#include <strstream.h>
#include <rw/pstream.h>


void main(void)
{
    // Create collectable strings we will stream out later.
    RWCollectableString stringOut1("First");
    RWCollectableString stringOut2("Second");
    RWCollectableString stringOut3("Third");

    // Create an ordered list.
    RWOrdered orderedOut;
    orderedOut.append(&stringOut1); 
    orderedOut.append(&stringOut2);
    orderedOut.append(&stringOut3);

    // Create our virtual stream that is attached to a standard ostrstream.
    ostrstream os;
    RWpostream post(os);

    // Fill the posted stream
    post << orderedIn;

    // Show the flattened ASCII format
    cout << os.str() << endl;
  
    // Create a virtual stream that is hooked to the ostrstream
    istrstream is(os.str());
    RWpistream pin(is);

    // Fill the incoming stream
    RWOrdered orderedIn(3);
    pin >> orderedIn;

    cout << "Num entries in: " << orderedIn.entries() << endl;

    // Restore the objects from the RWCollection set
    RWCollectableString stringIn1 = 
        *(RWCollectableString*)orderedIn[0];
    RWCollectableString stringIn2 =
        *(RWCollectableString*)orderedIn[1];
    RWCollectableString stringIn3 =
        *(RWCollectableString*)orderedIn[2];

    cout << stringIn1 << " " << stringIn2 << " " << stringIn3 << endl;
}

RWpostream will store values in a portable (ASCII format), that RWpistream will then read in for restoration of the objects. Note that this format will work cross-platform, so you could send this information over the network, or using file storage, for example.



Other Information


Rogue Wave has a web site at http://roguewave.com. This site has the latest information about the libraries including sample code, including frequently asked question information and updated README files.

As for using these collection classes instead of STL (Standard Template Libraries), it depends if you want to write STL code, or if there are cases where the Tools.h++ collection classes makes it easier to implement a specific feature. The positive aspect by using STL is that you could move such code to other platforms where the STL libraries are ported.








About the Author

Kent Sandvik works as a Developer Support Engineer for Silicon Graphics, He's worked in this role for over ten years, in various positions inside Apple and SGI including technical lead for the Newton Developer support group, and QuickTime developer support lead.

You could reach him at sandvik@sgi.com, and his home page is

at http://reality.sgi.com/sandvik/.



$Date: 1996/06/14 20:29:26 $, $Revision: 1.2 $