File indexing completed on 2024-09-28 07:02:17
0001
0002
0003
0004
0005
0006
0007 #pragma once
0008
0009
0010 #include <algorithm>
0011 #include <fstream>
0012 #include <iostream>
0013 #include <string>
0014 #include <vector>
0015
0016
0017 #include "Error.hpp"
0018 #include "StringTools.hpp"
0019
0020 namespace CLI {
0021
0022
0023 class App;
0024
0025
0026 struct ConfigItem {
0027
0028 std::vector<std::string> parents{};
0029
0030
0031 std::string name{};
0032
0033
0034 std::vector<std::string> inputs{};
0035
0036
0037 std::string fullname() const {
0038 std::vector<std::string> tmp = parents;
0039 tmp.emplace_back(name);
0040 return detail::join(tmp, ".");
0041 }
0042 };
0043
0044
0045 class Config {
0046 protected:
0047 std::vector<ConfigItem> items{};
0048
0049 public:
0050
0051 virtual std::string to_config(const App *, bool, bool, std::string) const = 0;
0052
0053
0054 virtual std::vector<ConfigItem> from_config(std::istream &) const = 0;
0055
0056
0057 virtual std::string to_flag(const ConfigItem &item) const {
0058 if(item.inputs.size() == 1) {
0059 return item.inputs.at(0);
0060 }
0061 throw ConversionError::TooManyInputsFlag(item.fullname());
0062 }
0063
0064
0065 std::vector<ConfigItem> from_file(const std::string &name) {
0066 std::ifstream input{name};
0067 if(!input.good())
0068 throw FileError::Missing(name);
0069
0070 return from_config(input);
0071 }
0072
0073
0074 virtual ~Config() = default;
0075 };
0076
0077
0078 class ConfigBase : public Config {
0079 protected:
0080
0081 char commentChar = '#';
0082
0083 char arrayStart = '[';
0084
0085 char arrayEnd = ']';
0086
0087 char arraySeparator = ',';
0088
0089 char valueDelimiter = '=';
0090
0091 char stringQuote = '"';
0092
0093 char characterQuote = '\'';
0094
0095 public:
0096 std::string
0097 to_config(const App * , bool default_also, bool write_description, std::string prefix) const override;
0098
0099 std::vector<ConfigItem> from_config(std::istream &input) const override;
0100
0101 ConfigBase *comment(char cchar) {
0102 commentChar = cchar;
0103 return this;
0104 }
0105
0106 ConfigBase *arrayBounds(char aStart, char aEnd) {
0107 arrayStart = aStart;
0108 arrayEnd = aEnd;
0109 return this;
0110 }
0111
0112 ConfigBase *arrayDelimiter(char aSep) {
0113 arraySeparator = aSep;
0114 return this;
0115 }
0116
0117 ConfigBase *valueSeparator(char vSep) {
0118 valueDelimiter = vSep;
0119 return this;
0120 }
0121
0122 ConfigBase *quoteCharacter(char qString, char qChar) {
0123 stringQuote = qString;
0124 characterQuote = qChar;
0125 return this;
0126 }
0127 };
0128
0129
0130 using ConfigTOML = ConfigBase;
0131
0132
0133 class ConfigINI : public ConfigTOML {
0134
0135 public:
0136 ConfigINI() {
0137 commentChar = ';';
0138 arrayStart = '\0';
0139 arrayEnd = '\0';
0140 arraySeparator = ' ';
0141 valueDelimiter = '=';
0142 }
0143 };
0144
0145 }