Chapter 2. Class Overview

This chapter contains the following sections:

This section gives an overview of Tools.h++, and highlights some common points among the classes.

Tools.h++ provides implementation, not policy. Hence, it consists mostly of a large and rich set of concrete classes that are usable in isolation and independent of other classes for their implementation or semantics. They can be pulled out and used just one or two at a time. Concrete classes are the heart of Tools.h++.

Tools.h++ also includes a rich set of abstract base classes, which define an interface for persistence, internationalization, and other issues, and a number of implementation classes that implement these interfaces. Although public, the implementation classes act like private classes. They are not designed to be used, and are therefore not documented.

Some Tools.h++ classes are further categorized as collection classes, or collections. A central feature of Tools.h++, the collection classes fall into three groups:

Regardless of their implementation, collection classes generally follow the Smalltalk naming conventions and semantical model: SortedCollection, Dictionaries, Bags, Sets, and so on. They use similar interfaces, allowing them to be interchanged easily. The template-based and generic collections will hold any kind of object; the Smalltalk-like collections require that all collected items inherit from RWCollectable.

Choosing which collection classes to use in your programs is not a trivial task. We have added Appendix A, "Choosing A Collection," to help you decide which class is the best for your purposes.

"Version" at the end of this chapter gives the class hierarchy of all the public Tools.h++ classes. In addition to these public classes, Tools.h++ contains other classes for its own internal use.

Concrete Classes

The concrete classes consist of:

  • The simple classes representing dates, times, strings, and so on, discussed in Chapter 3, Chapter 4, and Chapter 5.

  • The template-based collection classes, discussed in Chapter 11

  • The generic collection classes using the preprocessor <generic.h> facilities, discussed in Chapter 12.

Simple Classes

Tools.h++ provides a rich set of lightweight simple classes. By lightweight, we mean classes with low-cost initializers and copy constructors. These classes include: RWDate (for dates); RWTime (for times, with support for various time zones and locales); RWCString (for single and multibyte strings); RWWString (for wide character strings); and RWCRegexp or RWCRexpr (for regular expressions). Most of these classes can be held in four bytes or less, and have very simple copy constructors (usually just a bit copy) and no virtual functions. See the Class Reference.

Template-based Collection Classes

Template-based collection classes, or templates for short, give you the advantages of speed and type-safe usage. When templates are used sparingly, their code size can be quite small. When templates are used with many different types, however, their code size can become large because each type effectively generates a whole new class. If your compiler is capable of using the Standard C++ Library, you can use the Tools.h++ template-based collections that are based on the Standard C++ Library. If your compiler does not have access to the Standard C++ Library, you can still use a subset of the templates, as described in "Standard C++ Library Not Required" and "Migration Guide: For Users of Previous Versions of Tools.h++" in Chapter 11.

Generic Collection Classes

Generic collection classes are those which use the <generic.h> preprocessor macros supplied with your C++ compiler. They can approximate templates, in the sense that they are typesafe, for compilers that do not support templates, and so are highly portable. However, because they depend heavily on the preprocessor, it can be difficult to use a debugger on code that contains them. See Chapter 12 for more information.

Abstract Base Classes

Tools.h++ includes a set of abstract base classes and corresponding specializing classes that provides a framework for many issues. The list below identifies some of these issues and associates them with their respective abstract base classes. The description of each class in the Class Reference indicates if it is an abstract base class.

Table 2-1. Abstract Base Classes and Issues

Issue

Class

Chapter Where Discussed

Locale

RWLocale

Chapter 16

Time zones

RWZone

Chapter 16

Virtual streams

RWvistreamRWvostream

Chapter 6

Polymorphic persistence

RWCollectable

Chapter 14

Virtual page heaps

RWVirtualPageHeap

Class ReferenceXX

Model-View-Controller abstraction

RWModelRWModelClient

Class ReferenceXX


Smalltalk-like Collection Classes

The Smalltalk-like collection classes of Tools.h++ give you much of the functionality of such Smalltalk namesakes as Bag and SortedCollection, along with some of the strengths and weaknesses of C++. The greatest advantages of the Smalltalk-like collections are their simple programming interface, powerful I/O abilities, and high code reuse. Their biggest disadvantages are their relative lack of type-safety, and their relatively large object code size. Large code is typical even when these classes are used in only small doses because of their initially high overhead in code machinery. All objects to be used by the Smalltalk-like collection classes must inherit from the abstract base class RWCollectable.

