From f2487f0b481fae4aa1561e82e8e4aa5b8d0654a0 Mon Sep 17 00:00:00 2001 From: Loïc Collignon Date: Wed, 15 Mar 2017 02:36:22 +0100 Subject: initial commit. MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Change-Id: I5e639061c99b7cc6da3da06ccf19bde683a69e9f Signed-off-by: Loïc Collignon --- src/main.cpp | 197 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 197 insertions(+) create mode 100755 src/main.cpp (limited to 'src/main.cpp') diff --git a/src/main.cpp b/src/main.cpp new file mode 100755 index 00000000..042781c8 --- /dev/null +++ b/src/main.cpp @@ -0,0 +1,197 @@ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "openxc/message_set.hpp" + +#define EXIT_SUCCESS 0 +#define EXIT_UNKNOWN_ERROR 1 +#define EXIT_COMMAND_LINE_ERROR 2 +#define EXIT_PROGRAM_ERROR 3 + +/// @brief Generate the configuration code. +/// @param[in] header Content to be inserted as a header. +/// @param[in] footer Content to be inserted as a footer. +/// @param[in] message_set Configuration read from the json file. +/// @param[in] out Stream to write on. +void generate(const std::string& header, const std::string& footer, const openxc::message_set& message_set, std::ostream& out) +{ + if (header.size()) out << header << "\n"; + else out << "#pragma once\n\n"; + + out << "namespace generated {\n" + << " class configuration_generated\n" + << " {\n" + << " private:\n" + << " can_message_set_t can_message_set_;\n" + << " std::vector> can_message_definition_;\n" + << " std::vector> can_signals_;\n" + << " std::vector> obd2_signals_;\n" + << " public:\n" + << " configuration_generated()\n" + << " : message_set_{0, \"" + << message_set.name() << "\", " + << message_set.buses().size() << ", " + << message_set.messages().size() << ", " + << std::accumulate( + std::begin(message_set.messages()), + std::end(message_set.messages()), + 0, + [](int sum, const std::map::value_type& p) { return sum + p.second.signals().size(); } + ) << ", " + << message_set.commands().size() << ", " + << message_set.diagnostic_messages().size() << "}\n" + << " , can_message_definition_{\n"; + + std::uint32_t count = message_set.messages().size(); + for(const std::map::value_type& m : message_set.messages()) + { + out << " {{\"" << m.second.bus() << "\", " + << m.first << ", " + << "can_message_format_t::STANDARD, frequency_clock_t(), false}}"; + if (count > 1) out << ","; + out << "\n"; + --count; + } + out << " }\n"; + + + out << " , can_signals_" << "..." << "\n" + << " , obd2_signals_" << "..." << "\n" + << " {\n" + << " }\n" + << " };\n" + << "}\n\n"; + + out << footer << std::endl; +} + +/// @brief Read whole file content to a string. +/// @param[in] file Path to the file. +/// @return A std::string which contains the file content. If @c file is an empty string, the return value is also empty. +/// @exception std::runtime_error Throw this exception if the specified file is not found or cannot be opened. +std::string read_file(const std::string& file) +{ + if(file.size() == 0) return std::string(); + + std::string content; + std::ifstream stream(file); + if (stream) + { + stream.seekg(0, std::ios::end); + content.reserve(stream.tellg()); + stream.seekg(0, std::ios::beg); + content.assign((std::istreambuf_iterator(stream)), std::istreambuf_iterator()); + return content; + } + std::stringstream ss; + ss << "The specified file (" << file << ") is not found!"; + throw std::runtime_error(ss.str()); +} + +/// @brief Read whole file content as a json document. +/// @param[in] file Path to the file. +/// @return A @c nlohmann::json object. +/// @exception std::runtime_error Throw this exception if the specified file is not found or cannot be opened. +nlohmann::json read_json(const std::string& file) +{ + std::ifstream stream(file); + if (stream) + { + nlohmann::json result; + stream >> result; + return result; + } + std::stringstream ss; + ss << "The specified file (" << file << ") is not found!"; + throw std::runtime_error(ss.str()); +} + +/// @brief Entry point. +/// @param[in] argc Argument's count. +/// @param[in] argv Argument's array. +/// @return Exit code, zero if success. +int main(int argc, char** argv) +{ + std::ios::sync_with_stdio(false); + + try + { + std::string appName = boost::filesystem::basename(argv[0]); + std::string message_set_file; + std::string output_file; + std::string header_file; + std::string footer_file; + + namespace bpo = boost::program_options; + bpo::options_description desc("Options"); + desc.add_options() + ("help,h", "Display this help.") + ("message-set,m", bpo::value(&message_set_file)->required(), "The message set definition file.") + ("output,o", bpo::value(&output_file), "An output file, if not specified stdout is used.") + ("header,h", bpo::value(&header_file), "A file to copy at the top of the generated output.") + ("footer,f", bpo::value(&footer_file), "A file to copy at the end of the generated output."); + + bpo::variables_map vm; + try + { + bpo::store(bpo::parse_command_line(argc, argv, desc), vm); + + if (vm.count("help")) + { + std::cout << desc << std::endl; + return EXIT_SUCCESS; + } + + bpo::notify(vm); + + std::string header = read_file(header_file); + std::string footer = read_file(footer_file); + openxc::message_set message_set; + message_set.from_json(read_json(message_set_file)); + std::ofstream out; + if (output_file.size()) + { + out = std::ofstream(output_file); + if(!out) + { + std::stringstream ss; + ss << "Can't open the ouput file (" << output_file << ") for writing!"; + throw std::runtime_error(ss.str()); + } + } + + generate(header, footer, message_set, output_file.size() ? out : std::cout); + + } + catch (bpo::required_option& e) + { + std::cerr << "ERROR: Argument required - " << e.what() << std::endl; + std::cout << desc << std::endl; + return EXIT_COMMAND_LINE_ERROR; + } + catch (bpo::error& e) + { + std::cerr << "ERROR: Command line error - " << e.what() << std::endl; + std::cout << desc << std::endl; + return EXIT_COMMAND_LINE_ERROR; + } + catch(std::exception& e) + { + std::cerr << "ERROR: " << e.what() << std::endl; + return EXIT_PROGRAM_ERROR; + } + } + catch (std::exception& e) + { + std::cerr << "ERROR: Unhandled exception - " << e.what() << std::endl; + return EXIT_UNKNOWN_ERROR; + } + + return EXIT_SUCCESS; +} -- cgit 1.2.3-korg