config.h (2656B)
1 /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ 2 /* vim: set ts=2 et sw=2 tw=80: */ 3 /* This Source Code Form is subject to the terms of the Mozilla Public 4 * License, v. 2.0. If a copy of the MPL was not distributed with this file, 5 * You can obtain one at http://mozilla.org/MPL/2.0/. */ 6 7 // Generic command line flags system for NSS BoGo shim. This class 8 // could actually in principle handle other programs. The flags are 9 // defined in the consumer code. 10 11 #ifndef config_h_ 12 #define config_h_ 13 14 #include <cassert> 15 16 #include <iostream> 17 #include <map> 18 #include <memory> 19 #include <queue> 20 #include <string> 21 #include <typeinfo> 22 23 // Abstract base class for a given config flag. 24 class ConfigEntryBase { 25 public: 26 ConfigEntryBase(const std::string& nm, const std::string& typ) 27 : name_(nm), type_(typ) {} 28 29 virtual ~ConfigEntryBase() {} 30 31 const std::string& type() const { return type_; } 32 virtual bool Parse(std::queue<const char*>& args) = 0; 33 34 protected: 35 bool ParseInternal(std::queue<const char*>& args, std::vector<int>& out); 36 bool ParseInternal(std::queue<const char*>& args, std::string& out); 37 bool ParseInternal(std::queue<const char*>& args, int& out); 38 bool ParseInternal(std::queue<const char*>& args, bool& out); 39 40 const std::string name_; 41 const std::string type_; 42 }; 43 44 // Template specializations for the concrete flag types. 45 template <typename T> 46 class ConfigEntry : public ConfigEntryBase { 47 public: 48 ConfigEntry(const std::string& name, T init) 49 : ConfigEntryBase(name, typeid(T).name()), value_(init) {} 50 T get() const { return value_; } 51 52 bool Parse(std::queue<const char*>& args) { 53 return ParseInternal(args, value_); 54 } 55 56 private: 57 T value_; 58 }; 59 60 // The overall configuration (I.e., the total set of flags). 61 class Config { 62 public: 63 enum Status { kOK, kUnknownFlag, kMalformedArgument, kMissingValue }; 64 65 Config() : entries_() {} 66 67 template <typename T> 68 void AddEntry(const std::string& name, T init) { 69 entries_[name] = 70 std::unique_ptr<ConfigEntryBase>(new ConfigEntry<T>(name, init)); 71 } 72 73 Status ParseArgs(int argc, char** argv); 74 75 template <typename T> 76 T get(const std::string& key) const { 77 auto e = entry(key); 78 assert(e->type() == typeid(T).name()); 79 return static_cast<const ConfigEntry<T>*>(e)->get(); 80 } 81 82 private: 83 static std::string XformFlag(const std::string& arg); 84 85 std::map<std::string, std::unique_ptr<ConfigEntryBase>> entries_; 86 87 const ConfigEntryBase* entry(const std::string& key) const { 88 auto e = entries_.find(key); 89 if (e == entries_.end()) return nullptr; 90 return e->second.get(); 91 } 92 }; 93 94 #endif // config_h_