Common Member Functions

Whatever their category, all classes have similar programming interfaces. This section highlights their common functionality.

Persistence

Tools.h++ uses the following member functions to store an object of type ClassName to and from an RWFile, and to and from the Rogue Wave virtual streams facility, and to restore it later:

RWFile&      operator<<(RWFile& file, const ClassName&);
RWFile&      operator>>(RWFile& file,       ClassName&);
Rwvostream&  operator<<(RWvostream& vstream,const ClassName&);
Rwvistream&  operator>>(RWvistream& vstream,  ClassName&);

Class RWFile, which encapsulates ANSI-C file I/O, saves objects in binary format. The result is efficient storage and retrieval to files. For more information on RWFile, see Chapter 7 and the Class Reference.

Classes RWvistream and RWvostream are abstract base classes used by the Rogue Wave virtual streams facility. The final output format is determined by the specializing class. For example, RWpistream and RWpostream are two classes that derive from RWvistream and RWvostream, respectively. They store and retrieve objects using a portable ASCII format. The results can be transferred between different operating systems. These classes are discussed in more detail in Chapter 6 and the Class Reference.

It's up to you to decide whether to store to RWFiles, or to Rogue Wave streams. Storing to RWFiles gives you speed, but limits portability of results to the host machine and operating system. Storing to Rogue Wave streams is not as fast, but you get several specializing classes that provide other useful features, including highly portable format between different machines, and XDR stream encapsulation for distributed computations.

Store Size

The following common member functions return the number of bytes of secondary storage necessary to store an object of type ClassName to an RWFile:

Rwspace  ClassName::binaryStoreSize() const;
Rwspace  ClassName::recursiveStoreSize() const;

The member functions use the function:

RWFile& operator<<(RWFile& file, const ClassName&);

The above member functions are good for storing objects using classes RWFileManager and RWBTreeOnDisk. For objects that inherit from RWCollectable, the second variant recursiveStoreSize() can calculate the number of bytes used in a recursive store. The variant uses the function:

RWFile& operator<<(RWFile& file, const RWCollectable&)

You can use class RWAuditStreamBuffer in conjuction with any stream to count the number of bytes that pass through the buffer. Therefore, this class gives you functionality for streams as the above member functions give you functionality for files. For more information on class RWAuditStreamBuffer, see the Class Reference.

Stream I/O

The overloaded left-shift operator <<, taking an ostream object as its first argument, will print the contents of an object in human-readable form. Conversely, the overloaded right-shift operator >>, taking an istream object as its first argument, will read and parse an object from the stream in a human-understandable format.

ostream&  operator<<(ostream& ostr, const ClassName& x);
istream&  operator>>(istream& istr, const ClassName& x);

The overloaded left-shift and right-shift operators contrast with the persistence operators:

Rwvostream&  operator<<(RWvostream& vstream, const ClassName&);
Rwvistream&  operator>>(RWvistream& vstream,       ClassName&);

Although the persistence shift operators may store and restore to and from a stream, they will not necessarily do so in a form that could be called "human-readable."

Comparisons

Finally, most classes have comparison and equality member functions:

int        compareTo(ClassName*) const;
RWBoolean  equalTo(ClassName*) const;

and their logical operator counterparts:

RWBoolean  operator==(const ClassName&) const;
RWBoolean  operator!=(const ClassName&) const;
RWBoolean  operator<=(const ClassName&) const;
RWBoolean  operator>=(const ClassName&) const;
RWBoolean  operator<(const ClassName&) const;
RWBoolean  operator>(const ClassName&) const;

Memory Allocation and Deallocation

When an object is allocated off the heap, who is responsible for deleting it? With some libraries, ownership can be a problem.

Most of the Rogue Wave classes take a very simple approach: if you allocate something off the heap, then you are responsible for deallocating it. If the Rogue Wave library allocates something off the heap, then it is responsible for deallocating it.

There are two exceptions for creation of objects. The first exception involves the operators:

RWFile&      operator>>(RWFile& file, RWCollectable*&);
Rwvistream&  operator>>(RWvistream& vstream, RWCollectable*&);

These operators restore an object inheriting from RWCollectable from an RWFile or RWvistream, respectively. They return a pointer to an object allocated off the heap: you are responsible for deleting it.

