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