w11 - cpp 0.794
Backend server for Rlink and w11
Loading...
Searching...
No Matches
RtclCmdBase.cpp
Go to the documentation of this file.
1// $Id: RtclCmdBase.cpp 1175 2019-06-30 06:13:17Z mueller $
2// SPDX-License-Identifier: GPL-3.0-or-later
3// Copyright 2011-2019 by Walter F.J. Mueller <W.F.J.Mueller@gsi.de>
4//
5// Revision History:
6// Date Rev Version Comment
7// 2019-06-29 1175 1.1.4 GetArgsDump(): add missing OptValid() call
8// 2018-12-15 1083 1.1.3 AddMeth(): use rval ref and move semantics
9// 2018-11-09 1066 1.1.2 use auto
10// 2017-04-02 865 1.1.1 add GetArgsDump()
11// 2017-04-02 863 1.1 add DelMeth(),TstMeth(); add M_info() and '?'
12// rename fMapMeth -> fMethMap
13// 2017-03-11 859 1.1 support now sub-command handling
14// 2014-08-22 584 1.0.3 use nullptr
15// 2013-02-10 485 1.0.2 add static const defs
16// 2013-02-05 483 1.0.1 remove 'unknown specified, full match only' logic
17// 2013-02-02 480 1.0 Initial version (refactored out from ProxyBase)
18// ---------------------------------------------------------------------------
19
24#include "RtclCmdBase.hpp"
25
28
29#include "Rtcl.hpp"
30#include "RtclOPtr.hpp"
31
32using namespace std;
33
39// all method definitions in namespace Retro
40namespace Retro {
41
42//------------------------------------------+-----------------------------------
43// constants definitions
44
45const int RtclCmdBase::kOK;
46const int RtclCmdBase::kERR;
47
48//------------------------------------------+-----------------------------------
50
52 : fMethMap()
53{}
54
55//------------------------------------------+-----------------------------------
57
59{}
60
61//------------------------------------------+-----------------------------------
63
65{
66 mmap_cit_t it_match;
67
68 Tcl_Interp* interp = args.Interp();
69
70 if (size_t(args.Objc()) == args.NDone()) {// no args left -> no method name
71 it_match = fMethMap.find("$default"); // default method registered ?
72 if (it_match != fMethMap.end()) {
73 return (it_match->second)(args);
74 }
75 // or fail
76 Tcl_WrongNumArgs(interp, args.NDone(), args.Objv(), "option ?args?");
77 return kERR;
78 }
79
80 string name;
81 /* coverity[checked_return] */
82 args.GetArg("cmd", name); // will always succeed
83 it_match = fMethMap.lower_bound(name);
84
85 // handle '?'
86 if (name == "?") return M_info(args);
87
88 // no leading substring match
89 if (it_match==fMethMap.end() ||
90 name!=it_match->first.substr(0,name.length())) {
91
92 auto it_un = fMethMap.find("$unknown"); // unknown method registered ?
93 if (it_un!=fMethMap.end()) {
94 return (it_un->second)(args);
95 }
96
97 Tcl_AppendResult(interp, "-E: bad option '", name.c_str(),
98 "': must be ", nullptr);
99 const char* delim = "";
100 for (const auto& kv : fMethMap) {
101 if (kv.first.c_str()[0] != '$') {
102 Tcl_AppendResult(interp, delim, kv.first.c_str(), nullptr);
103 delim = ",";
104 }
105 }
106 return kERR;
107 }
108
109 // check for ambiguous substring match
110 if (name != it_match->first) {
111 auto it1 = it_match;
112 it1++;
113 if (it1!=fMethMap.end() && name==it1->first.substr(0,name.length())) {
114 Tcl_AppendResult(interp, "-E: ambiguous option '",
115 name.c_str(), "': must be ", nullptr);
116 const char* delim = "";
117 for (it1=it_match; it1!=fMethMap.end() &&
118 name==it1->first.substr(0,name.length()); it1++) {
119 Tcl_AppendResult(interp, delim, it1->first.c_str(), nullptr);
120 delim = ",";
121 }
122 return kERR;
123 }
124 }
125
126 return (it_match->second)(args);
127}
128
129//------------------------------------------+-----------------------------------
131
132void RtclCmdBase::AddMeth(const std::string& name, methfo_t&& methfo)
133{
134 auto ret = fMethMap.emplace(name, move(methfo));
135 if (ret.second == false) // or use !(ret.second)
136 throw Rexception("RtclCmdBase::AddMeth:",
137 string("Bad args: duplicate name: '") + name + "'");
138 return;
139}
140
141//------------------------------------------+-----------------------------------
143
144void RtclCmdBase::DelMeth(const std::string& name)
145{
146 if (fMethMap.erase(name) == 0) // balk if not existing
147 throw Rexception("RtclCmdBase::DelMeth:",
148 string("Bad args: non-existing name: '") + name + "'");
149 return;
150}
151
152//------------------------------------------+-----------------------------------
154
155bool RtclCmdBase::TstMeth(const std::string& name)
156{
157 return fMethMap.find(name) != fMethMap.end();
158}
159
160//------------------------------------------+-----------------------------------
162
163bool RtclCmdBase::GetArgsDump(RtclArgs& args, int& detail)
164{
165 static RtclNameSet optset("-brief|-v|-vv|-vvv");
166 detail = 0;
167 string opt;
168
169 while (args.NextOpt(opt, optset)) {
170 if (opt == "-brief") { detail = -1;}
171 else if (opt == "-v") { detail = +1;}
172 else if (opt == "-vv") { detail = +2;}
173 else if (opt == "-vvv") { detail = +3;}
174 else { detail = 0;}
175 }
176
177 return args.OptValid();
178}
179
180//------------------------------------------+-----------------------------------
182
184{
185 Tcl_Interp* interp = args.Interp();
186 string cname("");
187 if (!args.GetArg("??cname", cname)) return TCL_ERROR;
188 if (!args.AllDone()) return TCL_ERROR;
189
190 RtclOPtr rlist(Tcl_NewListObj(0,nullptr));
191 if (cname == "") { // no name --> return all
192 for (const auto& kv : fMethMap) {
193 if (kv.first[0] == '$') continue; // skip $nnn internals
194 RtclOPtr pele(Tcl_NewStringObj(kv.first.c_str(), -1));
195 Tcl_ListObjAppendElement(nullptr, rlist, pele);
196 }
197
198 } else { // name seen --> return matches
199 auto it_match = fMethMap.lower_bound(cname);
200 for (auto it=it_match; it!=fMethMap.end() &&
201 cname==it->first.substr(0,cname.length()); it++) {
202 RtclOPtr pele(Tcl_NewStringObj(it->first.c_str(), -1));
203 Tcl_ListObjAppendElement(nullptr, rlist, pele);
204 }
205 }
206
207 Tcl_SetObjResult(interp, rlist);
208 return TCL_OK;
209}
210
211} // end namespace Retro
FIXME_docs.
Definition: Rexception.hpp:29
FIXME_docs.
Definition: RtclArgs.hpp:41
bool NextOpt(std::string &val)
FIXME_docs.
Definition: RtclArgs.cpp:368
Tcl_Obj *const * Objv() const
FIXME_docs.
Definition: RtclArgs.ipp:44
bool GetArg(const char *name, Tcl_Obj *&pval)
FIXME_docs.
Definition: RtclArgs.cpp:114
bool OptValid() const
FIXME_docs.
Definition: RtclArgs.ipp:52
int Objc() const
FIXME_docs.
Definition: RtclArgs.ipp:36
size_t NDone() const
FIXME_docs.
Definition: RtclArgs.ipp:60
Tcl_Interp * Interp() const
FIXME_docs.
Definition: RtclArgs.ipp:28
bool AllDone()
FIXME_docs.
Definition: RtclArgs.cpp:447
mmap_t::const_iterator mmap_cit_t
Definition: RtclCmdBase.hpp:40
void AddMeth(const std::string &name, methfo_t &&methfo)
FIXME_docs.
int M_info(RtclArgs &args)
FIXME_docs.
virtual ~RtclCmdBase()
Destructor.
Definition: RtclCmdBase.cpp:58
mmap_t fMethMap
map for named methods
Definition: RtclCmdBase.hpp:62
std::function< int(RtclArgs &)> methfo_t
Definition: RtclCmdBase.hpp:36
static const int kOK
Definition: RtclCmdBase.hpp:54
bool GetArgsDump(RtclArgs &args, int &detail)
FIXME_docs.
void DelMeth(const std::string &name)
FIXME_docs.
RtclCmdBase()
FIXME_docs.
Definition: RtclCmdBase.cpp:51
static const int kERR
Definition: RtclCmdBase.hpp:55
int DispatchCmd(RtclArgs &args)
FIXME_docs.
Definition: RtclCmdBase.cpp:64
bool TstMeth(const std::string &name)
FIXME_docs.
Implemenation (inline) of RtclOPtr.
Definition: RtclOPtr.hpp:23
Declaration of class ReventLoop.
Definition: ReventLoop.cpp:47