The second exception is member function:

RWCollection* RWCollection::select(RWtestCollectable, void*)const;

This function returns a pointer to a collection, allocated off the heap, with members satisfying some selection criterion. Again, you are responsible for deleting this collection when you are done with it.

There is also an exception for object deletion: As a service, many of the collection classes provide a method, clearAndDestroy(), which will remove all pointers from the collection and delete each. Even with clearAndDestroy(), however, it is still your responsibility to know that it is safe to delete all the pointers in that collection.

These methods are documented in detail in the Class Reference.

Information Flow

With the Rogue Wave libraries, information generally flows into a function via its arguments and out through a return value. Most functions do not modify their arguments. Indeed, if an argument is passed by value or as a const reference:

void  foo(const RWCString& a)

you can be confident that the argument will not be modified. However, if an argument is passed as a non-const reference, you may find that the function will modify it.

If an argument is passed in as a pointer, there is the strong possibility that the function will retain a copy of the pointer. This is typical of the collection classes:

RWOrdered::insert(RWCollectable*);

The function retains a copy of the pointer to remind you that the collection will be retaining a pointer to the object after the function returns[1] .

Multithread Safe

When compiled with the appropriate option according to the release notes for your compiler, Tools.h++ is multithread safe. In other words, all Tools.h++ functions behave the same in a multithreaded environment as in a single-threaded environment. Of course, this assumes the application program takes care either to avoid sharing individual objects between threads, or to perform locking around operations on objects shared across threads. Tools.h++ does enough internal locking to maintain its own internal integrity, and uses appropriate multithread-safe systems calls.

Eight-bit Clean

All classes in Tools.h++ are eight-bit clean. This means they can be used with eight-bit code sets such as ISO Latin-1.

Embedded Nulls

All classes in Tools.h++, including RWCString and RWWString, support character sets with embedded nulls. This allows them to be used with multibyte character sets.

Indexing

Indexes have type size_t, an unsigned integral type defined by your compiler, usually in <stddef.h>. Because size_t is unsigned, it allows indexes up to 64k minus one under 16-bit DOS.

Invalid indexes are signified by the special value RW_NPOS, defined in <rw/defs.h>.

Version

When programming, you may need to know the specific version number of Tools.h++ to perform certain operations. This number is given by the macro RWTOOLS, expressed as a hexadecimal number. For example, version 1.2.3 would be 0x123. This can be used for conditional compilations.

If the version is needed at run time, you can find it via the function rwToolsVersion(), declared in header file <rw/tooldefs.h>.

Example 2-1. The Public Class Hierarchy of the Tools.h++ Classes



Note: This is the public class hierarchythe class implementations may use private inheritance. Classes that have multiple inheritance are shown in both places in the hierarchy; their other base is shown in italics to the right.


RWBench
RWBitVec
RWBTreeOnDisk
RWCacheManager
RWCollectable
       RWCollection
              RWBag
              RWBinaryTree
              RWBTree
                     RWBTreeDictionary
              RWHashTable
                     RWSet
                            RWFactory
                                   RWHashDictionary
                                          RWIdentityDictionary
                                   RWIdentitySet
              RWSequenceable
                     RWDlistCollectables
                     RWOrdered
                            RWSortedVector
                     RWSlistCollectables
                            RWSlistCollectablesQueue
                            RWSlistCollectablesStack
RWCollectableDate (&RWDate)
       RWCollectableInt (&RWInteger)
       RWCollectableString (&RWCString)
       RWCollectableTime (&RWTime)
       RWModelClient
RWCRegexp
RWCRExp
RWCString
       RWCollectableString (&RWCollectable)
RWCSubString
RWCTokenizer
RWDate 
       RWCollectableDate (&RWCollectable)
RWErrObject
RWFile
       RWFileManager
RWGBitVec(size)
RWGDlist(type)
RWGDlistIterator(type)
RWGOrderedVector(val)
RWGQueue(type)
RWGSlist(type)
RWGSlistIterator(type)
RWGStack(type)
RWGVector(val)
RWGSortedVector(val)
RWInteger
       RWCollectableInt (&RWCollectable)
RWIterator
       RWBagIterator
       RWBinaryTreeIterator
       RWDlistCollectablesIterator
       RWHashDictionaryIterator
       RWHashTableIterator
              RWSetIterator
       RWOrderedIterator
       RWSlistCollectablesIterator
