mirror of
https://github.com/Zygo/bees.git
synced 2025-05-17 21:35:45 +02:00
crucible: remove ArgList and drop the unimplemented interpreter classes
Signed-off-by: Zygo Blaxell <bees@furryterror.org>
This commit is contained in:
parent
e8eaa7e471
commit
4a9f26d12e
@ -1,106 +0,0 @@
|
|||||||
#ifndef CRUCIBLE_INTERP_H
|
|
||||||
#define CRUCIBLE_INTERP_H
|
|
||||||
|
|
||||||
#include "crucible/error.h"
|
|
||||||
|
|
||||||
#include <map>
|
|
||||||
#include <memory>
|
|
||||||
#include <string>
|
|
||||||
#include <vector>
|
|
||||||
|
|
||||||
namespace crucible {
|
|
||||||
using namespace std;
|
|
||||||
|
|
||||||
struct ArgList : public vector<string> {
|
|
||||||
ArgList(const char **argv);
|
|
||||||
// using vector<string>::vector ... doesn't work:
|
|
||||||
// error: ‘std::vector<std::basic_string<char> >::vector’ names constructor
|
|
||||||
// Still doesn't work in 4.9 because it can't manage a conversion
|
|
||||||
ArgList(const vector<string> &&that);
|
|
||||||
};
|
|
||||||
|
|
||||||
struct ArgActor {
|
|
||||||
struct ArgActorBase {
|
|
||||||
virtual void predicate(void *obj, string arg);
|
|
||||||
};
|
|
||||||
|
|
||||||
template <class T>
|
|
||||||
struct ArgActorDerived {
|
|
||||||
function<void(T, string)> m_func;
|
|
||||||
|
|
||||||
ArgActorDerived(decltype(m_func) func) :
|
|
||||||
m_func(func)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
void predicate(void *obj, string arg) override
|
|
||||||
{
|
|
||||||
T &op = *(reinterpret_cast<T*>(obj));
|
|
||||||
m_func(op, obj);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
template <class T>
|
|
||||||
ArgActor(T, function<void(T, string)> func) :
|
|
||||||
m_actor(make_shared(ArgActorDerived<T>(func)))
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
ArgActor() = default;
|
|
||||||
|
|
||||||
void predicate(void *t, string arg)
|
|
||||||
{
|
|
||||||
if (m_actor) {
|
|
||||||
m_actor->predicate(t, arg);
|
|
||||||
} else {
|
|
||||||
THROW_ERROR(invalid_argument, "null m_actor for predicate arg '" << arg << "'");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private:
|
|
||||||
shared_ptr<ArgActorBase> m_actor;
|
|
||||||
};
|
|
||||||
|
|
||||||
struct ArgParser {
|
|
||||||
~ArgParser();
|
|
||||||
ArgParser();
|
|
||||||
|
|
||||||
void add_opt(string opt, ArgActor actor);
|
|
||||||
|
|
||||||
template <class T>
|
|
||||||
void
|
|
||||||
parse(T t, const ArgList &args)
|
|
||||||
{
|
|
||||||
void *vt = &t;
|
|
||||||
parse_backend(vt, args);
|
|
||||||
}
|
|
||||||
|
|
||||||
private:
|
|
||||||
void parse_backend(void *t, const ArgList &args);
|
|
||||||
map<string, ArgActor> m_string_opts;
|
|
||||||
};
|
|
||||||
|
|
||||||
struct Command {
|
|
||||||
virtual ~Command();
|
|
||||||
virtual int exec(const ArgList &args) = 0;
|
|
||||||
};
|
|
||||||
|
|
||||||
struct Proc : public Command {
|
|
||||||
int exec(const ArgList &args) override;
|
|
||||||
Proc(const function<int(const ArgList &)> &f);
|
|
||||||
private:
|
|
||||||
function<int(const ArgList &)> m_cmd;
|
|
||||||
};
|
|
||||||
|
|
||||||
struct Interp {
|
|
||||||
virtual ~Interp();
|
|
||||||
Interp(const map<string, shared_ptr<Command> > &cmdlist);
|
|
||||||
void add_command(const string &name, const shared_ptr<Command> &command);
|
|
||||||
int exec(const ArgList &args);
|
|
||||||
private:
|
|
||||||
Interp(const Interp &) = delete;
|
|
||||||
map<string, shared_ptr<Command> > m_commands;
|
|
||||||
};
|
|
||||||
|
|
||||||
};
|
|
||||||
#endif // CRUCIBLE_INTERP_H
|
|
@ -8,7 +8,6 @@ OBJS = \
|
|||||||
extentwalker.o \
|
extentwalker.o \
|
||||||
fd.o \
|
fd.o \
|
||||||
fs.o \
|
fs.o \
|
||||||
interp.o \
|
|
||||||
ntoa.o \
|
ntoa.o \
|
||||||
path.o \
|
path.o \
|
||||||
process.o \
|
process.o \
|
||||||
|
@ -1,96 +0,0 @@
|
|||||||
#include "crucible/interp.h"
|
|
||||||
|
|
||||||
#include "crucible/chatter.h"
|
|
||||||
|
|
||||||
namespace crucible {
|
|
||||||
using namespace std;
|
|
||||||
|
|
||||||
int
|
|
||||||
Proc::exec(const ArgList &args)
|
|
||||||
{
|
|
||||||
return m_cmd(args);
|
|
||||||
}
|
|
||||||
|
|
||||||
Proc::Proc(const function<int(const ArgList &)> &f) :
|
|
||||||
m_cmd(f)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
Command::~Command()
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
ArgList::ArgList(const char **argv)
|
|
||||||
{
|
|
||||||
while (argv && *argv) {
|
|
||||||
push_back(*argv++);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
ArgList::ArgList(const vector<string> &&that) :
|
|
||||||
vector<string>(that)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
Interp::~Interp()
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
Interp::Interp(const map<string, shared_ptr<Command> > &cmdlist) :
|
|
||||||
m_commands(cmdlist)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
|
||||||
Interp::add_command(const string &name, const shared_ptr<Command> &command)
|
|
||||||
{
|
|
||||||
m_commands[name] = command;
|
|
||||||
}
|
|
||||||
|
|
||||||
int
|
|
||||||
Interp::exec(const ArgList &args)
|
|
||||||
{
|
|
||||||
auto next_arg = args.begin();
|
|
||||||
++next_arg;
|
|
||||||
return m_commands.at(args[0])->exec(vector<string>(next_arg, args.end()));
|
|
||||||
}
|
|
||||||
|
|
||||||
ArgParser::~ArgParser()
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
ArgParser::ArgParser()
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
|
||||||
ArgParser::add_opt(string opt, ArgActor actor)
|
|
||||||
{
|
|
||||||
m_string_opts[opt] = actor;
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
|
||||||
ArgParser::parse_backend(void *t, const ArgList &args)
|
|
||||||
{
|
|
||||||
bool quote_args = false;
|
|
||||||
for (string arg : args) {
|
|
||||||
if (quote_args) {
|
|
||||||
cerr << "arg: '" << arg << "'" << endl;
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
if (arg == "--") {
|
|
||||||
quote_args = true;
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
if (arg.compare(0, 2, "--") == 0) {
|
|
||||||
auto found = m_string_opts.find(arg.substr(2, string::npos));
|
|
||||||
if (found != m_string_opts.end()) {
|
|
||||||
found->second.predicate(t, "foo");
|
|
||||||
}
|
|
||||||
(void)t;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
};
|
|
11
src/bees.cc
11
src/bees.cc
@ -1,7 +1,6 @@
|
|||||||
#include "bees-version.h"
|
#include "bees-version.h"
|
||||||
#include "bees.h"
|
#include "bees.h"
|
||||||
|
|
||||||
#include "crucible/interp.h"
|
|
||||||
#include "crucible/limits.h"
|
#include "crucible/limits.h"
|
||||||
#include "crucible/process.h"
|
#include "crucible/process.h"
|
||||||
#include "crucible/string.h"
|
#include "crucible/string.h"
|
||||||
@ -25,7 +24,7 @@ using namespace crucible;
|
|||||||
using namespace std;
|
using namespace std;
|
||||||
|
|
||||||
int
|
int
|
||||||
do_cmd_help(const ArgList &argv)
|
do_cmd_help(const char **argv)
|
||||||
{
|
{
|
||||||
cerr << "Usage: " << argv[0] << " fs-root-path [fs-root-path-2...]\n"
|
cerr << "Usage: " << argv[0] << " fs-root-path [fs-root-path-2...]\n"
|
||||||
"Performs best-effort extent-same deduplication on btrfs.\n"
|
"Performs best-effort extent-same deduplication on btrfs.\n"
|
||||||
@ -555,8 +554,10 @@ BeesTempFile::make_copy(const BeesFileRange &src)
|
|||||||
}
|
}
|
||||||
|
|
||||||
int
|
int
|
||||||
bees_main(ArgList args)
|
bees_main(int argc, const char **argv)
|
||||||
{
|
{
|
||||||
|
vector<string> args(argv, argv + argc);
|
||||||
|
|
||||||
set_catch_explainer([&](string s) {
|
set_catch_explainer([&](string s) {
|
||||||
BEESLOG("\n\n*** EXCEPTION ***\n\t" << s << "\n***\n");
|
BEESLOG("\n\n*** EXCEPTION ***\n\t" << s << "\n***\n");
|
||||||
BEESCOUNT(exception_caught);
|
BEESCOUNT(exception_caught);
|
||||||
@ -603,11 +604,9 @@ main(int argc, const char **argv)
|
|||||||
return 2;
|
return 2;
|
||||||
}
|
}
|
||||||
|
|
||||||
ArgList args(argv + 1);
|
|
||||||
|
|
||||||
int rv = 1;
|
int rv = 1;
|
||||||
catch_and_explain([&]() {
|
catch_and_explain([&]() {
|
||||||
rv = bees_main(args);
|
rv = bees_main(argc, argv);
|
||||||
});
|
});
|
||||||
return rv;
|
return rv;
|
||||||
}
|
}
|
||||||
|
@ -3,7 +3,6 @@ PROGRAMS = \
|
|||||||
crc64 \
|
crc64 \
|
||||||
execpipe \
|
execpipe \
|
||||||
fd \
|
fd \
|
||||||
interp \
|
|
||||||
limits \
|
limits \
|
||||||
path \
|
path \
|
||||||
process \
|
process \
|
||||||
|
@ -1,88 +0,0 @@
|
|||||||
#include "tests.h"
|
|
||||||
|
|
||||||
#include "crucible/interp.h"
|
|
||||||
|
|
||||||
using namespace crucible;
|
|
||||||
using namespace std;
|
|
||||||
|
|
||||||
/***********************************************************************
|
|
||||||
|
|
||||||
How this should work:
|
|
||||||
|
|
||||||
Interpreter reads an arg list:
|
|
||||||
|
|
||||||
argv[0] --method0args --method1arg arg1 --method1arg=arg1 -- args...
|
|
||||||
|
|
||||||
argv[0] should look up a shared_ptr<Command> which creates an object of
|
|
||||||
type shared_ptr<Process>. This object is used to receive args by
|
|
||||||
method calls or one at a time.
|
|
||||||
|
|
||||||
<Command> and <Process> can be the same object, or not.
|
|
||||||
|
|
||||||
Process p methods:
|
|
||||||
|
|
||||||
p->spawn(Interp*) -> Process
|
|
||||||
p->exec(ArgList) -> Process / Result
|
|
||||||
p->method (from ArgParser<>)
|
|
||||||
p->finish() -> void (destroys object without early destruction warnings...?)
|
|
||||||
p->~Process() -> complains loudly if finish() not called first...?
|
|
||||||
|
|
||||||
Result might be a pair of Process, string. Or just string.
|
|
||||||
|
|
||||||
ArgParser should be more like GetOpt:
|
|
||||||
|
|
||||||
build a dictionary and an arg list from arguments
|
|
||||||
Process methods should interrogate ArgParser
|
|
||||||
ArgParser might have a table of boolean and string option names so it can reject invalid options
|
|
||||||
but if it had that, we could also pass in Process and have it call methods on it
|
|
||||||
...but that is a _lot_ of pointer-hiding when we could KISS
|
|
||||||
...but if we had that solved, argparser tables look like lists of method names
|
|
||||||
ArgParser<T> has a table of names and methods on object of type T
|
|
||||||
ArgParser hides everything behind void* and hands off to a compiled implementation to do callbacks
|
|
||||||
|
|
||||||
Extreme simplification: arguments are themselves executable
|
|
||||||
|
|
||||||
so '--method_foo arg' really means construct MethodFoo(arg) and cast to shared_ptr<ProcArg>
|
|
||||||
then Process->invokeSomething(ProcArg)
|
|
||||||
too extreme, use argparser instead
|
|
||||||
|
|
||||||
***********************************************************************/
|
|
||||||
|
|
||||||
void
|
|
||||||
test_arg_parser()
|
|
||||||
{
|
|
||||||
ArgParser ap;
|
|
||||||
ArgList al( { "abc", "--def", "ghi" } );
|
|
||||||
ap.parse(NULL, al);
|
|
||||||
}
|
|
||||||
|
|
||||||
struct Thing {
|
|
||||||
int m_i;
|
|
||||||
double m_d;
|
|
||||||
string m_s;
|
|
||||||
|
|
||||||
void set_i(int i) { cerr << "i = " << i << endl; m_i = i; }
|
|
||||||
void set_d(double d) { cerr << "d = " << d << endl; m_d = d; }
|
|
||||||
void set_s(string s) { cerr << "s = " << s << endl; m_s = s; }
|
|
||||||
};
|
|
||||||
|
|
||||||
template <typename F, typename T, typename A>
|
|
||||||
void
|
|
||||||
assign(T& t, F f, A a)
|
|
||||||
{
|
|
||||||
cerr << __PRETTY_FUNCTION__ << " - a = " << a << endl;
|
|
||||||
(t.*f)(a);
|
|
||||||
}
|
|
||||||
|
|
||||||
int
|
|
||||||
main(int, char**)
|
|
||||||
{
|
|
||||||
RUN_A_TEST(test_arg_parser());
|
|
||||||
|
|
||||||
Thing p;
|
|
||||||
assign(p, &Thing::set_i, 5);
|
|
||||||
|
|
||||||
cerr << "p.m_i = " << p.m_i << endl;
|
|
||||||
|
|
||||||
exit(EXIT_SUCCESS);
|
|
||||||
}
|
|
Loading…
x
Reference in New Issue
Block a user