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
00057
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
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
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 }