Reflection for RapidJSON 0.0.17
Reflection for serializing/deserializing with RapidJSON
Loading...
Searching...
No Matches
main.cpp
Go to the documentation of this file.
2#include "./codefactory.h"
4
5#include "resources/config.h"
6
7#include <c++utilities/application/argumentparser.h>
8#include <c++utilities/application/commandlineutils.h>
9#include <c++utilities/conversion/stringconversion.h>
10#include <c++utilities/io/ansiescapecodes.h>
11#include <c++utilities/io/misc.h>
12
13#include <cstring>
14#include <fstream>
15#include <iostream>
16#include <unordered_map>
17
18using namespace std;
19using namespace CppUtilities;
20using namespace CppUtilities::EscapeCodes;
21using namespace ReflectiveRapidJSON;
22
23int main(int argc, char *argv[])
24{
25 SET_APPLICATION_INFO;
26 CMD_UTILS_CONVERT_ARGS_TO_UTF8;
27
28 // setup argument parser
29 ArgumentParser parser;
30 OperationArgument generateArg("generate", '\0', "runs the code generator");
31 generateArg.setImplicit(true);
32 ConfigValueArgument inputFileArg("input-file", '\0', "specifies the input file", { "path" });
33 inputFileArg.setRequired(true);
34 ConfigValueArgument outputFileArg("output-file", '\0', "specifies the output file", { "path" });
35 Argument generatorsArg("generators", '\0', "specifies the generators (by default all generators are enabled)");
36 generatorsArg.setValueNames({ "json", "binary" });
37 generatorsArg.setPreDefinedCompletionValues("json binary");
38 generatorsArg.setRequiredValueCount(Argument::varValueCount);
39 generatorsArg.setCombinable(true);
40 ConfigValueArgument clangOptionsArg("clang-opt", '\0', "specifies arguments/options to be passed to Clang", { "option" });
41 clangOptionsArg.setRequiredValueCount(Argument::varValueCount);
42 ConfigValueArgument logClangOptions("log-clang-opt", '\0', "logs the options passed to Clang");
43 ConfigValueArgument errorResilientArg("error-resilient", '\0', "turns most errors into warnings");
44 HelpArgument helpArg(parser);
45 NoColorArgument noColorArg;
46 generateArg.setSubArguments({ &inputFileArg, &outputFileArg, &generatorsArg, &clangOptionsArg, &logClangOptions, &errorResilientArg });
48 jsonOptions.appendTo(&generateArg);
50 binaryOptions.appendTo(&generateArg);
51 parser.setMainArguments({ &generateArg, &noColorArg, &helpArg });
52
53 // parse arguments
54 parser.parseArgs(argc, argv);
55 if (helpArg.isPresent() || !generateArg.isPresent()) {
56 return 0;
57 }
58
59 // setup output stream
60 ostream *os = nullptr;
61 try {
62 ofstream outputFile;
63 if (outputFileArg.isPresent()) {
64 outputFile.exceptions(ios_base::badbit | ios_base::failbit);
65 outputFile.open(outputFileArg.values(0).front(), ios_base::out | ios_base::trunc | ios_base::binary);
66 os = &outputFile;
67 } else {
68 os = &cout;
69 }
70
71 // compose options passed to the clang tool invocation
72 auto clangOptions = std::vector<std::string_view>();
73 if (clangOptionsArg.isPresent()) {
74 // add additional options specified via CLI argument
75 for (const auto *const value : clangOptionsArg.values(0)) {
76 // split options by ";" - not nice but this eases using CMake generator expressions
77 const auto splittedValues = splitStringSimple<std::vector<std::string_view>>(value, ";");
78 for (const auto &splittedValue : splittedValues) {
79 if (!splittedValue.empty()) {
80 clangOptions.emplace_back(splittedValue);
81 }
82 }
83 }
84 }
85 if (logClangOptions.isPresent()) {
86 cerr << Phrases::Info << "Options passed to clang:" << Phrases::End;
87 for (const auto &opt : clangOptions) {
88 cerr << opt << '\n';
89 }
90 }
91
92 // instantiate the code factory and add generators to it
93 auto factory = CodeFactory(parser.executable(), inputFileArg.values(0), clangOptions, *os);
94 factory.setErrorResilient(errorResilientArg.isPresent());
95 // add specified generators if the --generator argument is present; otherwise add default generators
96 if (generatorsArg.isPresent()) {
97 // define mapping of generator names to generator constructors (add new generators here!)
98 // clang-format off
99 const std::unordered_map<std::string, std::function<void()>> generatorsByName{
100 { "json", factory.bindGenerator<JsonSerializationCodeGenerator, const JsonSerializationCodeGenerator::Options &>(jsonOptions) },
101 { "binary", factory.bindGenerator<BinarySerializationCodeGenerator, const BinarySerializationCodeGenerator::Options &>(binaryOptions) },
102 };
103 // clang-format on
104
105 // find and construct generators by name
106 for (const char *generatorName : generatorsArg.values(0)) {
107 try {
108 generatorsByName.at(generatorName)();
109 } catch (const out_of_range &) {
110 cerr << Phrases::Error << "The specified generator \"" << generatorName << "\" does not exist." << Phrases::End;
111 cerr << "Available generators:";
112 for (const auto &generators : generatorsByName) {
113 cerr << ' ' << generators.first;
114 }
115 cerr << endl;
116 return -5;
117 }
118 }
119 } else {
120 // add default generators
121 factory.addGenerator<JsonSerializationCodeGenerator>(jsonOptions);
122 }
123
124 // read AST elements from input files and run the code generator
125 if (!factory.run()) {
126 cerr << Phrases::Error << "Errors occurred." << Phrases::EndFlush;
127 return -2;
128 }
129
130 } catch (const std::ios_base::failure &failure) {
131 const char *errorMessage = failure.what();
132 if (os) {
133 errorMessage = os->fail() || os->bad() ? "An IO error occurred when writing to the output stream." : "An IO error occurred.";
134 } else {
135 errorMessage = "An IO error when opening output stream.";
136 }
137 cerr << Phrases::Error << errorMessage << Phrases::EndFlush;
138 return -4;
139 }
140
141 return 0;
142}
The BinarySerializationCodeGenerator class generates code for JSON (de)serialization of objects inher...
CodeFactory(std::string_view applicationPath, const std::vector< const char * > &sourceFiles, const std::vector< std::string_view > &clangOptions, std::ostream &os)
Constructs a new instance.
The JsonSerializationCodeGenerator class generates code for JSON (de)serialization of objects inherit...
int main(int argc, char *argv[])
Definition main.cpp:23