File indexing completed on 2025-07-05 08:51:42
0001
0002
0003
0004
0005
0006
0007 #pragma once
0008
0009
0010
0011
0012 #include <algorithm>
0013 #include <fstream>
0014 #include <iostream>
0015 #include <memory>
0016 #include <string>
0017 #include <vector>
0018
0019
0020 #include "Error.hpp"
0021 #include "StringTools.hpp"
0022
0023 namespace CLI {
0024
0025
0026 class App;
0027
0028
0029 struct ConfigItem {
0030
0031 std::vector<std::string> parents{};
0032
0033
0034 std::string name{};
0035
0036 std::vector<std::string> inputs{};
0037
0038
0039 CLI11_NODISCARD std::string fullname() const {
0040 std::vector<std::string> tmp = parents;
0041 tmp.emplace_back(name);
0042 return detail::join(tmp, ".");
0043 }
0044 };
0045
0046
0047 class Config {
0048 protected:
0049 std::vector<ConfigItem> items{};
0050
0051 public:
0052
0053 virtual std::string to_config(const App *, bool, bool, std::string) const = 0;
0054
0055
0056 virtual std::vector<ConfigItem> from_config(std::istream &) const = 0;
0057
0058
0059 CLI11_NODISCARD virtual std::string to_flag(const ConfigItem &item) const {
0060 if(item.inputs.size() == 1) {
0061 return item.inputs.at(0);
0062 }
0063 if(item.inputs.empty()) {
0064 return "{}";
0065 }
0066 throw ConversionError::TooManyInputsFlag(item.fullname());
0067 }
0068
0069
0070 CLI11_NODISCARD std::vector<ConfigItem> from_file(const std::string &name) const {
0071 std::ifstream input{name};
0072 if(!input.good())
0073 throw FileError::Missing(name);
0074
0075 return from_config(input);
0076 }
0077
0078
0079 virtual ~Config() = default;
0080 };
0081
0082
0083 class ConfigBase : public Config {
0084 protected:
0085
0086 char commentChar = '#';
0087
0088 char arrayStart = '[';
0089
0090 char arrayEnd = ']';
0091
0092 char arraySeparator = ',';
0093
0094 char valueDelimiter = '=';
0095
0096 char stringQuote = '"';
0097
0098 char literalQuote = '\'';
0099
0100 uint8_t maximumLayers{255};
0101
0102 char parentSeparatorChar{'.'};
0103
0104 int16_t configIndex{-1};
0105
0106 std::string configSection{};
0107
0108 public:
0109 std::string
0110 to_config(const App * , bool default_also, bool write_description, std::string prefix) const override;
0111
0112 std::vector<ConfigItem> from_config(std::istream &input) const override;
0113
0114 ConfigBase *comment(char cchar) {
0115 commentChar = cchar;
0116 return this;
0117 }
0118
0119 ConfigBase *arrayBounds(char aStart, char aEnd) {
0120 arrayStart = aStart;
0121 arrayEnd = aEnd;
0122 return this;
0123 }
0124
0125 ConfigBase *arrayDelimiter(char aSep) {
0126 arraySeparator = aSep;
0127 return this;
0128 }
0129
0130 ConfigBase *valueSeparator(char vSep) {
0131 valueDelimiter = vSep;
0132 return this;
0133 }
0134
0135 ConfigBase *quoteCharacter(char qString, char literalChar) {
0136 stringQuote = qString;
0137 literalQuote = literalChar;
0138 return this;
0139 }
0140
0141 ConfigBase *maxLayers(uint8_t layers) {
0142 maximumLayers = layers;
0143 return this;
0144 }
0145
0146 ConfigBase *parentSeparator(char sep) {
0147 parentSeparatorChar = sep;
0148 return this;
0149 }
0150
0151 std::string §ionRef() { return configSection; }
0152
0153 CLI11_NODISCARD const std::string §ion() const { return configSection; }
0154
0155 ConfigBase *section(const std::string §ionName) {
0156 configSection = sectionName;
0157 return this;
0158 }
0159
0160
0161 int16_t &indexRef() { return configIndex; }
0162
0163 CLI11_NODISCARD int16_t index() const { return configIndex; }
0164
0165 ConfigBase *index(int16_t sectionIndex) {
0166 configIndex = sectionIndex;
0167 return this;
0168 }
0169 };
0170
0171
0172 using ConfigTOML = ConfigBase;
0173
0174
0175 class ConfigINI : public ConfigTOML {
0176
0177 public:
0178 ConfigINI() {
0179 commentChar = ';';
0180 arrayStart = '\0';
0181 arrayEnd = '\0';
0182 arraySeparator = ' ';
0183 valueDelimiter = '=';
0184 }
0185 };
0186
0187 }