Main Page   Namespace List   Class Hierarchy   Alphabetical List   Compound List   File List   Namespace Members   Compound Members   File Members   Related Pages  

dispatch.h

Go to the documentation of this file.
00001 #ifndef DVCGI_DISPATCHER_H
00002 #define DVCGI_DISPATCHER_H
00003 // $Id: dispatch.h,v 1.1 2003/08/10 13:21:03 dvermeir Exp $
00004 #include <string>
00005 #include <stdexcept>
00006 #include <iostream>
00007 #include <dvcgi/cgi.h>
00008 
00009 namespace Dv {
00010 namespace Cgi {
00011 /** A class template framework to dispatch the control of a Cgi
00012  * program based on a key in the formdata.
00013  * 
00014  * We assume that a cgi application has two main objects: a
00015  * Dv::Cgi::Cgi input object and an application object of class
00016  * Application.
00017  *
00018  * The main function would construct both 
00019  * @code
00020  * int main(int, char**) {
00021  * .. // get configuration info
00022  * Application application(config-info)
00023  * Dv::Cgi::Cgi cgi(..)
00024  * if (application.main(cgi))
00025  *   return 0;
00026  *  else {
00027  *    cgi.header().content_type("text/plain");
00028  *    cgi << "Error: " << ... << std::endl;
00029  *    return 1;
00030  *    }
00031  * }
00032  * @endcode
00033  *
00034  * We also assume that there is a single formdata key that determines
00035  * the action to take, e.g. a key "opcode". Moreover, for each
00036  * relevant key value, there should be a member function
00037  *
00038  *   Application::handle_value(Dv::Cgi::Cgi& cgi, const std::string& value);
00039  *
00040  * The class template below makes it easy to dispatch to the correct
00041  * handler-function, based on the value of the specified formdata key.
00042  * 
00043  * To use, an instance should define Dispatcher<Application>::table as in the
00044  * example below.
00045  * @code
00046  * Dispatcher<Application>::Entry 
00047  * Dispatcher<Application>::table[] = {
00048  *   { "", &Application::default_handler },
00049  *   { "a", &Application::handle_a },
00050  *   { "b", &Application::handle_b },
00051  *   { "c", &Application::handle_c },
00052  *   { "", &Application::default_handler } // if "opcode" not defined, should be last
00053  * };
00054  * @endcode
00055  *
00056  * The main function in the Application could use a Dispatcher as shown below.
00057  * @code
00058  * class Application {
00059  * public:
00060  *   bool main(const Dv::Cgi::Cgi& cgi);
00061  *     return Dispatcher<Application>::handle(*this, cgi, "opcode");
00062  *     }
00063  * };
00064  * @endcode
00065  * @sa Dv::Cgi::Cgi
00066  */
00067 template <class Application>
00068 class Dispatcher {
00069 public:
00070   typedef bool (Application::*Handler)(const Dv::Cgi::Cgi& cgi, const std::string& value);
00071   typedef struct { std::string key; Handler h; } Entry;
00072   static Entry table[];
00073   static bool handle(Application& c, Dv::Cgi::Cgi& cgi,  const std::string& key) {
00074     std::string* value(cgi.props().find(key));
00075     if (value) {
00076       for (Entry* e(table); (e->key.size()) ;  ++e)
00077         if (e->key==*value)
00078           return (c.*(e->h))(cgi, *value);
00079       }
00080     else {
00081       for (Entry* e(table); (e->key.size()) ;  ++e)
00082         if (e->key.size() == 0)
00083           return (c.*(e->h))(cgi, "");
00084       }
00085     return false;
00086     }
00087 };
00088 
00089 }}
00090 #endif

dvcgi-0.5.9 [10 August, 2003]