CLI11
C++11 Command Line Interface Parser
ConfigFwd.hpp
1 #pragma once
2 
3 // Distributed under the 3-Clause BSD License. See accompanying
4 // file LICENSE or https://github.com/CLIUtils/CLI11 for details.
5 
6 #include <algorithm>
7 #include <fstream>
8 #include <iostream>
9 #include <string>
10 
11 #include "CLI/StringTools.hpp"
12 
13 namespace CLI {
14 
15 class App;
16 
17 namespace detail {
18 
20 inline std::string ini_join(std::vector<std::string> args) {
21  std::ostringstream s;
22  size_t start = 0;
23  for(const auto &arg : args) {
24  if(start++ > 0)
25  s << " ";
26 
27  auto it = std::find_if(arg.begin(), arg.end(), [](char ch) { return std::isspace<char>(ch, std::locale()); });
28  if(it == arg.end())
29  s << arg;
30  else if(arg.find_first_of('\"') == std::string::npos)
31  s << '\"' << arg << '\"';
32  else
33  s << '\'' << arg << '\'';
34  }
35 
36  return s.str();
37 }
38 
39 } // namespace detail
40 
42 struct ConfigItem {
44  std::vector<std::string> parents;
45 
47  std::string name;
48 
50  std::vector<std::string> inputs;
51 
53  std::string fullname() const {
54  std::vector<std::string> tmp = parents;
55  tmp.emplace_back(name);
56  return detail::join(tmp, ".");
57  }
58 };
59 
61 class Config {
62  protected:
63  std::vector<ConfigItem> items;
64 
65  public:
67  virtual std::string to_config(const App *, bool, bool, std::string) const = 0;
68 
70  virtual std::vector<ConfigItem> from_config(std::istream &) const = 0;
71 
73  virtual std::string to_flag(const ConfigItem &item) const {
74  if(item.inputs.size() == 1) {
75  return item.inputs.at(0);
76  }
77  throw ConversionError::TooManyInputsFlag(item.fullname());
78  }
79 
81  std::vector<ConfigItem> from_file(const std::string &name) {
82  std::ifstream input{name};
83  if(!input.good())
84  throw FileError::Missing(name);
85 
86  return from_config(input);
87  }
88 
90  virtual ~Config() = default;
91 };
92 
94 class ConfigINI : public Config {
95  public:
96  std::string to_config(const App *, bool default_also, bool write_description, std::string prefix) const override;
97 
98  std::vector<ConfigItem> from_config(std::istream &input) const override {
99  std::string line;
100  std::string section = "default";
101 
102  std::vector<ConfigItem> output;
103 
104  while(getline(input, line)) {
105  std::vector<std::string> items_buffer;
106 
107  detail::trim(line);
108  size_t len = line.length();
109  if(len > 1 && line[0] == '[' && line[len - 1] == ']') {
110  section = line.substr(1, len - 2);
111  } else if(len > 0 && line[0] != ';') {
112  output.emplace_back();
113  ConfigItem &out = output.back();
114 
115  // Find = in string, split and recombine
116  auto pos = line.find('=');
117  if(pos != std::string::npos) {
118  out.name = detail::trim_copy(line.substr(0, pos));
119  std::string item = detail::trim_copy(line.substr(pos + 1));
120  items_buffer = detail::split_up(item);
121  } else {
122  out.name = detail::trim_copy(line);
123  items_buffer = {"ON"};
124  }
125 
126  if(detail::to_lower(section) != "default") {
127  out.parents = {section};
128  }
129 
130  if(out.name.find('.') != std::string::npos) {
131  std::vector<std::string> plist = detail::split(out.name, '.');
132  out.name = plist.back();
133  plist.pop_back();
134  out.parents.insert(out.parents.end(), plist.begin(), plist.end());
135  }
136 
137  out.inputs.insert(std::end(out.inputs), std::begin(items_buffer), std::end(items_buffer));
138  }
139  }
140  return output;
141  }
142 };
143 
144 } // namespace CLI
std::vector< ConfigItem > from_config(std::istream &input) const override
Convert a configuration into an app.
Definition: ConfigFwd.hpp:98
Definition: App.hpp:29
std::vector< std::string > inputs
Listing of inputs.
Definition: ConfigFwd.hpp:50
std::vector< std::string > parents
This is the list of parents.
Definition: ConfigFwd.hpp:44
This converter works with INI files.
Definition: ConfigFwd.hpp:94
virtual std::string to_config(const App *, bool, bool, std::string) const =0
Convert an app into a configuration.
virtual std::string to_flag(const ConfigItem &item) const
Get a flag value.
Definition: ConfigFwd.hpp:73
std::string name
This is the name.
Definition: ConfigFwd.hpp:47
Holds values to load into Options.
Definition: ConfigFwd.hpp:42
Creates a command line program, with very few defaults.
Definition: App.hpp:59
std::vector< ConfigItem > from_file(const std::string &name)
Parse a config file, throw an error (ParseError:ConfigParseError or FileError) on failure...
Definition: ConfigFwd.hpp:81
virtual ~Config()=default
Virtual destructor.
This class provides a converter for configuration files.
Definition: ConfigFwd.hpp:61
std::string fullname() const
The list of parents and name joined by ".".
Definition: ConfigFwd.hpp:53
std::string to_config(const App *, bool default_also, bool write_description, std::string prefix) const override
Convert an app into a configuration.
Definition: Config.hpp:18
virtual std::vector< ConfigItem > from_config(std::istream &) const =0
Convert a configuration into an app.