Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2025-09-17 08:54:00

0001 // Copyright (c) 2017-2025, University of Cincinnati, developed by Henry Schreiner
0002 // under NSF AWARD 1414736 and by the respective contributors.
0003 // All rights reserved.
0004 //
0005 // SPDX-License-Identifier: BSD-3-Clause
0006 
0007 #pragma once
0008 
0009 // IWYU pragma: private, include "CLI/CLI.hpp"
0010 
0011 // [CLI11:public_includes:set]
0012 #include <algorithm>
0013 #include <fstream>
0014 #include <iostream>
0015 #include <memory>
0016 #include <string>
0017 #include <vector>
0018 // [CLI11:public_includes:end]
0019 
0020 #include "Error.hpp"
0021 #include "StringTools.hpp"
0022 
0023 namespace CLI {
0024 // [CLI11:config_fwd_hpp:verbatim]
0025 
0026 class App;
0027 
0028 /// Holds values to load into Options
0029 struct ConfigItem {
0030     /// This is the list of parents
0031     std::vector<std::string> parents{};
0032 
0033     /// This is the name
0034     std::string name{};
0035     /// Listing of inputs
0036     std::vector<std::string> inputs{};
0037     /// @brief indicator if a multiline vector separator was inserted
0038     bool multiline{false};
0039     /// The list of parents and name joined by "."
0040     CLI11_NODISCARD std::string fullname() const {
0041         std::vector<std::string> tmp = parents;
0042         tmp.emplace_back(name);
0043         return detail::join(tmp, ".");
0044         (void)multiline;  // suppression for cppcheck false positive
0045     }
0046 };
0047 
0048 /// This class provides a converter for configuration files.
0049 class Config {
0050   protected:
0051     std::vector<ConfigItem> items{};
0052 
0053   public:
0054     /// Convert an app into a configuration
0055     virtual std::string to_config(const App *, bool, bool, std::string) const = 0;
0056 
0057     /// Convert a configuration into an app
0058     virtual std::vector<ConfigItem> from_config(std::istream &) const = 0;
0059 
0060     /// Get a flag value
0061     CLI11_NODISCARD virtual std::string to_flag(const ConfigItem &item) const {
0062         if(item.inputs.size() == 1) {
0063             return item.inputs.at(0);
0064         }
0065         if(item.inputs.empty()) {
0066             return "{}";
0067         }
0068         throw ConversionError::TooManyInputsFlag(item.fullname());  // LCOV_EXCL_LINE
0069     }
0070 
0071     /// Parse a config file, throw an error (ParseError:ConfigParseError or FileError) on failure
0072     CLI11_NODISCARD std::vector<ConfigItem> from_file(const std::string &name) const {
0073         std::ifstream input{name};
0074         if(!input.good())
0075             throw FileError::Missing(name);
0076 
0077         return from_config(input);
0078     }
0079 
0080     /// Virtual destructor
0081     virtual ~Config() = default;
0082 };
0083 
0084 /// This converter works with INI/TOML files; to write INI files use ConfigINI
0085 class ConfigBase : public Config {
0086   protected:
0087     /// the character used for comments
0088     char commentChar = '#';
0089     /// the character used to start an array '\0' is a default to not use
0090     char arrayStart = '[';
0091     /// the character used to end an array '\0' is a default to not use
0092     char arrayEnd = ']';
0093     /// the character used to separate elements in an array
0094     char arraySeparator = ',';
0095     /// the character used separate the name from the value
0096     char valueDelimiter = '=';
0097     /// the character to use around strings
0098     char stringQuote = '"';
0099     /// the character to use around single characters and literal strings
0100     char literalQuote = '\'';
0101     /// the maximum number of layers to allow
0102     uint8_t maximumLayers{255};
0103     /// the separator used to separator parent layers
0104     char parentSeparatorChar{'.'};
0105     /// comment default values
0106     bool commentDefaultsBool = false;
0107     /// specify the config reader should collapse repeated field names to a single vector
0108     bool allowMultipleDuplicateFields{false};
0109     /// Specify the configuration index to use for arrayed sections
0110     int16_t configIndex{-1};
0111     /// Specify the configuration section that should be used
0112     std::string configSection{};
0113 
0114   public:
0115     std::string
0116     to_config(const App * /*app*/, bool default_also, bool write_description, std::string prefix) const override;
0117 
0118     std::vector<ConfigItem> from_config(std::istream &input) const override;
0119     /// Specify the configuration for comment characters
0120     ConfigBase *comment(char cchar) {
0121         commentChar = cchar;
0122         return this;
0123     }
0124     /// Specify the start and end characters for an array
0125     ConfigBase *arrayBounds(char aStart, char aEnd) {
0126         arrayStart = aStart;
0127         arrayEnd = aEnd;
0128         return this;
0129     }
0130     /// Specify the delimiter character for an array
0131     ConfigBase *arrayDelimiter(char aSep) {
0132         arraySeparator = aSep;
0133         return this;
0134     }
0135     /// Specify the delimiter between a name and value
0136     ConfigBase *valueSeparator(char vSep) {
0137         valueDelimiter = vSep;
0138         return this;
0139     }
0140     /// Specify the quote characters used around strings and literal strings
0141     ConfigBase *quoteCharacter(char qString, char literalChar) {
0142         stringQuote = qString;
0143         literalQuote = literalChar;
0144         return this;
0145     }
0146     /// Specify the maximum number of parents
0147     ConfigBase *maxLayers(uint8_t layers) {
0148         maximumLayers = layers;
0149         return this;
0150     }
0151     /// Specify the separator to use for parent layers
0152     ConfigBase *parentSeparator(char sep) {
0153         parentSeparatorChar = sep;
0154         return this;
0155     }
0156     /// comment default value options
0157     ConfigBase *commentDefaults(bool comDef = true) {
0158         commentDefaultsBool = comDef;
0159         return this;
0160     }
0161     /// get a reference to the configuration section
0162     std::string &sectionRef() { return configSection; }
0163     /// get the section
0164     CLI11_NODISCARD const std::string &section() const { return configSection; }
0165     /// specify a particular section of the configuration file to use
0166     ConfigBase *section(const std::string &sectionName) {
0167         configSection = sectionName;
0168         return this;
0169     }
0170 
0171     /// get a reference to the configuration index
0172     int16_t &indexRef() { return configIndex; }
0173     /// get the section index
0174     CLI11_NODISCARD int16_t index() const { return configIndex; }
0175     /// specify a particular index in the section to use (-1) for all sections to use
0176     ConfigBase *index(int16_t sectionIndex) {
0177         configIndex = sectionIndex;
0178         return this;
0179     }
0180     /// specify that multiple duplicate arguments should be merged even if not sequential
0181     ConfigBase *allowDuplicateFields(bool value = true) {
0182         allowMultipleDuplicateFields = value;
0183         return this;
0184     }
0185 };
0186 
0187 /// the default Config is the TOML file format
0188 using ConfigTOML = ConfigBase;
0189 
0190 /// ConfigINI generates a "standard" INI compliant output
0191 class ConfigINI : public ConfigTOML {
0192 
0193   public:
0194     ConfigINI() {
0195         commentChar = ';';
0196         arrayStart = '\0';
0197         arrayEnd = '\0';
0198         arraySeparator = ' ';
0199         valueDelimiter = '=';
0200     }
0201 };
0202 // [CLI11:config_fwd_hpp:end]
0203 }  // namespace CLI