// This class implements a 'stringtable'. It is being released into
// the public domain on September 27, 2000 by John W. Ratcliff
// email@example.com for FlipCode.com as part of the 'code of they day'
// 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
typedef std::string String;
bool operator()(const char *v1,const char *v2) const
int v = strcmp(v1,v2);
if ( v < 0 ) return true;
typedef std::set< const char *, CharPtrLess > CharPtrSet;
for (i=mStrings.begin(); i!=mStrings.end(); i++)
char *str = (char *)(*i);
const char * Get(const char *str)
found = mStrings.find( str );
if ( found != mStrings.end() ) return (*found);
int l = strlen(str);
char *mem = new char[l+1];
mStrings.insert( mem );
const char * Get(const String &str)
return Get( str.c_str() );