Using CKStrings in hash_set and hash_map
Yesterday I was starting to work on my next little project - a price injector from our price feed to a new vendor app that we're integrating.
Another developer is building a nice C++ wrapper around the proprietary messaging API. It's not terribly complicated, but he's going to wrap it so that we can make a message system that we can use within the Shop without having to worry that we're overloading the vendor's product. So with that part done, or at least getting done, I can focus on the application that will takes prices from the price source (CacheStation) and then send it to the app via our message bus.
Configuration for these apps is something I've worried about over and over for each new app. You want something that's easy to edit... something that's got a central location for easy maintenance... yet not introduce more system dependencies than you absolutely have to. Most of the time this is a configuration file, but I have used configuration databases at times and while I like a lot about that, I think the better solution is to have a flat file that can hold complex objects and structures and then make it possible to have this reloaded on-demand or on a timer and in that way you simply edit the file and the changes will be read in.
So in doing this I was thinking I'd mimic the BKHashMap and BKHashTree in BKit. Both have been very successful for me, and so I started looking at the hash_map in the SGI extensions to STL that have recently been adopted by C++. The problem was that in order to use a CKString as a key in the map (or an element in a hash_set) I needed to specialize the hash<T> template. It was pretty simple once I looked at the header for hash_fun.h:
/* * While I'm not a big fan of the way they have chosen to put in the hash_map * and hash_set templates - I think it's too clunky. They should have made * it possible to put a hash operator or method on the class, but that's an * opinion. Anyway, given how they chose to do it, this template specialization * allows us to create sets and maps using the hashing function below. */ namespace __gnu_cxx { template<> struct hash<const CKString &> { size_t operator()(const CKString & arg) const { return __stl_hash_string(arg.c_str()); } }; }
With this, I can create the has_map by simply saying:
#include <ext> #include "CKString.h" __gnu_cxx::hash_map< CKString, int, __gnu_cxx::hash<const CKString &> > map; map["when"] = 10;
Once I have the hash_map I can build the CKHashMap and CKHashTree classes. These would then form the basis of the file-based preferences system for the application. I've already done the code for BKHashMap to read and write plists of objects, so it'd be easy for me to make nicely structure-rich preferences files and then simply read them in and manipulate them.