config.h 2.6 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495
  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. // Generic command line flags system for NSS BoGo shim. This class
  7. // could actually in principle handle other programs. The flags are
  8. // defined in the consumer code.
  9. #ifndef config_h_
  10. #define config_h_
  11. #include <cassert>
  12. #include <iostream>
  13. #include <map>
  14. #include <memory>
  15. #include <queue>
  16. #include <string>
  17. #include <typeinfo>
  18. // Abstract base class for a given config flag.
  19. class ConfigEntryBase {
  20. public:
  21. ConfigEntryBase(const std::string& nm, const std::string& typ)
  22. : name_(nm), type_(typ) {}
  23. virtual ~ConfigEntryBase() {}
  24. const std::string& type() const { return type_; }
  25. virtual bool Parse(std::queue<const char*>& args) = 0;
  26. protected:
  27. bool ParseInternal(std::queue<const char*>& args, std::vector<int>& out);
  28. bool ParseInternal(std::queue<const char*>& args, std::string& out);
  29. bool ParseInternal(std::queue<const char*>& args, int& out);
  30. bool ParseInternal(std::queue<const char*>& args, bool& out);
  31. const std::string name_;
  32. const std::string type_;
  33. };
  34. // Template specializations for the concrete flag types.
  35. template <typename T>
  36. class ConfigEntry : public ConfigEntryBase {
  37. public:
  38. ConfigEntry(const std::string& name, T init)
  39. : ConfigEntryBase(name, typeid(T).name()), value_(init) {}
  40. T get() const { return value_; }
  41. bool Parse(std::queue<const char*>& args) {
  42. return ParseInternal(args, value_);
  43. }
  44. private:
  45. T value_;
  46. };
  47. // The overall configuration (I.e., the total set of flags).
  48. class Config {
  49. public:
  50. enum Status { kOK, kUnknownFlag, kMalformedArgument, kMissingValue };
  51. Config() : entries_() {}
  52. template <typename T>
  53. void AddEntry(const std::string& name, T init) {
  54. entries_[name] =
  55. std::unique_ptr<ConfigEntryBase>(new ConfigEntry<T>(name, init));
  56. }
  57. Status ParseArgs(int argc, char** argv);
  58. template <typename T>
  59. T get(const std::string& key) const {
  60. auto e = entry(key);
  61. assert(e->type() == typeid(T).name());
  62. return static_cast<const ConfigEntry<T>*>(e)->get();
  63. }
  64. private:
  65. static std::string XformFlag(const std::string& arg);
  66. std::map<std::string, std::unique_ptr<ConfigEntryBase>> entries_;
  67. const ConfigEntryBase* entry(const std::string& key) const {
  68. auto e = entries_.find(key);
  69. if (e == entries_.end()) return nullptr;
  70. return e->second.get();
  71. }
  72. };
  73. #endif // config_h_