#ifndef STABLE_H
#define STABLE_H
// This class implements a 'stringtable'. It is being released into
// the public domain on September 27, 2000 by John W. Ratcliff
// jratcliff@verant.com for FlipCode.com as part of the 'code of they day'
// project.
//
// What the heck does a 'StringTable' class do for me? What a StringTable
// is used for is to manage a collection of shared strings across a package.
// It is primarily used for tokens, keywords, asset names, etc. You do
// *NOT* want to use the StringTable for any cases which could produce
// an infinite number of strings. This is only for managing a finite list
// of keywords.
//
// The reason you use a string table is so that you can keep track of items
// by ASCII name instead of some non-intutitive and arbritrary id number.
// Normally it is not practical to make a container class who's key is
// an STL string. First of all there is a memory overhead, and additionally
// there is a serious peformance penalty. However, with the StringTable
// class, instead you can keep track of a list of items where the key is
// a pointer to the string, instead of the string itself. Now you can
// compare if 'two strings are equal' simply by comparing if their address
// is the same. Remember that any container class which uses this pointer as
// a key is *NOT* in alphabetical order!! It's ordered based on the address
// in memory of the string itself. But that doesn't matter, because the
// purpose of the container is not to maintain an alphabetical list of
// items but rather to simply locate items *BY NAME* extremely quickly.
//
// Using a stringtable makes it trivial to keep ASCII names and descriptions
// as member variables in all of your classes. This makes debugging and
// debug output vastly simpler.
//
// Example: Say you contruct a new intance of a Vehicle class. In it's
// constructor you might have something like:
//
// mObjectName = gStringTable.Get("vehicle");
//
// Where mObjectName is a member variable of type 'const char *' and
// gStringTable is some global instance of a shared string table across
// your application. Now, you can compare whether or not an object is of
// type 'vehicle' simply by comparing it's name to anybody else's name
// with the two pointers allocated with the same string table.
//
// This is extremely convenient for debugging, logging, etc.
//
// To create an STL map where you access every item *by name* all you
// have to do is:
//
// typedef std::map< const char * , Texture *> TextureMap;
//
// This would create an STL map that would allow you to quickly look
// up any texture by name. A fairly useful data structure.
//
// Example of how to locate a texture by name:
//
// **NOTE* texname must have been created by the same StringTable
//
// Texture * FindTexture(const char *texname)
// {
// TextureMap::iterator found; // STL map iterator to find item.
// found = mTextures.find( texname ); // search red/black tree
// if ( found != mTextures.end() ) return (*found).second;
// return 0; // no texture of this name found.
// }
//
// The string table implementation uses STL to maintain the collection
// of strings. If you change the comparator function in CharPtrLess
// from strcmp to stricmp then all of your strings will be created without
// case sensitivity, which is often the behavior you want for tokens and
// keywords.
#include <string.h>
#include <string>
#include <set>
typedef std::string String;
class CharPtrLess
{
public:
bool operator()(const char *v1,const char *v2) const
{
int v = strcmp(v1,v2);
if ( v < 0 ) return true;
return false;
};
};
typedef std::set< const char *, CharPtrLess > CharPtrSet;
class StringTable
{
public:
StringTable(void)
{
};
~StringTable(void)
{
CharPtrSet::iterator i;
for (i=mStrings.begin(); i!=mStrings.end(); i++)
{
char *str = (char *)(*i);
delete str;
}
}
const char * Get(const char *str)
{
CharPtrSet::iterator found;
found = mStrings.find( str );
if ( found != mStrings.end() ) return (*found);
int l = strlen(str);
char *mem = new char[l+1];
strcpy(mem,str);
mStrings.insert( mem );
return mem;
};
const char * Get(const String &str)
{
return Get( str.c_str() );
};
private:
CharPtrSet mStrings;
};
#endif
|