Use hash map to find specified code generator

So adding further generators will not result in having
a lot of "else if (!strcmp(..." conditions.

This also allows to improve the error message.
This commit is contained in:
Martchus 2018-02-02 18:21:04 +01:00
parent 1eaa2d52c2
commit 0d2f39a2b5
3 changed files with 44 additions and 6 deletions

View File

@ -3,6 +3,7 @@
#include "./codegenerator.h"
#include <functional>
#include <iosfwd>
#include <memory>
#include <string>
@ -34,6 +35,7 @@ public:
const std::vector<std::unique_ptr<CodeGenerator>> &generators() const;
template <typename GeneratorType, typename... Args> void addGenerator(Args &&... args);
template <typename GeneratorType, typename... Args> auto bindGenerator(Args &&... args);
bool run();
clang::CompilerInstance *compilerInstance();
@ -60,6 +62,28 @@ template <typename GeneratorType, typename... Args> void CodeFactory::addGenerat
m_generators.emplace_back(std::make_unique<GeneratorType>(*this, std::forward<Args>(args)...));
}
namespace Detail {
template <typename T> std::reference_wrapper<const T> wrapReferences(const T &val)
{
return std::cref(val);
}
template <typename T> std::reference_wrapper<T> wrapReferences(T &val)
{
return std::ref(val);
}
template <typename T> T &&wrapReferences(T &&val)
{
return std::forward<T>(val);
}
} // namespace Detail
template <typename GeneratorType, typename... Args> auto CodeFactory::bindGenerator(Args &&... args)
{
return std::bind(&CodeFactory::addGenerator<GeneratorType, Args...>, this, Detail::wrapReferences(std::forward<Args>(args)...));
}
inline const std::vector<std::unique_ptr<CodeGenerator>> &CodeFactory::generators() const
{
return m_generators;

View File

@ -15,6 +15,7 @@ class JsonSerializationCodeGenerator : public CodeGenerator {
public:
struct Options {
Options();
Options(const Options &other) = delete;
void appendTo(ApplicationUtilities::Argument *arg);
ApplicationUtilities::ConfigValueArgument additionalClassesArg;

View File

@ -14,6 +14,7 @@
#include <cstring>
#include <fstream>
#include <iostream>
#include <unordered_map>
using namespace std;
using namespace ApplicationUtilities;
@ -80,16 +81,28 @@ int main(int argc, char *argv[])
}
}
// configure code generator
// instantiate the code factory and add generators to it
CodeFactory factory(parser.executable(), inputFileArg.values(0), clangOptions, *os);
// add only specified generators if the --generator argument is present
// add specified generators if the --generator argument is present; otherwise add default generators
if (generatorsArg.isPresent()) {
// define mapping of generator names to generator constructions (add new generators here!)
// clang-format off
const std::unordered_map<std::string, std::function<void()>> generatorsByName{
{ "json", factory.bindGenerator<JsonSerializationCodeGenerator, const JsonSerializationCodeGenerator::Options &>(jsonOptions) }
};
// clang-format on
// find and construct generators by name
for (const char *generatorName : generatorsArg.values(0)) {
if (!strcmp(generatorName, "json")) {
factory.addGenerator<JsonSerializationCodeGenerator>(jsonOptions);
} else {
cerr << Phrases::Error << "The specified generator \"" << generatorName << "\" does not exist." << Phrases::EndFlush;
try {
generatorsByName.at(generatorName)();
} catch (const out_of_range &) {
cerr << Phrases::Error << "The specified generator \"" << generatorName << "\" does not exist." << Phrases::End;
cerr << "Available generators:";
for (const auto &generators : generatorsByName) {
cerr << ' ' << generators.first;
}
cerr << endl;
return -5;
}
}