WvStreams
wvstreamsdebugger.cc
00001 #include <set>
00002 #include "wvstreamsdebugger.h"
00003 #include "wvlinklist.h"
00004 
00005 using std::set;
00006 
00007 
00008 static set<WvStreamsDebugger*> *debuggers;
00009 
00010 
00011 WvStreamsDebugger::CommandMap *WvStreamsDebugger::commands;
00012 
00013 
00014 class WvStreamsDebuggerStaticInitCleanup
00015 {
00016 public:
00017     WvStreamsDebuggerStaticInitCleanup()
00018     {
00019         WvStreamsDebugger::add_command("help",
00020                 0, &WvStreamsDebugger::help_run_cb, 0);
00021     }
00022     ~WvStreamsDebuggerStaticInitCleanup()
00023     {
00024         assert(!debuggers || debuggers->empty());
00025         
00026         if (WvStreamsDebugger::commands)
00027         {
00028             delete WvStreamsDebugger::commands;
00029             WvStreamsDebugger::commands = NULL;
00030         }
00031         
00032         if (debuggers)
00033         {
00034             delete debuggers;
00035             debuggers = NULL;
00036         }
00037     }
00038 };
00039 static WvStreamsDebuggerStaticInitCleanup ___;
00040 
00041 
00042 void *WvStreamsDebugger::get_command_data(WvStringParm cmd, Command *command)
00043 {
00044     if (command == NULL)
00045     {
00046         CommandMap::iterator it = commands->find(cmd);
00047         if (it == commands->end())
00048             return NULL;
00049         command = &it->second;
00050     }
00051 
00052     void *cd;
00053     CommandDataMap::iterator it = command_data.find(cmd);
00054     if (it == command_data.end())
00055     {
00056         // In case the command has been added since our constructor
00057         // was executed...
00058         if (command->init_cb)
00059             cd = command->init_cb(cmd);
00060         else
00061             cd = NULL;
00062             
00063         command_data[cmd] = cd;
00064     }
00065     else
00066         cd = it->second;
00067 
00068     return cd;
00069 }
00070 
00071 
00072 WvStreamsDebugger::WvStreamsDebugger()
00073 {
00074     if (!debuggers)
00075         debuggers = new set<WvStreamsDebugger*>;
00076     debuggers->insert(this);
00077     
00078     // Add command data for existing commands
00079     CommandMap::iterator it;
00080     for (it = commands->begin(); it != commands->end(); ++it)
00081         get_command_data(it->first, &it->second);
00082 }
00083 
00084 
00085 WvStreamsDebugger::~WvStreamsDebugger()
00086 {
00087     // Remove command data
00088     CommandDataMap::iterator it;
00089     for (it = command_data.begin(); it != command_data.end(); ++it)
00090     {
00091         CommandMap::iterator it2 = commands->find(it->first);
00092         if (it2 != commands->end() && it2->second.cleanup_cb)
00093             it2->second.cleanup_cb(it->first, it->second);
00094     }
00095     command_data.clear();
00096     
00097     debuggers->erase(this);
00098 }
00099 
00100 
00101 WvString WvStreamsDebugger::run(WvStringParm cmd, WvStringList &args,
00102                                 ResultCallback result_cb)
00103 {
00104     CommandMap::iterator it = commands->find(cmd);
00105     if (it == commands->end())
00106         return "No such command";
00107     Command *command = &it->second;
00108    
00109     return command->run_cb(cmd, args, result_cb,
00110                            get_command_data(cmd, command));
00111 }
00112 
00113 
00114 bool WvStreamsDebugger::add_command(WvStringParm cmd,
00115         InitCallback init_cb,
00116         RunCallback run_cb,
00117         CleanupCallback cleanup_cb)
00118 {
00119     if (!commands)
00120         commands = new CommandMap;
00121 
00122     return commands->insert(
00123         std::make_pair(cmd, Command(init_cb, run_cb, cleanup_cb))).second;
00124 }
00125 
00126 
00127 bool WvStreamsDebugger::foreach(WvStringParm cmd, ForeachCallback foreach_cb)
00128 {
00129     CommandMap::iterator it = commands->find(cmd);
00130 
00131     if (it == commands->end())
00132         return false;
00133     
00134     if (debuggers)
00135     {
00136         set<WvStreamsDebugger*>::iterator it2;
00137         for (it2 = debuggers->begin(); it2 != debuggers->end(); ++it2)
00138         {
00139             void *cd = (*it2)->get_command_data(cmd, &it->second);
00140             foreach_cb(cmd, cd); 
00141         }
00142     }
00143     
00144     return true;
00145 }
00146 
00147 
00148 WvString WvStreamsDebugger::help_run_cb(WvStringParm cmd,
00149         WvStringList &args,
00150         ResultCallback result_cb, void *)
00151 {
00152     WvStringList cmd_list;
00153     cmd_list.append("Commands available:");
00154     CommandMap::iterator it;
00155     for (it = commands->begin(); it != commands->end(); ++it)
00156         cmd_list.append(it->first);
00157     result_cb(cmd, cmd_list);
00158     return WvString::null;
00159 }