RWLocale 
       RWLocaleSnapshot
RWMessage
RWModel
RWTime
       RWCollectableTime (&RWCollectable)
RWTimer
RWTBitVec<size>
RWTIsvDlist<T>
RWTIsvDlistIterator<TL>
RWTIsvSlist<T>
RWTIsvSlistIterator<TL> 
RWTPtrDeque<T>
RWTPtrDlist<T>
RWTPtrDlistIterator<T>
RWTPtrHashMap<Key,Type,Hash,EQ> 
RWTPtrHashMapIterator<Key,Type,Hash,EQ>
RWTPtrHashMultiMap<Key,Type,Hash,EQ>
RWTPtrHashMultiMapIterator<Key,Type,Hash,EQ>
RWTPtrHashMultiSet<T,Hash,EQ>
RWTPtrHashMultiSetIterator<T,Hash,EQ>
RWTPtrHashSet<T,Hash,EQ>
RWTPtrHashSetIterator<T,Hash,EQ>
RWTPtrMap<Key,Type,Compare>
RWTPtrMapIterator<Key,Type,Compare>
RWTPtrMultiMap<Key,Type,Compare>
RWTPtrMultiMapIterator<Key,Type,Compare>
RWTPtrMultiSet<T,Compare>
RWTPtrMultiSetIterator<T,Compare>
RWTPtrOrderedVector<T>
RWTPtrSet<T,Compare>
RWTPtrSetIterator<T,Compare>
RWTPtrSlist<T>
RWTPtrSlistIterator<T>
RWTPtrSlistDictionary<KeyP,ValP> 
RWTPtrSlistDictionaryIterator<KeyP,ValP>
RWTPtrSortedDlist<T,Compare>
RWTPtrSortedDlistIterator<T,Compare>
RWTPtrSortedVector<T,Compare>
RWTPtrVector<T>
RWTQueue<T,Container>
RWTRegularExpression<charT>
RWTStack<T,Container>
RWTValDeque<T>
RWTValDlist<T>
RWTValDlistIterator<T>
RWTValHashMap<Key,Type,Hash,EQ>
RWTValHashMapIterator<Key,Type,Hash,EQ>
RWTValHashMultiMap<Key,Type,Hash,EQ>
RWTValHashMultiMapIterator<Key,Type,Hash,EQ>
RWTValHashMultiSet<T,Hash,EQ>
RWTValHashMultiSetIterator<T,Hash,EQ>
RWTValHashSet<T,Hash,EQ>
RWTValHashSetIterator<T,Hash,EQ>
RWTValMap<Key,Type,Compare>
RWTValMapIterator<Key,Type,Compare>
RWTValMultiMap<Key,Type,Compare>
RWTValMultiMapIterator<Key,Type,Compare>
RWTValMultiSet<T,Compare>
RWTValMultiSetIterator<T,Compare>
RWTValOrderedVector<T>
RWTValSet<T,C>
RWTValSetIterator<T,C>
RWTValSlist<T>
RWTValSlistIterator<T>
RWTValSlistDictionary<Key,V>
RWTValSlistDictionaryIterator<Key,V>
RWTValSortedDlist<T,Compare>
RWTValSortedDlistIterator<T,Compare>
RWTValSortedVector<T>
RWTValVector<T>
RWTValVirtualArray<T>
RWvios
RWios (virtual)
RWvistream
RWbistream  (&ios: virtual)
RWeistream
RWpistream
                     RWXDRistream  (&RWios)
              RWvostream
RWbostream  (&ios: virtual)
RWeostream
                     RWpostream
                     RWXDRostream  (&RWios)
RWVirtualPageHeap
       RWBufferedPageHeap
              RWDiskPageHeap
RWWString
RWWSubString
RWWTokenizer
RWZone
       RWZoneSimple
streambuf
       RWAuditStreamBuffer
       RWCLIPstreambuf
              RWDDEstreambuf
xmsg
       RWxmsg
              RWExternalErr
                     RWFileErr
                     RWStreamErr
              RWInternalErr
                     RWBoundsErr
              RWxalloc



[1] An alternative design strategy would be to pass objects that are to be inserted into a collection by reference, as in The NIH Classes. We rejected this approach for two reasons: it looks so similar to pass-by-value that the programmer could forget about the retained reference; also, it becomes too easy to store a reference to a stack-based variable.