Explorar o código

Rewritten Option. Introduced Pref.

Now preference key is Pref instead of just string.  It has Option
ID. Now option lookup and setting takes O(1) using Pref object.
Tatsuhiro Tsujikawa %!s(int64=14) %!d(string=hai) anos
pai
achega
3832ed97c6

+ 1 - 1
src/AbstractCommand.cc

@@ -545,7 +545,7 @@ void AbstractCommand::setWriteCheckSocketIf
 namespace {
 // Returns proxy option value for the given protocol.
 const std::string& getProxyOptionFor
-(const std::string& proxyPref, const SharedHandle<Option>& option)
+(const Pref* proxyPref, const SharedHandle<Option>& option)
 {
   if(option->defined(proxyPref)) {
     return option->get(proxyPref);

+ 2 - 2
src/DHTSetup.cc

@@ -212,11 +212,11 @@ void DHTSetup::setup
       taskQueue->addPeriodicTask1(task);
     }
 
-    const std::string& prefEntryPointHost =
+    const Pref* prefEntryPointHost =
       family == AF_INET?PREF_DHT_ENTRY_POINT_HOST:PREF_DHT_ENTRY_POINT_HOST6;
     if(!e->getOption()->get(prefEntryPointHost).empty()) {
       {
-        const std::string& prefEntryPointPort =
+        const Pref* prefEntryPointPort =
           family == AF_INET?PREF_DHT_ENTRY_POINT_PORT:
           PREF_DHT_ENTRY_POINT_PORT6;
         std::pair<std::string, uint16_t> addr

+ 10 - 4
src/NameMatchOptionHandler.cc

@@ -39,16 +39,17 @@
 #include "OptionHandlerException.h"
 #include "a2functional.h"
 #include "Option.h"
+#include "prefs.h"
 
 namespace aria2 {
 
 NameMatchOptionHandler::NameMatchOptionHandler
-(const std::string& optName,
+(const Pref* pref,
  const std::string& description,
  const std::string& defaultValue,
  ARG_TYPE argType,
  char shortName)
-  : optName_(optName),
+  : pref_(pref),
     description_(description),
     defaultValue_(defaultValue),
     id_(0),
@@ -62,7 +63,7 @@ NameMatchOptionHandler::~NameMatchOptionHandler() {}
   
 bool NameMatchOptionHandler::canHandle(const std::string& optName)
 {
-  return optName_ == optName;
+  return pref_->k == optName;
 }
 
 void NameMatchOptionHandler::parse(Option& option, const std::string& arg)
@@ -70,7 +71,7 @@ void NameMatchOptionHandler::parse(Option& option, const std::string& arg)
   try {
     parseArg(option, arg);
   } catch(Exception& e) {
-    throw OPTION_HANDLER_EXCEPTION2(optName_, e);
+    throw OPTION_HANDLER_EXCEPTION2(pref_, e);
   }
 }
 
@@ -89,4 +90,9 @@ std::string NameMatchOptionHandler::toTagString() const
   return strjoin(tags_.begin(), tags_.end(), ", ");
 }
 
+const std::string& NameMatchOptionHandler::getName() const
+{
+  return pref_->k;
+}
+
 } // namespace aria2

+ 4 - 6
src/NameMatchOptionHandler.h

@@ -44,10 +44,11 @@
 namespace aria2 {
 
 class Option;
+class Pref;
 
 class NameMatchOptionHandler : public OptionHandler {
 protected:
-  std::string optName_;
+  const Pref* pref_;
 
   std::string description_;
 
@@ -67,7 +68,7 @@ protected:
 
   virtual void parseArg(Option& option, const std::string& arg) = 0;
 public:
-  NameMatchOptionHandler(const std::string& optName,
+  NameMatchOptionHandler(const Pref* pref,
                          const std::string& description = NO_DESCRIPTION,
                          const std::string& defaultValue = NO_DEFAULT_VALUE,
                          ARG_TYPE argType = REQ_ARG,
@@ -85,10 +86,7 @@ public:
 
   virtual std::string toTagString() const;
 
-  virtual const std::string& getName() const
-  {
-    return optName_;
-  }
+  virtual const std::string& getName() const;
 
   virtual const std::string& getDescription() const
   {

+ 61 - 51
src/Option.cc

@@ -33,43 +33,74 @@
  */
 /* copyright --> */
 #include "Option.h"
-#include "prefs.h"
-#include "A2STR.h"
+
 #include <cstdlib>
 #include <cstring>
 
+#include "prefs.h"
+#include "bitfield.h"
+
 namespace aria2 {
 
-Option::Option() {}
+Option::Option()
+  : table_(option::countOption()),
+    use_((option::countOption()+7)/8)
+{}
 
 Option::~Option() {}
 
-void Option::put(const std::string& name, const std::string& value) {
-  table_[name] = value;
+Option::Option(const Option& option)
+  : table_(option.table_),
+    use_(option.use_)
+{}
+
+Option& Option::operator=(const Option& option)
+{
+  if(this != &option) {
+    table_ = option.table_;
+    use_ = option.use_;
+  }
+  return *this;
 }
 
-bool Option::defined(const std::string& name) const
+namespace {
+
+template<typename V>
+void setBit(V& b, const Pref* pref)
 {
-  return table_.count(name) == 1;
+  b[pref->i/8] |= 128 >> (pref->i%8);
 }
 
-bool Option::blank(const std::string& name) const
+template<typename V>
+void unsetBit(V& b, const Pref* pref)
 {
-  std::map<std::string, std::string>::const_iterator i = table_.find(name);
-  return i == table_.end() || (*i).second.empty();
+  b[pref->i/8] &= ~(128 >> (pref->i%8));
 }
 
-const std::string& Option::get(const std::string& name) const {
-  std::map<std::string, std::string>::const_iterator itr = table_.find(name);
-  if(itr == table_.end()) {
-    return A2STR::NIL;
-  } else {
-    return (*itr).second;
-  }
+} // namespace
+
+void Option::put(const Pref* pref, const std::string& value) {
+  setBit(use_, pref);
+  table_[pref->i] = value;
+}
+
+bool Option::defined(const Pref* pref) const
+{
+  return bitfield::test(use_, use_.size()*8, pref->i);
+}
+
+bool Option::blank(const Pref* pref) const
+{
+  return !defined(pref) || table_[pref->i].empty();
 }
 
-int32_t Option::getAsInt(const std::string& name) const {
-  const std::string& value = get(name);
+const std::string& Option::get(const Pref* pref) const
+{
+  return table_[pref->i];
+}
+
+int32_t Option::getAsInt(const Pref* pref) const {
+  const std::string& value = get(pref);
   if(value.empty()) {
     return 0;
   } else {
@@ -77,8 +108,8 @@ int32_t Option::getAsInt(const std::string& name) const {
   }
 }
 
-int64_t Option::getAsLLInt(const std::string& name) const {
-  const std::string& value = get(name);
+int64_t Option::getAsLLInt(const Pref* pref) const {
+  const std::string& value = get(pref);
   if(value.empty()) {
     return 0;
   } else {
@@ -86,12 +117,12 @@ int64_t Option::getAsLLInt(const std::string& name) const {
   }
 }
 
-bool Option::getAsBool(const std::string& name) const {
-  return get(name) == A2_V_TRUE;
+bool Option::getAsBool(const Pref* pref) const {
+  return get(pref) == A2_V_TRUE;
 }
 
-double Option::getAsDouble(const std::string& name) const {
-  const std::string& value = get(name);
+double Option::getAsDouble(const Pref* pref) const {
+  const std::string& value = get(pref);
   if(value.empty()) {
     return 0.0;
   } else {
@@ -99,37 +130,16 @@ double Option::getAsDouble(const std::string& name) const {
   }
 }
 
-void Option::remove(const std::string& name)
+void Option::remove(const Pref* pref)
 {
-  std::map<std::string, std::string>::iterator i = table_.find(name);
-  if(i != table_.end()) {
-    table_.erase(i);
-  }
+  unsetBit(use_, pref);
+  table_[pref->i].clear();
 }
 
 void Option::clear()
 {
-  table_.clear();
-}
-
-std::map<std::string, std::string>::const_iterator Option::begin() const
-{
-  return table_.begin();
-}
-
-std::map<std::string, std::string>::const_iterator Option::end() const
-{
-  return table_.end();
-}
-
-std::map<std::string, std::string>::iterator Option::begin()
-{
-  return table_.begin();
-}
-
-std::map<std::string, std::string>::iterator Option::end()
-{
-  return table_.end();
+  std::fill(use_.begin(), use_.end(), 0);
+  std::fill(table_.begin(), table_.end(), "");
 }
 
 } // namespace aria2

+ 21 - 18
src/Option.h

@@ -36,42 +36,45 @@
 #define D_OPTION_H
 
 #include "common.h"
+
 #include <string>
-#include <map>
+#include <vector>
 
 namespace aria2 {
 
+class Pref;
+
 class Option {
 private:
-  std::map<std::string, std::string> table_;
+  std::vector<std::string> table_;
+  std::vector<unsigned char> use_;
 public:
   Option();
   ~Option();
+  Option(const Option& option);
+  Option& operator=(const Option& option);
 
-  void put(const std::string& name, const std::string& value);
+  void put(const Pref* pref, const std::string& value);
   // Returns true if name is defined. Otherwise returns false.
   // Note that even if the value is a empty string, this method returns true.
-  bool defined(const std::string& name) const;
+  bool defined(const Pref* pref) const;
   // Returns true if name is not defined or the value is a empty string.
   // Otherwise returns false.
-  bool blank(const std::string& name) const;
-  const std::string& get(const std::string& name) const;
-  int32_t getAsInt(const std::string& name) const;
-  int64_t getAsLLInt(const std::string& name) const;
-  bool getAsBool(const std::string& name) const;
-  double getAsDouble(const std::string& name) const;
+  bool blank(const Pref* pref) const;
+  const std::string& get(const Pref* pref) const;
+  int32_t getAsInt(const Pref* pref) const;
+  int64_t getAsLLInt(const Pref* pref) const;
+  bool getAsBool(const Pref* pref) const;
+  double getAsDouble(const Pref* pref) const;
   
-  void remove(const std::string& name);
+  void remove(const Pref* pref);
 
   void clear();
 
-  std::map<std::string, std::string>::const_iterator begin() const;
-
-  std::map<std::string, std::string>::const_iterator end() const;
-
-  std::map<std::string, std::string>::iterator begin();
-
-  std::map<std::string, std::string>::iterator end();
+  const std::vector<std::string>& getTable()
+  {
+    return table_;
+  }
 };
 
 } // namespace aria2

+ 20 - 13
src/OptionHandlerException.cc

@@ -34,31 +34,38 @@
 /* copyright --> */
 #include "OptionHandlerException.h"
 #include "fmt.h"
+#include "prefs.h"
 
 namespace aria2 {
 
 const std::string OptionHandlerException::MESSAGE
 ("We encountered a problem while processing the option '--%s'.");
 
-OptionHandlerException::OptionHandlerException(const char* file, int line,
-                                               const std::string& optName):
-  RecoverableException
-  (file, line, fmt(MESSAGE.c_str(), optName.c_str()), error_code::OPTION_ERROR),
-  optName_(optName) {}
+OptionHandlerException::OptionHandlerException
+(const char* file, int line,
+ const Pref* pref)
+  : RecoverableException
+    (file, line, fmt(MESSAGE.c_str(), pref->k.c_str()),
+     error_code::OPTION_ERROR),
+    pref_(pref)
+{}
 
-OptionHandlerException::OptionHandlerException(const char* file, int line,
-                                               const std::string& optName,
-                                               const Exception& cause):
-  RecoverableException
-  (file, line, fmt(MESSAGE.c_str(), optName.c_str()), error_code::OPTION_ERROR,
-   cause),
-  optName_(optName) {}
+OptionHandlerException::OptionHandlerException
+(const char* file, int line,
+ const Pref* pref,
+ const Exception& cause)
+  : RecoverableException
+    (file, line, fmt(MESSAGE.c_str(), pref->k.c_str()),
+     error_code::OPTION_ERROR,
+     cause),
+    pref_(pref)
+{}
 
 OptionHandlerException::~OptionHandlerException() throw() {}
 
 const std::string& OptionHandlerException::getOptionName() const throw()
 {
-  return optName_;
+  return pref_->k;
 }
 
 SharedHandle<Exception> OptionHandlerException::copy() const

+ 6 - 3
src/OptionHandlerException.h

@@ -38,18 +38,21 @@
 
 namespace aria2 {
 
+class Pref;
+
 class OptionHandlerException:public RecoverableException {
 private:
-  std::string optName_;
+  const Pref* pref_;
 
   static const std::string MESSAGE;
 protected:
   virtual SharedHandle<Exception> copy() const;
 public:
   OptionHandlerException(const char* file, int line,
-                         const std::string& optName);
+                         const Pref* pref);
 
-  OptionHandlerException(const char* file, int line, const std::string& optName,
+  OptionHandlerException(const char* file, int line,
+                         const Pref* pref,
                          const Exception& cause);
 
   virtual ~OptionHandlerException() throw();

+ 2 - 2
src/OptionHandlerFactory.cc

@@ -1781,7 +1781,7 @@ OptionHandlers OptionHandlerFactory::createOptionHandlers()
   // Version Option
   {
     SharedHandle<OptionHandler> op(new DefaultOptionHandler
-                                   ("version",
+                                   (PREF_VERSION,
                                     TEXT_VERSION,
                                     NO_DEFAULT_VALUE,
                                     A2STR::NIL,
@@ -1812,7 +1812,7 @@ OptionHandlers OptionHandlerFactory::createOptionHandlers()
     };
     static std::string tagsStr = strjoin(vbegin(tags), vend(tags), ", ");
     SharedHandle<OptionHandler> op(new DefaultOptionHandler
-                                   ("help",
+                                   (PREF_HELP,
                                     TEXT_HELP,
                                     TAG_BASIC,
                                     tagsStr,

+ 71 - 71
src/OptionHandlerImpl.cc

@@ -127,12 +127,12 @@ bool NullOptionHandler::getEraseAfterParse() const
 void NullOptionHandler::setEraseAfterParse(bool eraseAfterParse) {}
 
 BooleanOptionHandler::BooleanOptionHandler
-(const std::string& optName,
+(const Pref* pref,
  const std::string& description,
  const std::string& defaultValue,
  OptionHandler::ARG_TYPE argType,
  char shortName)
-  : NameMatchOptionHandler(optName, description, defaultValue,
+  : NameMatchOptionHandler(pref, description, defaultValue,
                            argType, shortName)
 {}
 
@@ -144,11 +144,11 @@ void BooleanOptionHandler::parseArg(Option& option, const std::string& optarg)
      ((argType_ == OptionHandler::OPT_ARG ||
        argType_ == OptionHandler::NO_ARG)
       && optarg.empty())) {
-    option.put(optName_, A2_V_TRUE);
+    option.put(pref_, A2_V_TRUE);
   } else if(optarg == "false") {
-    option.put(optName_, A2_V_FALSE);
+    option.put(pref_, A2_V_FALSE);
   } else {
-    std::string msg = optName_;
+    std::string msg = pref_->k;
     strappend(msg, " ", _("must be either 'true' or 'false'."));
     throw DL_ABORT_EX(msg);
   }
@@ -160,12 +160,12 @@ std::string BooleanOptionHandler::createPossibleValuesString() const
 }
 
 IntegerRangeOptionHandler::IntegerRangeOptionHandler
-(const std::string& optName,
+(const Pref* pref,
  const std::string& description,
  const std::string& defaultValue,
  int32_t min, int32_t max,
  char shortName)
-  : NameMatchOptionHandler(optName, description, defaultValue,
+  : NameMatchOptionHandler(pref, description, defaultValue,
                            OptionHandler::REQ_ARG, shortName),
     min_(min),
     max_(max)
@@ -180,13 +180,13 @@ void IntegerRangeOptionHandler::parseArg
   while(seq.hasNext()) {
     int32_t v = seq.next();
     if(v < min_ || max_ < v) {
-      std::string msg = optName_;
+      std::string msg = pref_->k;
       strappend(msg, " ", _("must be between %s and %s."));
       throw DL_ABORT_EX
         (fmt(msg.c_str(), util::itos(min_).c_str(),
              util::itos(max_).c_str()));
     }
-    option.put(optName_, optarg);
+    option.put(pref_, optarg);
   }
 }
 
@@ -196,13 +196,13 @@ std::string IntegerRangeOptionHandler::createPossibleValuesString() const
 }
 
 NumberOptionHandler::NumberOptionHandler
-(const std::string& optName,
+(const Pref* pref,
  const std::string& description,
  const std::string& defaultValue,
  int64_t min,
  int64_t max,
  char shortName)
-  : NameMatchOptionHandler(optName, description, defaultValue,
+  : NameMatchOptionHandler(pref, description, defaultValue,
                            OptionHandler::REQ_ARG, shortName),
     min_(min),
     max_(max)
@@ -219,9 +219,9 @@ void NumberOptionHandler::parseArg(Option& option, const std::string& optarg)
 void NumberOptionHandler::parseArg(Option& option, int64_t number)
 {
   if((min_ == -1 || min_ <= number) && (max_ ==  -1 || number <= max_)) {
-    option.put(optName_, util::itos(number));
+    option.put(pref_, util::itos(number));
   } else {
-    std::string msg = optName_;
+    std::string msg = pref_->k;
     msg += " ";
     if(min_ == -1 && max_ != -1) {
       msg += fmt(_("must be smaller than or equal to %s."),
@@ -258,13 +258,13 @@ std::string NumberOptionHandler::createPossibleValuesString() const
 }
 
 UnitNumberOptionHandler::UnitNumberOptionHandler
-(const std::string& optName,
+(const Pref* pref,
  const std::string& description,
  const std::string& defaultValue,
  int64_t min,
  int64_t max,
  char shortName)
-  : NumberOptionHandler(optName, description, defaultValue, min, max,
+  : NumberOptionHandler(pref, description, defaultValue, min, max,
                         shortName)
 {}
 
@@ -278,13 +278,13 @@ void UnitNumberOptionHandler::parseArg
 }
 
 FloatNumberOptionHandler::FloatNumberOptionHandler
-(const std::string& optName,
+(const Pref* pref,
  const std::string& description,
  const std::string& defaultValue,
  double min,
  double max,
  char shortName)
-  : NameMatchOptionHandler(optName, description, defaultValue,
+  : NameMatchOptionHandler(pref, description, defaultValue,
                            OptionHandler::REQ_ARG, shortName),
     min_(min),
     max_(max)
@@ -297,9 +297,9 @@ void FloatNumberOptionHandler::parseArg
 {
   double number = strtod(optarg.c_str(), 0);
   if((min_ < 0 || min_ <= number) && (max_ < 0 || number <= max_)) {
-    option.put(optName_, optarg);
+    option.put(pref_, optarg);
   } else {
-    std::string msg = optName_;
+    std::string msg = pref_->k;
     msg += " ";
     if(min_ < 0 && max_ >= 0) {
       msg += fmt(_("must be smaller than or equal to %.1f."), max_);
@@ -336,13 +336,13 @@ std::string FloatNumberOptionHandler::createPossibleValuesString() const
 }
 
 DefaultOptionHandler::DefaultOptionHandler
-(const std::string& optName,
+(const Pref* pref,
  const std::string& description,
  const std::string& defaultValue,
  const std::string& possibleValuesString,
  OptionHandler::ARG_TYPE argType,
  char shortName)
-  : NameMatchOptionHandler(optName, description, defaultValue, argType,
+  : NameMatchOptionHandler(pref, description, defaultValue, argType,
                            shortName),
     possibleValuesString_(possibleValuesString)
 {}
@@ -351,7 +351,7 @@ DefaultOptionHandler::~DefaultOptionHandler() {}
 
 void DefaultOptionHandler::parseArg(Option& option, const std::string& optarg)
 {
-  option.put(optName_, optarg);
+  option.put(pref_, optarg);
 }
 
 std::string DefaultOptionHandler::createPossibleValuesString() const
@@ -360,14 +360,14 @@ std::string DefaultOptionHandler::createPossibleValuesString() const
 }
 
 CumulativeOptionHandler::CumulativeOptionHandler
-(const std::string& optName,
+(const Pref* pref,
  const std::string& description,
  const std::string& defaultValue,
  const std::string& delim,
  const std::string& possibleValuesString,
  OptionHandler::ARG_TYPE argType,
  char shortName)
-  : NameMatchOptionHandler(optName, description, defaultValue, argType,
+  : NameMatchOptionHandler(pref, description, defaultValue, argType,
                            shortName),
     delim_(delim),
     possibleValuesString_(possibleValuesString)
@@ -378,9 +378,9 @@ CumulativeOptionHandler::~CumulativeOptionHandler() {}
 void CumulativeOptionHandler::parseArg
 (Option& option, const std::string& optarg)
 {
-  std::string value = option.get(optName_);
+  std::string value = option.get(pref_);
   strappend(value, optarg, delim_);
-  option.put(optName_, value);
+  option.put(pref_, value);
 }
 
 std::string CumulativeOptionHandler::createPossibleValuesString() const
@@ -389,10 +389,10 @@ std::string CumulativeOptionHandler::createPossibleValuesString() const
 }
 
 IndexOutOptionHandler::IndexOutOptionHandler
-(const std::string& optName,
+(const Pref* pref,
  const std::string& description,
  char shortName)
-  : NameMatchOptionHandler(optName, description, NO_DEFAULT_VALUE,
+  : NameMatchOptionHandler(pref, description, NO_DEFAULT_VALUE,
                            OptionHandler::REQ_ARG, shortName)
 {}
 
@@ -402,9 +402,9 @@ void IndexOutOptionHandler::parseArg(Option& option, const std::string& optarg)
 {
   // See optarg is in the fomrat of "INDEX=PATH"
   util::parseIndexPath(optarg);
-  std::string value = option.get(optName_);
+  std::string value = option.get(pref_);
   strappend(value, optarg, "\n");
-  option.put(optName_, value);
+  option.put(pref_, value);
 }
 
 std::string IndexOutOptionHandler::createPossibleValuesString() const
@@ -413,10 +413,10 @@ std::string IndexOutOptionHandler::createPossibleValuesString() const
 }
 
 ChecksumOptionHandler::ChecksumOptionHandler
-(const std::string& optName,
+(const Pref* pref,
  const std::string& description,
  char shortName)
-  : NameMatchOptionHandler(optName, description, NO_DEFAULT_VALUE,
+  : NameMatchOptionHandler(pref, description, NO_DEFAULT_VALUE,
                            OptionHandler::REQ_ARG, shortName)
 {}
 
@@ -431,7 +431,7 @@ void ChecksumOptionHandler::parseArg(Option& option, const std::string& optarg)
   if(!MessageDigest::isValidHash(p.first, p.second)) {
     throw DL_ABORT_EX(_("Unrecognized checksum"));
   }
-  option.put(optName_, optarg);
+  option.put(pref_, optarg);
 }
 
 std::string ChecksumOptionHandler::createPossibleValuesString() const
@@ -440,36 +440,36 @@ std::string ChecksumOptionHandler::createPossibleValuesString() const
 }
 
 ParameterOptionHandler::ParameterOptionHandler
-(const std::string& optName,
+(const Pref* pref,
  const std::string& description,
  const std::string& defaultValue,
  const std::vector<std::string>& validParamValues,
  char shortName)
-  : NameMatchOptionHandler(optName, description, defaultValue,
+  : NameMatchOptionHandler(pref, description, defaultValue,
                            OptionHandler::REQ_ARG, shortName),
     validParamValues_(validParamValues)
 {}
 
 ParameterOptionHandler::ParameterOptionHandler
-(const std::string& optName,
+(const Pref* pref,
  const std::string& description,
  const std::string& defaultValue,
  const std::string& validParamValue,
  char shortName)
-  : NameMatchOptionHandler(optName, description, defaultValue,
+  : NameMatchOptionHandler(pref, description, defaultValue,
                            OptionHandler::REQ_ARG, shortName)
 {
   validParamValues_.push_back(validParamValue);
 }
 
 ParameterOptionHandler::ParameterOptionHandler
-(const std::string& optName,
+(const Pref* pref,
  const std::string& description,
  const std::string& defaultValue,
  const std::string& validParamValue1,
  const std::string& validParamValue2,
  char shortName)
-  : NameMatchOptionHandler(optName, description, defaultValue,
+  : NameMatchOptionHandler(pref, description, defaultValue,
                            OptionHandler::REQ_ARG, shortName)
 {
   validParamValues_.push_back(validParamValue1);
@@ -477,14 +477,14 @@ ParameterOptionHandler::ParameterOptionHandler
 }
 
 ParameterOptionHandler::ParameterOptionHandler
-(const std::string& optName,
+(const Pref* pref,
  const std::string& description,
  const std::string& defaultValue,
  const std::string& validParamValue1,
  const std::string& validParamValue2,
  const std::string& validParamValue3,
  char shortName)
-  : NameMatchOptionHandler(optName, description, defaultValue,
+  : NameMatchOptionHandler(pref, description, defaultValue,
                            OptionHandler::REQ_ARG, shortName)
 {
   validParamValues_.push_back(validParamValue1);
@@ -499,7 +499,7 @@ void ParameterOptionHandler::parseArg(Option& option, const std::string& optarg)
   std::vector<std::string>::const_iterator itr =
     std::find(validParamValues_.begin(), validParamValues_.end(), optarg);
   if(itr == validParamValues_.end()) {
-    std::string msg = optName_;
+    std::string msg = pref_->k;
     strappend(msg, " ", _("must be one of the following:"));
     if(validParamValues_.size() == 0) {
       msg += "''";
@@ -512,7 +512,7 @@ void ParameterOptionHandler::parseArg(Option& option, const std::string& optarg)
     }
     throw DL_ABORT_EX(msg);
   } else {
-    option.put(optName_, optarg);
+    option.put(pref_, optarg);
   }
 }
 
@@ -525,13 +525,13 @@ std::string ParameterOptionHandler::createPossibleValuesString() const
 }
 
 HostPortOptionHandler::HostPortOptionHandler
-(const std::string& optName,
+(const Pref* pref,
  const std::string& description,
  const std::string& defaultValue,
- const std::string& hostOptionName,
- const std::string& portOptionName,
+ const Pref* hostOptionName,
+ const Pref* portOptionName,
  char shortName)
-  : NameMatchOptionHandler(optName, description, defaultValue,
+  : NameMatchOptionHandler(pref, description, defaultValue,
                            OptionHandler::REQ_ARG, shortName),
     hostOptionName_(hostOptionName),
     portOptionName_(portOptionName)
@@ -547,7 +547,7 @@ void HostPortOptionHandler::parseArg(Option& option, const std::string& optarg)
   if(!req.setUri(uri)) {
     throw DL_ABORT_EX(_("Unrecognized format"));
   }
-  option.put(optName_, optarg);
+  option.put(pref_, optarg);
   setHostAndPort(option, req.getHost(), req.getPort());
 }
 
@@ -564,19 +564,19 @@ std::string HostPortOptionHandler::createPossibleValuesString() const
 }
 
 HttpProxyUserOptionHandler::HttpProxyUserOptionHandler
-(const std::string& optName,
+(const Pref* pref,
  const std::string& description,
  const std::string& defaultValue,
  char shortName)
-  : NameMatchOptionHandler(optName, description, defaultValue,
+  : NameMatchOptionHandler(pref, description, defaultValue,
                            OptionHandler::REQ_ARG, shortName)
 {}
 
 void HttpProxyUserOptionHandler::parseArg
 (Option& option, const std::string& optarg)
 {
-  if(util::endsWith(optName_, "-user")) {
-    const std::string proxyPref = optName_.substr(0, optName_.size()-5);
+  if(util::endsWith(pref_->k, "-user")) {
+    const Pref* proxyPref = option::k2p(pref_->k.substr(0, pref_->k.size()-5));
     const std::string& olduri = option.get(proxyPref);
     if(!olduri.empty()) {
       Request req;
@@ -597,7 +597,7 @@ void HttpProxyUserOptionHandler::parseArg
       option.put(proxyPref, uri);
     }
   }
-  option.put(optName_, optarg);
+  option.put(pref_, optarg);
 }
 
 std::string HttpProxyUserOptionHandler::createPossibleValuesString() const
@@ -606,19 +606,19 @@ std::string HttpProxyUserOptionHandler::createPossibleValuesString() const
 }
 
 HttpProxyPasswdOptionHandler::HttpProxyPasswdOptionHandler
-(const std::string& optName,
+(const Pref* pref,
  const std::string& description,
  const std::string& defaultValue,
  char shortName)
-  : NameMatchOptionHandler(optName, description, defaultValue,
+  : NameMatchOptionHandler(pref, description, defaultValue,
                            OptionHandler::REQ_ARG, shortName)
 {}
 
 void HttpProxyPasswdOptionHandler::parseArg
 (Option& option, const std::string& optarg)
 {
-  if(util::endsWith(optName_, "-passwd")) {
-    const std::string proxyPref = optName_.substr(0, optName_.size()-7);
+  if(util::endsWith(pref_->k, "-passwd")) {
+    const Pref* proxyPref = option::k2p(pref_->k.substr(0, pref_->k.size()-7));
     const std::string& olduri = option.get(proxyPref);
     if(!olduri.empty()) {
       Request req;
@@ -639,7 +639,7 @@ void HttpProxyPasswdOptionHandler::parseArg
       option.put(proxyPref, uri);
     }
   }
-  option.put(optName_, optarg);
+  option.put(pref_, optarg);
 }
 
 std::string HttpProxyPasswdOptionHandler::createPossibleValuesString() const
@@ -648,14 +648,14 @@ std::string HttpProxyPasswdOptionHandler::createPossibleValuesString() const
 }
 
 HttpProxyOptionHandler::HttpProxyOptionHandler
-(const std::string& optName,
+(const Pref* pref,
  const std::string& description,
  const std::string& defaultValue,
  char shortName)
-  : NameMatchOptionHandler(optName, description, defaultValue,
+  : NameMatchOptionHandler(pref, description, defaultValue,
                            OptionHandler::REQ_ARG, shortName),
-    proxyUserPref_(optName_+"-user"),
-    proxyPasswdPref_(optName_+"-passwd")
+    proxyUserPref_(option::k2p(pref->k+"-user")),
+    proxyPasswdPref_(option::k2p(pref->k+"-passwd"))
 {}
 
 HttpProxyOptionHandler::~HttpProxyOptionHandler() {}
@@ -663,7 +663,7 @@ HttpProxyOptionHandler::~HttpProxyOptionHandler() {}
 void HttpProxyOptionHandler::parseArg(Option& option, const std::string& optarg)
 {
   if(optarg.empty()) {
-    option.put(optName_, optarg);
+    option.put(pref_, optarg);
   } else {
     Request req;
     std::string uri;
@@ -691,7 +691,7 @@ void HttpProxyOptionHandler::parseArg(Option& option, const std::string& optarg)
         us.hasPassword = true;
       }
     }
-    option.put(optName_, uri::construct(us));
+    option.put(pref_, uri::construct(us));
   }
 }
 
@@ -701,12 +701,12 @@ std::string HttpProxyOptionHandler::createPossibleValuesString() const
 }
 
 LocalFilePathOptionHandler::LocalFilePathOptionHandler
-(const std::string& optName,
+(const Pref* pref,
  const std::string& description,
  const std::string& defaultValue,
  bool acceptStdin,
  char shortName)
-  : NameMatchOptionHandler(optName, description, defaultValue,
+  : NameMatchOptionHandler(pref, description, defaultValue,
                            OptionHandler::REQ_ARG, shortName),
     acceptStdin_(acceptStdin)
 {}
@@ -715,13 +715,13 @@ void LocalFilePathOptionHandler::parseArg
 (Option& option, const std::string& optarg)
 {
   if(acceptStdin_ && optarg == "-") {
-    option.put(optName_, DEV_STDIN);
+    option.put(pref_, DEV_STDIN);
   } else {
     File f(optarg);
     if(!f.exists() || f.isDir()) {
       throw DL_ABORT_EX(fmt(MSG_NOT_FILE, optarg.c_str()));
     }
-    option.put(optName_, optarg);
+    option.put(pref_, optarg);
   }
 }
   
@@ -735,11 +735,11 @@ std::string LocalFilePathOptionHandler::createPossibleValuesString() const
 }
 
 PrioritizePieceOptionHandler::PrioritizePieceOptionHandler
-(const std::string& optName,
+(const Pref* pref,
  const std::string& description,
  const std::string& defaultValue,
  char shortName)
-  : NameMatchOptionHandler(optName, description, defaultValue,
+  : NameMatchOptionHandler(pref, description, defaultValue,
                            OptionHandler::REQ_ARG, shortName)
 {}
 
@@ -751,7 +751,7 @@ void PrioritizePieceOptionHandler::parseArg
   std::vector<size_t> result;
   util::parsePrioritizePieceRange
     (result, optarg, std::vector<SharedHandle<FileEntry> >(), 1024);
-  option.put(optName_, optarg);
+  option.put(pref_, optarg);
 }
 
 std::string PrioritizePieceOptionHandler::createPossibleValuesString() const

+ 26 - 27
src/OptionHandlerImpl.h

@@ -44,6 +44,7 @@
 namespace aria2 {
 
 class Option;
+class Pref;
 
 class NullOptionHandler : public OptionHandler {
 private:
@@ -71,7 +72,7 @@ public:
 
 class BooleanOptionHandler : public NameMatchOptionHandler {
 public:
-  BooleanOptionHandler(const std::string& optName,
+  BooleanOptionHandler(const Pref* pref,
                        const std::string& description = NO_DESCRIPTION,
                        const std::string& defaultValue = NO_DEFAULT_VALUE,
                        OptionHandler::ARG_TYPE argType = OptionHandler::REQ_ARG,
@@ -86,7 +87,7 @@ private:
   int32_t min_;
   int32_t max_;
 public:
-  IntegerRangeOptionHandler(const std::string& optName,
+  IntegerRangeOptionHandler(const Pref* pref,
                             const std::string& description,
                             const std::string& defaultValue,
                             int32_t min, int32_t max,
@@ -101,7 +102,7 @@ private:
   int64_t min_;
   int64_t max_;
 public:
-  NumberOptionHandler(const std::string& optName,
+  NumberOptionHandler(const Pref* pref,
                       const std::string& description = NO_DESCRIPTION,
                       const std::string& defaultValue = NO_DEFAULT_VALUE,
                       int64_t min = -1,
@@ -116,7 +117,7 @@ public:
 
 class UnitNumberOptionHandler : public NumberOptionHandler {
 public:
-  UnitNumberOptionHandler(const std::string& optName,
+  UnitNumberOptionHandler(const Pref* pref,
                           const std::string& description = NO_DESCRIPTION,
                           const std::string& defaultValue = NO_DEFAULT_VALUE,
                           int64_t min = -1,
@@ -131,7 +132,7 @@ private:
   double min_;
   double max_;
 public:
-  FloatNumberOptionHandler(const std::string& optName,
+  FloatNumberOptionHandler(const Pref* pref,
                            const std::string& description = NO_DESCRIPTION,
                            const std::string& defaultValue = NO_DEFAULT_VALUE,
                            double min = -1, double max = -1,
@@ -145,7 +146,7 @@ class DefaultOptionHandler : public NameMatchOptionHandler {
 private:
   std::string possibleValuesString_;
 public:
-  DefaultOptionHandler(const std::string& optName,
+  DefaultOptionHandler(const Pref* pref,
                        const std::string& description = NO_DESCRIPTION,
                        const std::string& defaultValue = NO_DEFAULT_VALUE,
                        const std::string& possibleValuesString = A2STR::NIL,
@@ -161,7 +162,7 @@ private:
   std::string delim_;
   std::string possibleValuesString_;
 public:
-  CumulativeOptionHandler(const std::string& optName,
+  CumulativeOptionHandler(const Pref* pref,
                           const std::string& description,
                           const std::string& defaultValue,
                           const std::string& delim,
@@ -175,9 +176,8 @@ public:
 };
 
 class IndexOutOptionHandler : public NameMatchOptionHandler {
-private:
 public:
-  IndexOutOptionHandler(const std::string& optName,
+  IndexOutOptionHandler(const Pref* pref,
                         const std::string& description,
                         char shortName = 0);
   virtual ~IndexOutOptionHandler();
@@ -186,9 +186,8 @@ public:
 };
 
 class ChecksumOptionHandler : public NameMatchOptionHandler {
-private:
 public:
-  ChecksumOptionHandler(const std::string& optName,
+  ChecksumOptionHandler(const Pref* pref,
                         const std::string& description,
                         char shortName = 0);
   virtual ~ChecksumOptionHandler();
@@ -200,23 +199,23 @@ class ParameterOptionHandler : public NameMatchOptionHandler {
 private:
   std::vector<std::string> validParamValues_;
 public:
-  ParameterOptionHandler(const std::string& optName,
+  ParameterOptionHandler(const Pref* pref,
                          const std::string& description,
                          const std::string& defaultValue,
                          const std::vector<std::string>& validParamValues,
                          char shortName = 0);
-  ParameterOptionHandler(const std::string& optName,
+  ParameterOptionHandler(const Pref* pref,
                          const std::string& description,
                          const std::string& defaultValue,
                          const std::string& validParamValue,
                          char shortName = 0);
-  ParameterOptionHandler(const std::string& optName,
+  ParameterOptionHandler(const Pref* pref,
                          const std::string& description,
                          const std::string& defaultValue,
                          const std::string& validParamValue1,
                          const std::string& validParamValue2,
                          char shortName = 0);
-  ParameterOptionHandler(const std::string& optName,
+  ParameterOptionHandler(const Pref* pref,
                          const std::string& description,
                          const std::string& defaultValue,
                          const std::string& validParamValue1,
@@ -230,14 +229,14 @@ public:
 
 class HostPortOptionHandler : public NameMatchOptionHandler {
 private:
-  std::string hostOptionName_;
-  std::string portOptionName_;
+  const Pref* hostOptionName_;
+  const Pref* portOptionName_;
 public:
-  HostPortOptionHandler(const std::string& optName,
+  HostPortOptionHandler(const Pref* pref,
                         const std::string& description,
                         const std::string& defaultValue,
-                        const std::string& hostOptionName,
-                        const std::string& portOptionName,
+                        const Pref* hostOptionName,
+                        const Pref* portOptionName,
                         char shortName = 0);
   virtual ~HostPortOptionHandler();
   virtual void parseArg(Option& option, const std::string& optarg);
@@ -248,7 +247,7 @@ public:
 
 class HttpProxyUserOptionHandler:public NameMatchOptionHandler {
 public:
-  HttpProxyUserOptionHandler(const std::string& optName,
+  HttpProxyUserOptionHandler(const Pref* pref,
                              const std::string& description,
                              const std::string& defaultValue,
                              char shortName = 0);
@@ -258,7 +257,7 @@ public:
 
 class HttpProxyPasswdOptionHandler:public NameMatchOptionHandler {
 public:
-  HttpProxyPasswdOptionHandler(const std::string& optName,
+  HttpProxyPasswdOptionHandler(const Pref* pref,
                                const std::string& description,
                                const std::string& defaultValue,
                                char shortName = 0);
@@ -268,10 +267,10 @@ public:
 
 class HttpProxyOptionHandler : public NameMatchOptionHandler {
 private:
-  std::string proxyUserPref_;
-  std::string proxyPasswdPref_;
+  const Pref* proxyUserPref_;
+  const Pref* proxyPasswdPref_;
 public:
-  HttpProxyOptionHandler(const std::string& optName,
+  HttpProxyOptionHandler(const Pref* pref,
                          const std::string& description,
                          const std::string& defaultValue,
                          char shortName = 0);
@@ -285,7 +284,7 @@ private:
   bool acceptStdin_;
 public:
   LocalFilePathOptionHandler
-  (const std::string& optName,
+  (const Pref* pref,
    const std::string& description = NO_DESCRIPTION,
    const std::string& defaultValue = NO_DEFAULT_VALUE,
    bool acceptStdin = false,
@@ -297,7 +296,7 @@ public:
 class PrioritizePieceOptionHandler:public NameMatchOptionHandler {
 public:
   PrioritizePieceOptionHandler
-  (const std::string& optName,
+  (const Pref* pref,
    const std::string& description = NO_DESCRIPTION,
    const std::string& defaultValue = NO_DEFAULT_VALUE,
    char shortName = 0);

+ 10 - 4
src/OptionParser.cc

@@ -50,6 +50,7 @@
 #include "OptionHandlerFactory.h"
 #include "DlAbortEx.h"
 #include "error_code.h"
+#include "prefs.h"
 
 namespace aria2 {
 
@@ -196,16 +197,21 @@ void OptionParser::parse(Option& option, std::istream& is)
 }
 
 namespace {
-class DummyOptionHandler:public NameMatchOptionHandler {
+class DummyOptionHandler:public NullOptionHandler {
 protected:
   virtual void parseArg(Option& option, const std::string& arg) {}
 public:
-  DummyOptionHandler(const std::string& name):NameMatchOptionHandler(name) {}
+  DummyOptionHandler(const std::string& optName)
+    : NullOptionHandler(),
+      optName_(optName)
+  {}
 
-  virtual std::string createPossibleValuesString() const
+  virtual const std::string& getName() const
   {
-    return A2STR::NIL;
+    return optName_;
   }
+private:
+  std::string optName_;
 };
 } // namespace
 

+ 13 - 12
src/RpcMethod.cc

@@ -107,7 +107,7 @@ void gatherOption
         // header and index-out option can take array as value
         const List* oplist = downcast<List>((*first).second);
         if(oplist &&
-           (optionName == PREF_HEADER || optionName == PREF_INDEX_OUT)) {
+           (optionName == PREF_HEADER->k || optionName == PREF_INDEX_OUT->k)) {
           for(List::ValueType::const_iterator argiter = oplist->begin(),
                 eoi = oplist->end(); argiter != eoi; ++argiter) {
             const String* opval = downcast<String>(*argiter);
@@ -142,8 +142,9 @@ void applyOption(InputIterator optNameFirst,
                  Option* src)
 {
   for(; optNameFirst != optNameLast; ++optNameFirst) {
-    if(src->defined(*optNameFirst)) {
-      dest->put(*optNameFirst, src->get(*optNameFirst));
+    const Pref* pref = option::k2p(*optNameFirst);
+    if(src->defined(pref)) {
+      dest->put(pref, src->get(pref));
     }
   }
 }
@@ -152,10 +153,10 @@ void applyOption(InputIterator optNameFirst,
 const std::set<std::string>& listChangeableOptions()
 {
   static const std::string OPTIONS[] = {
-    PREF_BT_MAX_PEERS,
-    PREF_BT_REQUEST_PEER_SPEED_LIMIT,
-    PREF_MAX_DOWNLOAD_LIMIT,
-    PREF_MAX_UPLOAD_LIMIT
+    PREF_BT_MAX_PEERS->k,
+    PREF_BT_REQUEST_PEER_SPEED_LIMIT->k,
+    PREF_MAX_DOWNLOAD_LIMIT->k,
+    PREF_MAX_UPLOAD_LIMIT->k
   };
   static std::set<std::string> options(vbegin(OPTIONS), vend(OPTIONS));
   return options;
@@ -180,11 +181,11 @@ void RpcMethod::applyChangeableOption(Option* dest, Option* src) const
 const std::set<std::string>& listChangeableGlobalOptions()
 {
   static const std::string OPTIONS[] = {
-    PREF_MAX_OVERALL_UPLOAD_LIMIT,
-    PREF_MAX_OVERALL_DOWNLOAD_LIMIT,
-    PREF_MAX_CONCURRENT_DOWNLOADS,
-    PREF_LOG,
-    PREF_LOG_LEVEL
+    PREF_MAX_OVERALL_UPLOAD_LIMIT->k,
+    PREF_MAX_OVERALL_DOWNLOAD_LIMIT->k,
+    PREF_MAX_CONCURRENT_DOWNLOADS->k,
+    PREF_LOG->k,
+    PREF_LOG_LEVEL->k
   };
   static std::set<std::string> options(vbegin(OPTIONS), vend(OPTIONS));
   return options;

+ 13 - 11
src/RpcMethodImpl.cc

@@ -1203,15 +1203,14 @@ SharedHandle<ValueBase> GetVersionRpcMethod::process
 }
 
 namespace {
-template<typename InputIterator>
 void pushRequestOption
-(const SharedHandle<Dict>& dict,
- InputIterator optionFirst, InputIterator optionLast)
+(const SharedHandle<Dict>& dict, const SharedHandle<Option>& option)
 {
   const std::set<std::string>& requestOptions = listRequestOptions();
-  for(; optionFirst != optionLast; ++optionFirst) {
-    if(requestOptions.count((*optionFirst).first)) {
-      dict->put((*optionFirst).first, (*optionFirst).second);
+  for(size_t i = 0, len = option->getTable().size(); i < len; ++i) {
+    const Pref* pref = option::i2p(i);
+    if(requestOptions.count(pref->k) && option->defined(pref)) {
+      dict->put(pref->k, option->get(pref));
     }
   }
 }
@@ -1232,7 +1231,7 @@ SharedHandle<ValueBase> GetOptionRpcMethod::process
   }
   SharedHandle<Dict> result = Dict::g();
   SharedHandle<Option> option = group->getOption();
-  pushRequestOption(result, option->begin(), option->end());
+  pushRequestOption(result, option);
   return result;
 }
 
@@ -1240,11 +1239,14 @@ SharedHandle<ValueBase> GetGlobalOptionRpcMethod::process
 (const RpcRequest& req, DownloadEngine* e)
 {
   SharedHandle<Dict> result = Dict::g();
-  for(std::map<std::string, std::string>::const_iterator i =
-        e->getOption()->begin(), eoi = e->getOption()->end(); i != eoi; ++i) {
-    SharedHandle<OptionHandler> h = getOptionParser()->findByName((*i).first);
+  for(size_t i = 0, len = e->getOption()->getTable().size(); i < len; ++i) {
+    const Pref* pref = option::i2p(i);
+    if(!e->getOption()->defined(pref)) {
+      continue;
+    }
+    SharedHandle<OptionHandler> h = getOptionParser()->findByName(pref->k);
     if(h && !h->isHidden()) {
-      result->put((*i).first, (*i).second);
+      result->put(pref->k, e->getOption()->get(pref));
     }
   }
   return result;

+ 8 - 6
src/SessionSerializer.cc

@@ -78,7 +78,7 @@ bool SessionSerializer::save(const std::string& filename) const
 namespace {
 const std::vector<std::string>& getCumulativeOpts()
 {
-  static std::string cumulativeOpts[] = { PREF_INDEX_OUT, PREF_HEADER };
+  static std::string cumulativeOpts[] = { PREF_INDEX_OUT->k, PREF_HEADER->k };
   static std::vector<std::string> opts
     (vbegin(cumulativeOpts), vend(cumulativeOpts));
   return opts;
@@ -108,8 +108,9 @@ bool writeOption(BufferedFile& fp, const SharedHandle<Option>& op)
     if(inCumulativeOpts(*itr)) {
       continue;
     }
-    if(op->defined(*itr)) {
-      if(fp.printf(" %s=%s\n", (*itr).c_str(), op->get(*itr).c_str()) < 0) {
+    const Pref* pref = option::k2p(*itr);
+    if(op->defined(pref)) {
+      if(fp.printf(" %s=%s\n", (*itr).c_str(), op->get(pref).c_str()) < 0) {
         return false;
       }
     }
@@ -117,9 +118,10 @@ bool writeOption(BufferedFile& fp, const SharedHandle<Option>& op)
   const std::vector<std::string>& cumopts = getCumulativeOpts();
   for(std::vector<std::string>::const_iterator opitr = cumopts.begin(),
         eoi = cumopts.end(); opitr != eoi; ++opitr) {
-    if(op->defined(*opitr)) {
+    const Pref* pref = option::k2p(*opitr);
+    if(op->defined(pref)) {
       std::vector<std::string> v;
-      util::split(op->get(*opitr), std::back_inserter(v), "\n",
+      util::split(op->get(pref), std::back_inserter(v), "\n",
                   false, false);
       for(std::vector<std::string>::const_iterator i = v.begin(), eoi = v.end();
           i != eoi; ++i) {
@@ -213,7 +215,7 @@ bool SessionSerializer::save(BufferedFile& fp) const
       // PREF_PAUSE was removed from option, so save it here looking
       // property separately.
       if((*itr)->isPauseRequested()) {
-        if(fp.printf(" %s=true\n", PREF_PAUSE.c_str()) < 0) {
+        if(fp.printf(" %s=true\n", PREF_PAUSE->k.c_str()) < 0) {
           return false;
         }
       }

+ 103 - 102
src/download_helper.cc

@@ -72,106 +72,106 @@ namespace aria2 {
 const std::set<std::string>& listRequestOptions()
 {
   static const std::string REQUEST_OPTIONS[] = {
-    PREF_DIR,
-    PREF_CHECK_INTEGRITY,
-    PREF_CONTINUE,
-    PREF_ALL_PROXY,
-    PREF_ALL_PROXY_USER,
-    PREF_ALL_PROXY_PASSWD,
-    PREF_CONNECT_TIMEOUT,
-    PREF_DRY_RUN,
-    PREF_LOWEST_SPEED_LIMIT,
-    PREF_MAX_FILE_NOT_FOUND,
-    PREF_MAX_TRIES,
-    PREF_NO_PROXY,
-    PREF_OUT,
-    PREF_PROXY_METHOD,
-    PREF_REMOTE_TIME,
-    PREF_SPLIT,
-    PREF_TIMEOUT,
-    PREF_HTTP_AUTH_CHALLENGE,
-    PREF_HTTP_NO_CACHE,
-    PREF_HTTP_USER,
-    PREF_HTTP_PASSWD,
-    PREF_HTTP_PROXY,
-    PREF_HTTP_PROXY_USER,
-    PREF_HTTP_PROXY_PASSWD,
-    PREF_HTTPS_PROXY,
-    PREF_HTTPS_PROXY_USER,
-    PREF_HTTPS_PROXY_PASSWD,
-    PREF_REFERER,
-    PREF_ENABLE_HTTP_KEEP_ALIVE,
-    PREF_ENABLE_HTTP_PIPELINING,
-    PREF_HEADER,
-    PREF_USE_HEAD,
-    PREF_USER_AGENT,
-    PREF_FTP_USER,
-    PREF_FTP_PASSWD,
-    PREF_FTP_PASV,
-    PREF_FTP_PROXY,
-    PREF_FTP_PROXY_USER,
-    PREF_FTP_PROXY_PASSWD,
-    PREF_FTP_TYPE,
-    PREF_FTP_REUSE_CONNECTION,
-    PREF_NO_NETRC,
-    PREF_REUSE_URI,
-    PREF_SELECT_FILE,
-    PREF_BT_ENABLE_LPD,
-    PREF_BT_EXTERNAL_IP,
-    PREF_BT_HASH_CHECK_SEED,
-    PREF_BT_MAX_OPEN_FILES,
-    PREF_BT_MAX_PEERS,
-    PREF_BT_METADATA_ONLY,
-    PREF_BT_MIN_CRYPTO_LEVEL,
-    PREF_BT_PRIORITIZE_PIECE,
-    PREF_BT_REQUIRE_CRYPTO,
-    PREF_BT_REQUEST_PEER_SPEED_LIMIT,
-    PREF_BT_SAVE_METADATA,
-    PREF_BT_SEED_UNVERIFIED,
-    PREF_BT_STOP_TIMEOUT,
-    PREF_BT_TRACKER_INTERVAL,
-    PREF_BT_TRACKER_TIMEOUT,
-    PREF_BT_TRACKER_CONNECT_TIMEOUT,
-    PREF_ENABLE_PEER_EXCHANGE,
-    PREF_FOLLOW_TORRENT,
-    PREF_INDEX_OUT,
-    PREF_MAX_UPLOAD_LIMIT,
-    PREF_SEED_RATIO,
-    PREF_SEED_TIME,
-    PREF_FOLLOW_METALINK,
-    PREF_METALINK_SERVERS,
-    PREF_METALINK_LANGUAGE,
-    PREF_METALINK_LOCATION,
-    PREF_METALINK_OS,
-    PREF_METALINK_VERSION,
-    PREF_METALINK_PREFERRED_PROTOCOL,
-    PREF_METALINK_ENABLE_UNIQUE_PROTOCOL,
-    PREF_ALLOW_OVERWRITE,
-    PREF_ALLOW_PIECE_LENGTH_CHANGE,
-    PREF_ASYNC_DNS,
-    PREF_AUTO_FILE_RENAMING,
-    PREF_FILE_ALLOCATION,
-    PREF_MAX_DOWNLOAD_LIMIT,
-    PREF_NO_FILE_ALLOCATION_LIMIT,
-    PREF_PARAMETERIZED_URI,
-    PREF_REALTIME_CHUNK_CHECKSUM,
-    PREF_REMOVE_CONTROL_FILE,
-    PREF_ALWAYS_RESUME,
-    PREF_MAX_RESUME_FAILURE_TRIES,
-    PREF_HTTP_ACCEPT_GZIP,
-    PREF_MAX_CONNECTION_PER_SERVER,
-    PREF_MIN_SPLIT_SIZE,
-    PREF_CONDITIONAL_GET,
-    PREF_ENABLE_ASYNC_DNS6,
-    PREF_BT_TRACKER,
-    PREF_BT_EXCLUDE_TRACKER,
-    PREF_RETRY_WAIT,
-    PREF_METALINK_BASE_URI,
-    PREF_PAUSE,
-    PREF_STREAM_PIECE_SELECTOR,
-    PREF_HASH_CHECK_ONLY,
-    PREF_CHECKSUM,
-    PREF_PIECE_LENGTH
+    PREF_DIR->k,
+    PREF_CHECK_INTEGRITY->k,
+    PREF_CONTINUE->k,
+    PREF_ALL_PROXY->k,
+    PREF_ALL_PROXY_USER->k,
+    PREF_ALL_PROXY_PASSWD->k,
+    PREF_CONNECT_TIMEOUT->k,
+    PREF_DRY_RUN->k,
+    PREF_LOWEST_SPEED_LIMIT->k,
+    PREF_MAX_FILE_NOT_FOUND->k,
+    PREF_MAX_TRIES->k,
+    PREF_NO_PROXY->k,
+    PREF_OUT->k,
+    PREF_PROXY_METHOD->k,
+    PREF_REMOTE_TIME->k,
+    PREF_SPLIT->k,
+    PREF_TIMEOUT->k,
+    PREF_HTTP_AUTH_CHALLENGE->k,
+    PREF_HTTP_NO_CACHE->k,
+    PREF_HTTP_USER->k,
+    PREF_HTTP_PASSWD->k,
+    PREF_HTTP_PROXY->k,
+    PREF_HTTP_PROXY_USER->k,
+    PREF_HTTP_PROXY_PASSWD->k,
+    PREF_HTTPS_PROXY->k,
+    PREF_HTTPS_PROXY_USER->k,
+    PREF_HTTPS_PROXY_PASSWD->k,
+    PREF_REFERER->k,
+    PREF_ENABLE_HTTP_KEEP_ALIVE->k,
+    PREF_ENABLE_HTTP_PIPELINING->k,
+    PREF_HEADER->k,
+    PREF_USE_HEAD->k,
+    PREF_USER_AGENT->k,
+    PREF_FTP_USER->k,
+    PREF_FTP_PASSWD->k,
+    PREF_FTP_PASV->k,
+    PREF_FTP_PROXY->k,
+    PREF_FTP_PROXY_USER->k,
+    PREF_FTP_PROXY_PASSWD->k,
+    PREF_FTP_TYPE->k,
+    PREF_FTP_REUSE_CONNECTION->k,
+    PREF_NO_NETRC->k,
+    PREF_REUSE_URI->k,
+    PREF_SELECT_FILE->k,
+    PREF_BT_ENABLE_LPD->k,
+    PREF_BT_EXTERNAL_IP->k,
+    PREF_BT_HASH_CHECK_SEED->k,
+    PREF_BT_MAX_OPEN_FILES->k,
+    PREF_BT_MAX_PEERS->k,
+    PREF_BT_METADATA_ONLY->k,
+    PREF_BT_MIN_CRYPTO_LEVEL->k,
+    PREF_BT_PRIORITIZE_PIECE->k,
+    PREF_BT_REQUIRE_CRYPTO->k,
+    PREF_BT_REQUEST_PEER_SPEED_LIMIT->k,
+    PREF_BT_SAVE_METADATA->k,
+    PREF_BT_SEED_UNVERIFIED->k,
+    PREF_BT_STOP_TIMEOUT->k,
+    PREF_BT_TRACKER_INTERVAL->k,
+    PREF_BT_TRACKER_TIMEOUT->k,
+    PREF_BT_TRACKER_CONNECT_TIMEOUT->k,
+    PREF_ENABLE_PEER_EXCHANGE->k,
+    PREF_FOLLOW_TORRENT->k,
+    PREF_INDEX_OUT->k,
+    PREF_MAX_UPLOAD_LIMIT->k,
+    PREF_SEED_RATIO->k,
+    PREF_SEED_TIME->k,
+    PREF_FOLLOW_METALINK->k,
+    PREF_METALINK_SERVERS->k,
+    PREF_METALINK_LANGUAGE->k,
+    PREF_METALINK_LOCATION->k,
+    PREF_METALINK_OS->k,
+    PREF_METALINK_VERSION->k,
+    PREF_METALINK_PREFERRED_PROTOCOL->k,
+    PREF_METALINK_ENABLE_UNIQUE_PROTOCOL->k,
+    PREF_ALLOW_OVERWRITE->k,
+    PREF_ALLOW_PIECE_LENGTH_CHANGE->k,
+    PREF_ASYNC_DNS->k,
+    PREF_AUTO_FILE_RENAMING->k,
+    PREF_FILE_ALLOCATION->k,
+    PREF_MAX_DOWNLOAD_LIMIT->k,
+    PREF_NO_FILE_ALLOCATION_LIMIT->k,
+    PREF_PARAMETERIZED_URI->k,
+    PREF_REALTIME_CHUNK_CHECKSUM->k,
+    PREF_REMOVE_CONTROL_FILE->k,
+    PREF_ALWAYS_RESUME->k,
+    PREF_MAX_RESUME_FAILURE_TRIES->k,
+    PREF_HTTP_ACCEPT_GZIP->k,
+    PREF_MAX_CONNECTION_PER_SERVER->k,
+    PREF_MIN_SPLIT_SIZE->k,
+    PREF_CONDITIONAL_GET->k,
+    PREF_ENABLE_ASYNC_DNS6->k,
+    PREF_BT_TRACKER->k,
+    PREF_BT_EXCLUDE_TRACKER->k,
+    PREF_RETRY_WAIT->k,
+    PREF_METALINK_BASE_URI->k,
+    PREF_PAUSE->k,
+    PREF_STREAM_PIECE_SELECTOR->k,
+    PREF_HASH_CHECK_ONLY->k,
+    PREF_CHECKSUM->k,
+    PREF_PIECE_LENGTH->k
   };
   static std::set<std::string> requestOptions
     (vbegin(REQUEST_OPTIONS), vend(REQUEST_OPTIONS));
@@ -534,8 +534,9 @@ void createRequestGroupForUriList
     for(std::set<std::string>::const_iterator i =
           listRequestOptions().begin(), eoi = listRequestOptions().end();
         i != eoi; ++i) {
-      if(tempOption->defined(*i)) {
-        requestOption->put(*i, tempOption->get(*i));
+      const Pref* pref = option::k2p(*i);
+      if(tempOption->defined(pref)) {
+        requestOption->put(pref, tempOption->get(pref));
       }
     }
 

+ 7 - 7
src/option_processing.cc

@@ -68,13 +68,13 @@ extern void showUsage(const std::string& keyword, const OptionParser& oparser);
 
 namespace {
 void overrideWithEnv(Option& op, const OptionParser& optionParser,
-                     const std::string& pref,
+                     const Pref* pref,
                      const std::string& envName)
 {
   char* value = getenv(envName.c_str());
   if(value) {
     try {
-      optionParser.findByName(pref)->parse(op, value);
+      optionParser.findByName(pref->k)->parse(op, value);
     } catch(Exception& e) {
       global::cerr()->printf
         ("Caught Error while parsing environment variable '%s'\n%s\n",
@@ -102,16 +102,16 @@ void option_processing(Option& op, std::vector<std::string>& uris,
       noConf = op.getAsBool(PREF_NO_CONF);
       ucfname = op.get(PREF_CONF_PATH);
 
-      if(op.defined("version")) {
+      if(op.defined(PREF_VERSION)) {
         showVersion();
         exit(error_code::FINISHED);
       }
-      if(op.defined("help")) {
+      if(op.defined(PREF_HELP)) {
         std::string keyword;
-        if(op.get("help").empty()) {
+        if(op.get(PREF_HELP).empty()) {
           keyword = TAG_BASIC;
         } else {
-          keyword = op.get("help");
+          keyword = op.get(PREF_HELP);
           if(util::startsWith(keyword, "--")) {
             keyword = keyword.substr(2);
           }
@@ -130,7 +130,7 @@ void option_processing(Option& op, std::vector<std::string>& uris,
     if(!noConf) {
       std::string cfname = 
         ucfname.empty() ?
-        oparser.findByName(PREF_CONF_PATH)->getDefaultValue():
+        oparser.findByName(PREF_CONF_PATH->k)->getDefaultValue():
         ucfname;
 
       if(File(cfname).isFile()) {

+ 292 - 206
src/prefs.cc

@@ -34,8 +34,91 @@
 /* copyright --> */
 #include "prefs.h"
 
+#include <cassert>
+#include <vector>
+#include <map>
+
 namespace aria2 {
 
+Pref::Pref(const std::string& k, size_t i):k(k), i(i) {}
+
+namespace {
+
+class PrefFactory {
+public:
+  PrefFactory():count_(0)
+  {
+    // We add special null pref whose ID is 0.
+    makePref("");
+  }
+  size_t nextId()
+  {
+    return count_++;
+  }
+  Pref* makePref(const std::string& key)
+  {
+    size_t id = nextId();
+    Pref* pref = new Pref(key, id);
+    i2p_.push_back(pref);
+    k2p_[key] = pref;
+    return pref;
+  }
+  size_t getCount() const
+  {
+    return count_;
+  }
+  const Pref* i2p(size_t id) const
+  {
+    assert(id < count_);
+    return i2p_[id];
+  }
+  const Pref* k2p(const std::string& k) const
+  {
+    std::map<std::string, const Pref*>::const_iterator i = k2p_.find(k);
+    if(i == k2p_.end()) {
+      return i2p_[0];
+    } else {
+      return (*i).second;
+    }
+  }
+private:
+  size_t count_;
+  std::vector<const Pref*> i2p_;
+  std::map<std::string, const Pref*> k2p_;
+};
+
+PrefFactory* getPrefFactory()
+{
+  static PrefFactory* pf = new PrefFactory();
+  return pf;
+}
+
+Pref* makePref(const std::string& key)
+{
+  return getPrefFactory()->makePref(key);
+}
+
+} // namespace
+
+namespace option {
+
+size_t countOption()
+{
+  return getPrefFactory()->getCount();
+}
+
+const Pref* i2p(size_t id)
+{
+  return getPrefFactory()->i2p(id);
+}
+
+const Pref* k2p(const std::string& key)
+{
+  return getPrefFactory()->k2p(key);
+}
+
+} // namespace option
+
 /**
  * Constants
  */
@@ -47,388 +130,391 @@ const std::string V_MEM("mem");
 const std::string V_ALL("all");
 const std::string A2_V_FULL("full");
 const std::string A2_V_GEOM("geom");
+const std::string V_PREALLOC("prealloc");
+const std::string V_FALLOC("falloc");
+const std::string V_DEBUG("debug");
+const std::string V_INFO("info");
+const std::string V_NOTICE("notice");
+const std::string V_WARN("warn");
+const std::string V_ERROR("error");
+const std::string V_INORDER("inorder");
+const std::string V_FEEDBACK("feedback");
+const std::string V_ADAPTIVE("adaptive");
+const std::string V_EPOLL("epoll");
+const std::string V_KQUEUE("kqueue");
+const std::string V_PORT("port");
+const std::string V_POLL("poll");
+const std::string V_SELECT("select");
+const std::string V_BINARY("binary");
+const std::string V_ASCII("ascii");
+const std::string V_GET("get");
+const std::string V_TUNNEL("tunnel");
+const std::string V_PLAIN("plain");
+const std::string V_ARC4("arc4");
+const std::string V_HTTP("http");
+const std::string V_HTTPS("https");
+const std::string V_FTP("ftp");
+
+const Pref* PREF_VERSION = makePref("version");
+const Pref* PREF_HELP = makePref("help");
 
 /**
  * General preferences
  */
 // values: 1*digit
-const std::string PREF_TIMEOUT("timeout");
+const Pref* PREF_TIMEOUT = makePref("timeout");
 // values: 1*digit
-const std::string PREF_DNS_TIMEOUT("dns-timeout");
+const Pref* PREF_DNS_TIMEOUT = makePref("dns-timeout");
 // values: 1*digit
-const std::string PREF_CONNECT_TIMEOUT("connect-timeout");
+const Pref* PREF_CONNECT_TIMEOUT = makePref("connect-timeout");
 // values: 1*digit
-const std::string PREF_MAX_TRIES("max-tries");
+const Pref* PREF_MAX_TRIES = makePref("max-tries");
 // values: 1*digit
-const std::string PREF_AUTO_SAVE_INTERVAL("auto-save-interval");
+const Pref* PREF_AUTO_SAVE_INTERVAL = makePref("auto-save-interval");
 // values: a string that your file system recognizes as a file name.
-const std::string PREF_LOG("log");
+const Pref* PREF_LOG = makePref("log");
 // values: a string that your file system recognizes as a directory.
-const std::string PREF_DIR("dir");
+const Pref* PREF_DIR = makePref("dir");
 // values: a string that your file system recognizes as a file name.
-const std::string PREF_OUT("out");
+const Pref* PREF_OUT = makePref("out");
 // values: 1*digit
-const std::string PREF_SPLIT("split");
+const Pref* PREF_SPLIT = makePref("split");
 // value: true | false
-const std::string PREF_DAEMON("daemon");
+const Pref* PREF_DAEMON = makePref("daemon");
 // value: a string
-const std::string PREF_REFERER("referer");
+const Pref* PREF_REFERER = makePref("referer");
 // value: 1*digit
-const std::string PREF_LOWEST_SPEED_LIMIT("lowest-speed-limit");
+const Pref* PREF_LOWEST_SPEED_LIMIT = makePref("lowest-speed-limit");
 // value: 1*digit
-const std::string PREF_PIECE_LENGTH("piece-length");
+const Pref* PREF_PIECE_LENGTH = makePref("piece-length");
 // value: 1*digit
-const std::string PREF_MAX_OVERALL_DOWNLOAD_LIMIT("max-overall-download-limit");
+const Pref* PREF_MAX_OVERALL_DOWNLOAD_LIMIT = makePref("max-overall-download-limit");
 // value: 1*digit
-const std::string PREF_MAX_DOWNLOAD_LIMIT("max-download-limit");
+const Pref* PREF_MAX_DOWNLOAD_LIMIT = makePref("max-download-limit");
 // value: 1*digit
-const std::string PREF_STARTUP_IDLE_TIME("startup-idle-time");
+const Pref* PREF_STARTUP_IDLE_TIME = makePref("startup-idle-time");
 // value: prealloc | fallc | none
-const std::string PREF_FILE_ALLOCATION("file-allocation");
-const std::string V_PREALLOC("prealloc");
-const std::string V_FALLOC("falloc");
+const Pref* PREF_FILE_ALLOCATION = makePref("file-allocation");
 // value: 1*digit
-const std::string PREF_NO_FILE_ALLOCATION_LIMIT("no-file-allocation-limit");
+const Pref* PREF_NO_FILE_ALLOCATION_LIMIT = makePref("no-file-allocation-limit");
 // value: true | false
-const std::string PREF_ALLOW_OVERWRITE("allow-overwrite");
+const Pref* PREF_ALLOW_OVERWRITE = makePref("allow-overwrite");
 // value: true | false
-const std::string PREF_REALTIME_CHUNK_CHECKSUM("realtime-chunk-checksum");
+const Pref* PREF_REALTIME_CHUNK_CHECKSUM = makePref("realtime-chunk-checksum");
 // value: true | false
-const std::string PREF_CHECK_INTEGRITY("check-integrity");
+const Pref* PREF_CHECK_INTEGRITY = makePref("check-integrity");
 // value: string that your file system recognizes as a file name.
-const std::string PREF_NETRC_PATH("netrc-path");
+const Pref* PREF_NETRC_PATH = makePref("netrc-path");
 // value:
-const std::string PREF_CONTINUE("continue");
+const Pref* PREF_CONTINUE = makePref("continue");
 // value:
-const std::string PREF_NO_NETRC("no-netrc");
+const Pref* PREF_NO_NETRC = makePref("no-netrc");
 // value: 1*digit
-const std::string PREF_MAX_DOWNLOADS("max-downloads");
+const Pref* PREF_MAX_DOWNLOADS = makePref("max-downloads");
 // value: string that your file system recognizes as a file name.
-const std::string PREF_INPUT_FILE("input-file");
+const Pref* PREF_INPUT_FILE = makePref("input-file");
 // value: 1*digit
-const std::string PREF_MAX_CONCURRENT_DOWNLOADS("max-concurrent-downloads");
+const Pref* PREF_MAX_CONCURRENT_DOWNLOADS = makePref("max-concurrent-downloads");
 // value: true | false
-const std::string PREF_FORCE_SEQUENTIAL("force-sequential");
+const Pref* PREF_FORCE_SEQUENTIAL = makePref("force-sequential");
 // value: true | false
-const std::string PREF_AUTO_FILE_RENAMING("auto-file-renaming");
+const Pref* PREF_AUTO_FILE_RENAMING = makePref("auto-file-renaming");
 // value: true | false
-const std::string PREF_PARAMETERIZED_URI("parameterized-uri");
+const Pref* PREF_PARAMETERIZED_URI = makePref("parameterized-uri");
 // value: true | false
-const std::string PREF_ENABLE_DIRECT_IO("enable-direct-io");
+const Pref* PREF_ENABLE_DIRECT_IO = makePref("enable-direct-io");
 // value: true | false
-const std::string PREF_ALLOW_PIECE_LENGTH_CHANGE("allow-piece-length-change");
+const Pref* PREF_ALLOW_PIECE_LENGTH_CHANGE = makePref("allow-piece-length-change");
 // value: true | false
-const std::string PREF_NO_CONF("no-conf");
+const Pref* PREF_NO_CONF = makePref("no-conf");
 // value: string
-const std::string PREF_CONF_PATH("conf-path");
+const Pref* PREF_CONF_PATH = makePref("conf-path");
 // value: 1*digit
-const std::string PREF_STOP("stop");
+const Pref* PREF_STOP = makePref("stop");
 // value: true | false
-const std::string PREF_QUIET("quiet");
+const Pref* PREF_QUIET = makePref("quiet");
 // value: true | false
-const std::string PREF_ASYNC_DNS("async-dns");
+const Pref* PREF_ASYNC_DNS = makePref("async-dns");
 // value: 1*digit
-const std::string PREF_SUMMARY_INTERVAL("summary-interval");
+const Pref* PREF_SUMMARY_INTERVAL = makePref("summary-interval");
 // value: debug, info, notice, warn, error
-const std::string PREF_LOG_LEVEL("log-level");
-const std::string V_DEBUG("debug");
-const std::string V_INFO("info");
-const std::string V_NOTICE("notice");
-const std::string V_WARN("warn");
-const std::string V_ERROR("error");
+const Pref* PREF_LOG_LEVEL = makePref("log-level");
 // value: inorder | feedback | adaptive
-const std::string PREF_URI_SELECTOR("uri-selector");
-const std::string V_INORDER("inorder");
-const std::string V_FEEDBACK("feedback");
-const std::string V_ADAPTIVE("adaptive");
+const Pref* PREF_URI_SELECTOR = makePref("uri-selector");
 // value: 1*digit
-const std::string PREF_SERVER_STAT_TIMEOUT("server-stat-timeout");
+const Pref* PREF_SERVER_STAT_TIMEOUT = makePref("server-stat-timeout");
 // value: string that your file system recognizes as a file name.
-const std::string PREF_SERVER_STAT_IF("server-stat-if");
+const Pref* PREF_SERVER_STAT_IF = makePref("server-stat-if");
 // value: string that your file system recognizes as a file name.
-const std::string PREF_SERVER_STAT_OF("server-stat-of");
+const Pref* PREF_SERVER_STAT_OF = makePref("server-stat-of");
 // value: true | false
-const std::string PREF_REMOTE_TIME("remote-time");
+const Pref* PREF_REMOTE_TIME = makePref("remote-time");
 // value: 1*digit
-const std::string PREF_MAX_FILE_NOT_FOUND("max-file-not-found");
+const Pref* PREF_MAX_FILE_NOT_FOUND = makePref("max-file-not-found");
 // value: epoll | select
-const std::string PREF_EVENT_POLL("event-poll");
-const std::string V_EPOLL("epoll");
-const std::string V_KQUEUE("kqueue");
-const std::string V_PORT("port");
-const std::string V_POLL("poll");
-const std::string V_SELECT("select");
+const Pref* PREF_EVENT_POLL = makePref("event-poll");
 // value: true | false
-const std::string PREF_ENABLE_RPC("enable-rpc");
+const Pref* PREF_ENABLE_RPC = makePref("enable-rpc");
 // value: 1*digit
-const std::string PREF_RPC_LISTEN_PORT("rpc-listen-port");
+const Pref* PREF_RPC_LISTEN_PORT = makePref("rpc-listen-port");
 // value: string
-const std::string PREF_RPC_USER("rpc-user");
+const Pref* PREF_RPC_USER = makePref("rpc-user");
 // value: string
-const std::string PREF_RPC_PASSWD("rpc-passwd");
+const Pref* PREF_RPC_PASSWD = makePref("rpc-passwd");
 // value: 1*digit
-const std::string PREF_RPC_MAX_REQUEST_SIZE("rpc-max-request-size");
+const Pref* PREF_RPC_MAX_REQUEST_SIZE = makePref("rpc-max-request-size");
 // value: true | false
-const std::string PREF_RPC_LISTEN_ALL("rpc-listen-all");
+const Pref* PREF_RPC_LISTEN_ALL = makePref("rpc-listen-all");
 // value: true | false
-const std::string PREF_RPC_ALLOW_ORIGIN_ALL("rpc-allow-origin-all");
+const Pref* PREF_RPC_ALLOW_ORIGIN_ALL = makePref("rpc-allow-origin-all");
 // value: true | false
-const std::string PREF_DRY_RUN("dry-run");
+const Pref* PREF_DRY_RUN = makePref("dry-run");
 // value: true | false
-const std::string PREF_REUSE_URI("reuse-uri");
+const Pref* PREF_REUSE_URI = makePref("reuse-uri");
 // value: string
-const std::string PREF_ON_DOWNLOAD_START("on-download-start");
-const std::string PREF_ON_DOWNLOAD_PAUSE("on-download-pause");
-const std::string PREF_ON_DOWNLOAD_STOP("on-download-stop");
-const std::string PREF_ON_DOWNLOAD_COMPLETE("on-download-complete");
-const std::string PREF_ON_DOWNLOAD_ERROR("on-download-error");
+const Pref* PREF_ON_DOWNLOAD_START = makePref("on-download-start");
+const Pref* PREF_ON_DOWNLOAD_PAUSE = makePref("on-download-pause");
+const Pref* PREF_ON_DOWNLOAD_STOP = makePref("on-download-stop");
+const Pref* PREF_ON_DOWNLOAD_COMPLETE = makePref("on-download-complete");
+const Pref* PREF_ON_DOWNLOAD_ERROR = makePref("on-download-error");
 // value: string
-const std::string PREF_INTERFACE("interface");
+const Pref* PREF_INTERFACE = makePref("interface");
 // value: true | false
-const std::string PREF_DISABLE_IPV6("disable-ipv6");
+const Pref* PREF_DISABLE_IPV6 = makePref("disable-ipv6");
 // value: true | false
-const std::string PREF_HUMAN_READABLE("human-readable");
+const Pref* PREF_HUMAN_READABLE = makePref("human-readable");
 // value: true | false
-const std::string PREF_REMOVE_CONTROL_FILE("remove-control-file");
+const Pref* PREF_REMOVE_CONTROL_FILE = makePref("remove-control-file");
 // value: true | false
-const std::string PREF_ALWAYS_RESUME("always-resume");
+const Pref* PREF_ALWAYS_RESUME = makePref("always-resume");
 // value: 1*digit
-const std::string PREF_MAX_RESUME_FAILURE_TRIES("max-resume-failure-tries");
+const Pref* PREF_MAX_RESUME_FAILURE_TRIES = makePref("max-resume-failure-tries");
 // value: string that your file system recognizes as a file name.
-const std::string PREF_SAVE_SESSION("save-session");
+const Pref* PREF_SAVE_SESSION = makePref("save-session");
 // value: 1*digit
-const std::string PREF_MAX_CONNECTION_PER_SERVER("max-connection-per-server");
+const Pref* PREF_MAX_CONNECTION_PER_SERVER = makePref("max-connection-per-server");
 // value: 1*digit
-const std::string PREF_MIN_SPLIT_SIZE("min-split-size");
+const Pref* PREF_MIN_SPLIT_SIZE = makePref("min-split-size");
 // value: true | false
-const std::string PREF_CONDITIONAL_GET("conditional-get");
+const Pref* PREF_CONDITIONAL_GET = makePref("conditional-get");
 // value: true | false
-const std::string PREF_SELECT_LEAST_USED_HOST("select-least-used-host");
+const Pref* PREF_SELECT_LEAST_USED_HOST = makePref("select-least-used-host");
 // value: true | false
-const std::string PREF_ENABLE_ASYNC_DNS6("enable-async-dns6");
+const Pref* PREF_ENABLE_ASYNC_DNS6 = makePref("enable-async-dns6");
 // value: 1*digit
-const std::string PREF_MAX_DOWNLOAD_RESULT("max-download-result");
+const Pref* PREF_MAX_DOWNLOAD_RESULT = makePref("max-download-result");
 // value: 1*digit
-const std::string PREF_RETRY_WAIT("retry-wait");
+const Pref* PREF_RETRY_WAIT = makePref("retry-wait");
 // value: string
-const std::string PREF_ASYNC_DNS_SERVER("async-dns-server");
+const Pref* PREF_ASYNC_DNS_SERVER = makePref("async-dns-server");
 // value: true | false
-const std::string PREF_SHOW_CONSOLE_READOUT("show-console-readout");
+const Pref* PREF_SHOW_CONSOLE_READOUT = makePref("show-console-readout");
 // value: default | inorder
-const std::string PREF_STREAM_PIECE_SELECTOR("stream-piece-selector");
+const Pref* PREF_STREAM_PIECE_SELECTOR = makePref("stream-piece-selector");
 // value: true | false
-const std::string PREF_TRUNCATE_CONSOLE_READOUT("truncate-console-readout");
+const Pref* PREF_TRUNCATE_CONSOLE_READOUT = makePref("truncate-console-readout");
 // value: true | false
-const std::string PREF_PAUSE("pause");
+const Pref* PREF_PAUSE = makePref("pause");
 // value: default | full
-const std::string PREF_DOWNLOAD_RESULT("download-result");
+const Pref* PREF_DOWNLOAD_RESULT = makePref("download-result");
 // value: true | false
-const std::string PREF_HASH_CHECK_ONLY("hash-check-only");
+const Pref* PREF_HASH_CHECK_ONLY = makePref("hash-check-only");
 // values: hashType=digest
-const std::string PREF_CHECKSUM("checksum");
+const Pref* PREF_CHECKSUM = makePref("checksum");
 
 /**
  * FTP related preferences
  */
-const std::string PREF_FTP_USER("ftp-user");
-const std::string PREF_FTP_PASSWD("ftp-passwd");
+const Pref* PREF_FTP_USER = makePref("ftp-user");
+const Pref* PREF_FTP_PASSWD = makePref("ftp-passwd");
 // values: binary | ascii
-const std::string PREF_FTP_TYPE("ftp-type");
-const std::string V_BINARY("binary");
-const std::string V_ASCII("ascii");
+const Pref* PREF_FTP_TYPE = makePref("ftp-type");
 // values: true | false
-const std::string PREF_FTP_PASV("ftp-pasv");
+const Pref* PREF_FTP_PASV = makePref("ftp-pasv");
 // values: true | false
-const std::string PREF_FTP_REUSE_CONNECTION("ftp-reuse-connection");
+const Pref* PREF_FTP_REUSE_CONNECTION = makePref("ftp-reuse-connection");
 
 /**
  * HTTP related preferences
  */
-const std::string PREF_HTTP_USER("http-user");
-const std::string PREF_HTTP_PASSWD("http-passwd");
+const Pref* PREF_HTTP_USER = makePref("http-user");
+const Pref* PREF_HTTP_PASSWD = makePref("http-passwd");
 // values: string
-const std::string PREF_USER_AGENT("user-agent");
+const Pref* PREF_USER_AGENT = makePref("user-agent");
 // value: string that your file system recognizes as a file name.
-const std::string PREF_LOAD_COOKIES("load-cookies");
+const Pref* PREF_LOAD_COOKIES = makePref("load-cookies");
 // value: string that your file system recognizes as a file name.
-const std::string PREF_SAVE_COOKIES("save-cookies");
+const Pref* PREF_SAVE_COOKIES = makePref("save-cookies");
 // values: true | false
-const std::string PREF_ENABLE_HTTP_KEEP_ALIVE("enable-http-keep-alive");
+const Pref* PREF_ENABLE_HTTP_KEEP_ALIVE = makePref("enable-http-keep-alive");
 // values: true | false
-const std::string PREF_ENABLE_HTTP_PIPELINING("enable-http-pipelining");
+const Pref* PREF_ENABLE_HTTP_PIPELINING = makePref("enable-http-pipelining");
 // value: 1*digit
-const std::string PREF_MAX_HTTP_PIPELINING("max-http-pipelining");
+const Pref* PREF_MAX_HTTP_PIPELINING = makePref("max-http-pipelining");
 // value: string
-const std::string PREF_HEADER("header");
+const Pref* PREF_HEADER = makePref("header");
 // value: string that your file system recognizes as a file name.
-const std::string PREF_CERTIFICATE("certificate");
+const Pref* PREF_CERTIFICATE = makePref("certificate");
 // value: string that your file system recognizes as a file name.
-const std::string PREF_PRIVATE_KEY("private-key");
+const Pref* PREF_PRIVATE_KEY = makePref("private-key");
 // value: string that your file system recognizes as a file name.
-const std::string PREF_CA_CERTIFICATE("ca-certificate");
+const Pref* PREF_CA_CERTIFICATE = makePref("ca-certificate");
 // value: true | false
-const std::string PREF_CHECK_CERTIFICATE("check-certificate");
+const Pref* PREF_CHECK_CERTIFICATE = makePref("check-certificate");
 // value: true | false
-const std::string PREF_USE_HEAD("use-head");
+const Pref* PREF_USE_HEAD = makePref("use-head");
 // value: true | false
-const std::string PREF_HTTP_AUTH_CHALLENGE("http-auth-challenge");
+const Pref* PREF_HTTP_AUTH_CHALLENGE = makePref("http-auth-challenge");
 // value: true | false
-const std::string PREF_HTTP_NO_CACHE("http-no-cache");
+const Pref* PREF_HTTP_NO_CACHE = makePref("http-no-cache");
 // value: true | false
-const std::string PREF_HTTP_ACCEPT_GZIP("http-accept-gzip");
+const Pref* PREF_HTTP_ACCEPT_GZIP = makePref("http-accept-gzip");
 
 /** 
  * Proxy related preferences
  */
-const std::string PREF_HTTP_PROXY("http-proxy");
-const std::string PREF_HTTPS_PROXY("https-proxy");
-const std::string PREF_FTP_PROXY("ftp-proxy");
-const std::string PREF_ALL_PROXY("all-proxy");
+const Pref* PREF_HTTP_PROXY = makePref("http-proxy");
+const Pref* PREF_HTTPS_PROXY = makePref("https-proxy");
+const Pref* PREF_FTP_PROXY = makePref("ftp-proxy");
+const Pref* PREF_ALL_PROXY = makePref("all-proxy");
 // values: comma separeted hostname or domain
-const std::string PREF_NO_PROXY("no-proxy");
+const Pref* PREF_NO_PROXY = makePref("no-proxy");
 // values: get | tunnel
-const std::string PREF_PROXY_METHOD("proxy-method");
-const std::string V_GET("get");
-const std::string V_TUNNEL("tunnel");
-const std::string PREF_HTTP_PROXY_USER("http-proxy-user");
-const std::string PREF_HTTP_PROXY_PASSWD("http-proxy-passwd");
-const std::string PREF_HTTPS_PROXY_USER("https-proxy-user");
-const std::string PREF_HTTPS_PROXY_PASSWD("https-proxy-passwd");
-const std::string PREF_FTP_PROXY_USER("ftp-proxy-user");
-const std::string PREF_FTP_PROXY_PASSWD("ftp-proxy-passwd");
-const std::string PREF_ALL_PROXY_USER("all-proxy-user");
-const std::string PREF_ALL_PROXY_PASSWD("all-proxy-passwd");
+const Pref* PREF_PROXY_METHOD = makePref("proxy-method");
+const Pref* PREF_HTTP_PROXY_USER = makePref("http-proxy-user");
+const Pref* PREF_HTTP_PROXY_PASSWD = makePref("http-proxy-passwd");
+const Pref* PREF_HTTPS_PROXY_USER = makePref("https-proxy-user");
+const Pref* PREF_HTTPS_PROXY_PASSWD = makePref("https-proxy-passwd");
+const Pref* PREF_FTP_PROXY_USER = makePref("ftp-proxy-user");
+const Pref* PREF_FTP_PROXY_PASSWD = makePref("ftp-proxy-passwd");
+const Pref* PREF_ALL_PROXY_USER = makePref("all-proxy-user");
+const Pref* PREF_ALL_PROXY_PASSWD = makePref("all-proxy-passwd");
 
 /**
  * BitTorrent related preferences
  */
 // values: 1*digit
-const std::string PREF_PEER_CONNECTION_TIMEOUT("peer-connection-timeout");
+const Pref* PREF_PEER_CONNECTION_TIMEOUT = makePref("peer-connection-timeout");
 // values: 1*digit
-const std::string PREF_BT_TIMEOUT("bt-timeout");
+const Pref* PREF_BT_TIMEOUT = makePref("bt-timeout");
 // values: 1*digit
-const std::string PREF_BT_REQUEST_TIMEOUT("bt-request-timeout");
+const Pref* PREF_BT_REQUEST_TIMEOUT = makePref("bt-request-timeout");
 // values: true | false
-const std::string PREF_SHOW_FILES("show-files");
+const Pref* PREF_SHOW_FILES = makePref("show-files");
 // values: 1*digit
-const std::string PREF_MAX_OVERALL_UPLOAD_LIMIT("max-overall-upload-limit");
+const Pref* PREF_MAX_OVERALL_UPLOAD_LIMIT = makePref("max-overall-upload-limit");
 // values: 1*digit
-const std::string PREF_MAX_UPLOAD_LIMIT("max-upload-limit");
+const Pref* PREF_MAX_UPLOAD_LIMIT = makePref("max-upload-limit");
 // values: a string that your file system recognizes as a file name.
-const std::string PREF_TORRENT_FILE("torrent-file");
+const Pref* PREF_TORRENT_FILE = makePref("torrent-file");
 // values: 1*digit
-const std::string PREF_LISTEN_PORT("listen-port");
+const Pref* PREF_LISTEN_PORT = makePref("listen-port");
 // values: true | false | mem
-const std::string PREF_FOLLOW_TORRENT("follow-torrent");
-// values: 1*digit *( (,|-) 1*digit);
-const std::string PREF_SELECT_FILE("select-file");
+const Pref* PREF_FOLLOW_TORRENT = makePref("follow-torrent");
+// values: 1*digit * = makePref(  = makePref(,|-) 1*digit);
+const Pref* PREF_SELECT_FILE = makePref("select-file");
 // values: 1*digit
-const std::string PREF_SEED_TIME("seed-time");
+const Pref* PREF_SEED_TIME = makePref("seed-time");
 // values: 1*digit ['.' [ 1*digit ] ]
-const std::string PREF_SEED_RATIO("seed-ratio");
+const Pref* PREF_SEED_RATIO = makePref("seed-ratio");
 // values: 1*digit
-const std::string PREF_BT_KEEP_ALIVE_INTERVAL("bt-keep-alive-interval");
+const Pref* PREF_BT_KEEP_ALIVE_INTERVAL = makePref("bt-keep-alive-interval");
 // values: a string, less than or equals to 20 bytes length
-const std::string PREF_PEER_ID_PREFIX("peer-id-prefix");
+const Pref* PREF_PEER_ID_PREFIX = makePref("peer-id-prefix");
 // values: true | false
-const std::string PREF_ENABLE_PEER_EXCHANGE("enable-peer-exchange");
+const Pref* PREF_ENABLE_PEER_EXCHANGE = makePref("enable-peer-exchange");
 // values: true | false
-const std::string PREF_ENABLE_DHT("enable-dht");
+const Pref* PREF_ENABLE_DHT = makePref("enable-dht");
 // values: a string
-const std::string PREF_DHT_LISTEN_ADDR("dht-listen-addr");
+const Pref* PREF_DHT_LISTEN_ADDR = makePref("dht-listen-addr");
 // values: 1*digit
-const std::string PREF_DHT_LISTEN_PORT("dht-listen-port");
+const Pref* PREF_DHT_LISTEN_PORT = makePref("dht-listen-port");
 // values: a string
-const std::string PREF_DHT_ENTRY_POINT_HOST("dht-entry-point-host");
+const Pref* PREF_DHT_ENTRY_POINT_HOST = makePref("dht-entry-point-host");
 // values: 1*digit
-const std::string PREF_DHT_ENTRY_POINT_PORT("dht-entry-point-port");
-// values: a string (hostname:port);
-const std::string PREF_DHT_ENTRY_POINT("dht-entry-point");
+const Pref* PREF_DHT_ENTRY_POINT_PORT = makePref("dht-entry-point-port");
+// values: a string  = makePref(hostname:port);
+const Pref* PREF_DHT_ENTRY_POINT = makePref("dht-entry-point");
 // values: a string
-const std::string PREF_DHT_FILE_PATH("dht-file-path");
+const Pref* PREF_DHT_FILE_PATH = makePref("dht-file-path");
 // values: true | false
-const std::string PREF_ENABLE_DHT6("enable-dht6");
+const Pref* PREF_ENABLE_DHT6 = makePref("enable-dht6");
 // values: a string
-const std::string PREF_DHT_LISTEN_ADDR6("dht-listen-addr6");
+const Pref* PREF_DHT_LISTEN_ADDR6 = makePref("dht-listen-addr6");
 // values: a string
-const std::string PREF_DHT_ENTRY_POINT_HOST6("dht-entry-point-host6");
+const Pref* PREF_DHT_ENTRY_POINT_HOST6 = makePref("dht-entry-point-host6");
 // values: 1*digit
-const std::string PREF_DHT_ENTRY_POINT_PORT6("dht-entry-point-port6");
-// values: a string (hostname:port)
-const std::string PREF_DHT_ENTRY_POINT6("dht-entry-point6");
+const Pref* PREF_DHT_ENTRY_POINT_PORT6 = makePref("dht-entry-point-port6");
+// values: a string  = makePref(hostname:port)
+const Pref* PREF_DHT_ENTRY_POINT6 = makePref("dht-entry-point6");
 // values: a string
-const std::string PREF_DHT_FILE_PATH6("dht-file-path6");
+const Pref* PREF_DHT_FILE_PATH6 = makePref("dht-file-path6");
 // values: plain | arc4
-const std::string PREF_BT_MIN_CRYPTO_LEVEL("bt-min-crypto-level");
-const std::string V_PLAIN("plain");
-const std::string V_ARC4("arc4");
+const Pref* PREF_BT_MIN_CRYPTO_LEVEL = makePref("bt-min-crypto-level");
 // values:: true | false
-const std::string PREF_BT_REQUIRE_CRYPTO("bt-require-crypto");
+const Pref* PREF_BT_REQUIRE_CRYPTO = makePref("bt-require-crypto");
 // values: 1*digit
-const std::string PREF_BT_REQUEST_PEER_SPEED_LIMIT("bt-request-peer-speed-limit");
+const Pref* PREF_BT_REQUEST_PEER_SPEED_LIMIT = makePref("bt-request-peer-speed-limit");
 // values: 1*digit
-const std::string PREF_BT_MAX_OPEN_FILES("bt-max-open-files");
+const Pref* PREF_BT_MAX_OPEN_FILES = makePref("bt-max-open-files");
 // values: true | false
-const std::string PREF_BT_SEED_UNVERIFIED("bt-seed-unverified");
+const Pref* PREF_BT_SEED_UNVERIFIED = makePref("bt-seed-unverified");
 // values: true | false
-const std::string PREF_BT_HASH_CHECK_SEED("bt-hash-check-seed");
+const Pref* PREF_BT_HASH_CHECK_SEED = makePref("bt-hash-check-seed");
 // values: 1*digit
-const std::string PREF_BT_MAX_PEERS("bt-max-peers");
-// values: a string (IP address)
-const std::string PREF_BT_EXTERNAL_IP("bt-external-ip");
+const Pref* PREF_BT_MAX_PEERS = makePref("bt-max-peers");
+// values: a string  = makePref(IP address)
+const Pref* PREF_BT_EXTERNAL_IP = makePref("bt-external-ip");
 // values: 1*digit '=' a string that your file system recognizes as a file name.
-const std::string PREF_INDEX_OUT("index-out");
+const Pref* PREF_INDEX_OUT = makePref("index-out");
 // values: 1*digit
-const std::string PREF_BT_TRACKER_INTERVAL("bt-tracker-interval");
+const Pref* PREF_BT_TRACKER_INTERVAL = makePref("bt-tracker-interval");
 // values: 1*digit
-const std::string PREF_BT_STOP_TIMEOUT("bt-stop-timeout");
+const Pref* PREF_BT_STOP_TIMEOUT = makePref("bt-stop-timeout");
 // values: head[=SIZE]|tail[=SIZE], ...
-const std::string PREF_BT_PRIORITIZE_PIECE("bt-prioritize-piece");
+const Pref* PREF_BT_PRIORITIZE_PIECE = makePref("bt-prioritize-piece");
 // values: true | false
-const std::string PREF_BT_SAVE_METADATA("bt-save-metadata");
+const Pref* PREF_BT_SAVE_METADATA = makePref("bt-save-metadata");
 // values: true | false
-const std::string PREF_BT_METADATA_ONLY("bt-metadata-only");
+const Pref* PREF_BT_METADATA_ONLY = makePref("bt-metadata-only");
 // values: true | false
-const std::string PREF_BT_ENABLE_LPD("bt-enable-lpd");
+const Pref* PREF_BT_ENABLE_LPD = makePref("bt-enable-lpd");
 // values: string
-const std::string PREF_BT_LPD_INTERFACE("bt-lpd-interface");
+const Pref* PREF_BT_LPD_INTERFACE = makePref("bt-lpd-interface");
 // values: 1*digit
-const std::string PREF_BT_TRACKER_TIMEOUT("bt-tracker-timeout");
+const Pref* PREF_BT_TRACKER_TIMEOUT = makePref("bt-tracker-timeout");
 // values: 1*digit
-const std::string PREF_BT_TRACKER_CONNECT_TIMEOUT("bt-tracker-connect-timeout");
+const Pref* PREF_BT_TRACKER_CONNECT_TIMEOUT = makePref("bt-tracker-connect-timeout");
 // values: 1*digit
-const std::string PREF_DHT_MESSAGE_TIMEOUT("dht-message-timeout");
+const Pref* PREF_DHT_MESSAGE_TIMEOUT = makePref("dht-message-timeout");
 // values: string
-const std::string PREF_ON_BT_DOWNLOAD_COMPLETE("on-bt-download-complete");
+const Pref* PREF_ON_BT_DOWNLOAD_COMPLETE = makePref("on-bt-download-complete");
 // values: string
-const std::string PREF_BT_TRACKER("bt-tracker");
+const Pref* PREF_BT_TRACKER = makePref("bt-tracker");
 // values: string
-const std::string PREF_BT_EXCLUDE_TRACKER("bt-exclude-tracker");
+const Pref* PREF_BT_EXCLUDE_TRACKER = makePref("bt-exclude-tracker");
 
 /**
  * Metalink related preferences
  */
 // values: a string that your file system recognizes as a file name.
-const std::string PREF_METALINK_FILE("metalink-file");
+const Pref* PREF_METALINK_FILE = makePref("metalink-file");
 // values: a string
-const std::string PREF_METALINK_VERSION("metalink-version");
+const Pref* PREF_METALINK_VERSION = makePref("metalink-version");
 // values: a string
-const std::string PREF_METALINK_LANGUAGE("metalink-language");
+const Pref* PREF_METALINK_LANGUAGE = makePref("metalink-language");
 // values: a string
-const std::string PREF_METALINK_OS("metalink-os");
+const Pref* PREF_METALINK_OS = makePref("metalink-os");
 // values: a string
-const std::string PREF_METALINK_LOCATION("metalink-location");
+const Pref* PREF_METALINK_LOCATION = makePref("metalink-location");
 // values: 1*digit
-const std::string PREF_METALINK_SERVERS("metalink-servers");
+const Pref* PREF_METALINK_SERVERS = makePref("metalink-servers");
 // values: true | false | mem
-const std::string PREF_FOLLOW_METALINK("follow-metalink");
+const Pref* PREF_FOLLOW_METALINK = makePref("follow-metalink");
 // values: http | https | ftp | none
-const std::string PREF_METALINK_PREFERRED_PROTOCOL("metalink-preferred-protocol");
-const std::string V_HTTP("http");
-const std::string V_HTTPS("https");
-const std::string V_FTP("ftp");
+const Pref* PREF_METALINK_PREFERRED_PROTOCOL = makePref("metalink-preferred-protocol");
 // values: true | false
-const std::string PREF_METALINK_ENABLE_UNIQUE_PROTOCOL("metalink-enable-unique-protocol");
-const std::string PREF_METALINK_BASE_URI("metalink-base-uri");
+const Pref* PREF_METALINK_ENABLE_UNIQUE_PROTOCOL = makePref("metalink-enable-unique-protocol");
+const Pref* PREF_METALINK_BASE_URI = makePref("metalink-base-uri");
 
 } // namespace aria2

+ 227 - 202
src/prefs.h

@@ -40,6 +40,28 @@
 
 namespace aria2 {
 
+struct Pref {
+  Pref(const std::string& k, size_t i);
+  // Keyword, aka Option Name
+  std::string k;
+  // Option ID
+  size_t i;
+};
+
+namespace option {
+
+// Returns the number of options.
+size_t countOption();
+
+// Returns Pref whose ID is id. id must be less than countOption().
+const Pref* i2p(size_t id);
+
+// Returns Pref whose keyword is k. If no such Pref is found, returns
+// special null Pref whose ID is 0.
+const Pref* k2p(const std::string& k);
+
+} // namespace option
+
 /**
  * Constants
  */
@@ -51,390 +73,393 @@ extern const std::string V_MEM;
 extern const std::string V_ALL;
 extern const std::string A2_V_FULL;
 extern const std::string A2_V_GEOM;
+extern const std::string V_PREALLOC;
+extern const std::string V_FALLOC;
+extern const std::string V_DEBUG;
+extern const std::string V_INFO;
+extern const std::string V_NOTICE;
+extern const std::string V_WARN;
+extern const std::string V_ERROR;
+extern const std::string V_INORDER;
+extern const std::string V_FEEDBACK;
+extern const std::string V_ADAPTIVE;
+extern const std::string V_EPOLL;
+extern const std::string V_KQUEUE;
+extern const std::string V_PORT;
+extern const std::string V_POLL;
+extern const std::string V_SELECT;
+extern const std::string V_BINARY;
+extern const std::string V_ASCII;
+extern const std::string V_GET;
+extern const std::string V_TUNNEL;
+extern const std::string V_PLAIN;
+extern const std::string V_ARC4;
+extern const std::string V_HTTP;
+extern const std::string V_HTTPS;
+extern const std::string V_FTP;
+
+extern const Pref* PREF_VERSION;
+extern const Pref* PREF_HELP;
 
 /**
  * General preferences
  */
 // values: 1*digit
-extern const std::string PREF_TIMEOUT;
+extern const Pref* PREF_TIMEOUT;
 // values: 1*digit
-extern const std::string PREF_DNS_TIMEOUT;
+extern const Pref* PREF_DNS_TIMEOUT;
 // values: 1*digit
-extern const std::string PREF_CONNECT_TIMEOUT;
+extern const Pref* PREF_CONNECT_TIMEOUT;
 // values: 1*digit
-extern const std::string PREF_MAX_TRIES;
+extern const Pref* PREF_MAX_TRIES;
 // values: 1*digit
-extern const std::string PREF_AUTO_SAVE_INTERVAL;
+extern const Pref* PREF_AUTO_SAVE_INTERVAL;
 // values: a string that your file system recognizes as a file name.
-extern const std::string PREF_LOG;
+extern const Pref* PREF_LOG;
 // values: a string that your file system recognizes as a directory.
-extern const std::string PREF_DIR;
+extern const Pref* PREF_DIR;
 // values: a string that your file system recognizes as a file name.
-extern const std::string PREF_OUT;
+extern const Pref* PREF_OUT;
 // values: 1*digit
-extern const std::string PREF_SPLIT;
+extern const Pref* PREF_SPLIT;
 // value: true | false
-extern const std::string PREF_DAEMON;
+extern const Pref* PREF_DAEMON;
 // value: a string
-extern const std::string PREF_REFERER;
+extern const Pref* PREF_REFERER;
 // value: 1*digit
-extern const std::string PREF_LOWEST_SPEED_LIMIT;
+extern const Pref* PREF_LOWEST_SPEED_LIMIT;
 // value: 1*digit
-extern const std::string PREF_PIECE_LENGTH;
+extern const Pref* PREF_PIECE_LENGTH;
 // value: 1*digit
-extern const std::string PREF_MAX_DOWNLOAD_LIMIT;
+extern const Pref* PREF_MAX_DOWNLOAD_LIMIT;
 // value: 1*digit
-extern const std::string PREF_STARTUP_IDLE_TIME;
+extern const Pref* PREF_STARTUP_IDLE_TIME;
 // value: prealloc | falloc | none
-extern const std::string PREF_FILE_ALLOCATION;
-extern const std::string V_PREALLOC;
-extern const std::string V_FALLOC;
+extern const Pref* PREF_FILE_ALLOCATION;
 // value: 1*digit
-extern const std::string PREF_NO_FILE_ALLOCATION_LIMIT;
+extern const Pref* PREF_NO_FILE_ALLOCATION_LIMIT;
 // value: true | false
-extern const std::string PREF_ALLOW_OVERWRITE;
+extern const Pref* PREF_ALLOW_OVERWRITE;
 // value: true | false
-extern const std::string PREF_REALTIME_CHUNK_CHECKSUM;
+extern const Pref* PREF_REALTIME_CHUNK_CHECKSUM;
 // value: true | false
-extern const std::string PREF_CHECK_INTEGRITY;
+extern const Pref* PREF_CHECK_INTEGRITY;
 // value: string that your file system recognizes as a file name.
-extern const std::string PREF_NETRC_PATH;
+extern const Pref* PREF_NETRC_PATH;
 // value:
-extern const std::string PREF_CONTINUE;
+extern const Pref* PREF_CONTINUE;
 // value:
-extern const std::string PREF_NO_NETRC;
+extern const Pref* PREF_NO_NETRC;
 // value: 1*digit
-extern const std::string PREF_MAX_OVERALL_DOWNLOAD_LIMIT;
+extern const Pref* PREF_MAX_OVERALL_DOWNLOAD_LIMIT;
 // value: 1*digit
-extern const std::string PREF_MAX_DOWNLOADS;
+extern const Pref* PREF_MAX_DOWNLOADS;
 // value: string that your file system recognizes as a file name.
-extern const std::string PREF_INPUT_FILE;
+extern const Pref* PREF_INPUT_FILE;
 // value: 1*digit
-extern const std::string PREF_MAX_CONCURRENT_DOWNLOADS;
+extern const Pref* PREF_MAX_CONCURRENT_DOWNLOADS;
 // value: true | false
-extern const std::string PREF_FORCE_SEQUENTIAL;
+extern const Pref* PREF_FORCE_SEQUENTIAL;
 // value: true | false
-extern const std::string PREF_AUTO_FILE_RENAMING;
+extern const Pref* PREF_AUTO_FILE_RENAMING;
 // value: true | false
-extern const std::string PREF_PARAMETERIZED_URI;
+extern const Pref* PREF_PARAMETERIZED_URI;
 // value: true | false
-extern const std::string PREF_ENABLE_DIRECT_IO;
+extern const Pref* PREF_ENABLE_DIRECT_IO;
 // value: true | false
-extern const std::string PREF_ALLOW_PIECE_LENGTH_CHANGE;
+extern const Pref* PREF_ALLOW_PIECE_LENGTH_CHANGE;
 // value: true | false
-extern const std::string PREF_NO_CONF;
+extern const Pref* PREF_NO_CONF;
 // value: string
-extern const std::string PREF_CONF_PATH;
+extern const Pref* PREF_CONF_PATH;
 // value: 1*digit
-extern const std::string PREF_STOP;
+extern const Pref* PREF_STOP;
 // value: true | false
-extern const std::string PREF_QUIET;
+extern const Pref* PREF_QUIET;
 // value: true | false
-extern const std::string PREF_ASYNC_DNS;
+extern const Pref* PREF_ASYNC_DNS;
 // value: 1*digit
-extern const std::string PREF_SUMMARY_INTERVAL;
+extern const Pref* PREF_SUMMARY_INTERVAL;
 // value: debug, info, notice, warn, error
-extern const std::string PREF_LOG_LEVEL;
-extern const std::string V_DEBUG;
-extern const std::string V_INFO;
-extern const std::string V_NOTICE;
-extern const std::string V_WARN;
-extern const std::string V_ERROR;
+extern const Pref* PREF_LOG_LEVEL;
 // value: inorder | feedback | adaptive
-extern const std::string PREF_URI_SELECTOR;
-extern const std::string V_INORDER;
-extern const std::string V_FEEDBACK;
-extern const std::string V_ADAPTIVE;
+extern const Pref* PREF_URI_SELECTOR;
 // value: 1*digit
-extern const std::string PREF_SERVER_STAT_TIMEOUT;
+extern const Pref* PREF_SERVER_STAT_TIMEOUT;
 // value: string that your file system recognizes as a file name.
-extern const std::string PREF_SERVER_STAT_IF;
+extern const Pref* PREF_SERVER_STAT_IF;
 // value: string that your file system recognizes as a file name.
-extern const std::string PREF_SERVER_STAT_OF;
+extern const Pref* PREF_SERVER_STAT_OF;
 // value: true | false
-extern const std::string PREF_REMOTE_TIME;
+extern const Pref* PREF_REMOTE_TIME;
 // value: 1*digit
-extern const std::string PREF_MAX_FILE_NOT_FOUND;
+extern const Pref* PREF_MAX_FILE_NOT_FOUND;
 // value: epoll | select
-extern const std::string PREF_EVENT_POLL;
-extern const std::string V_EPOLL;
-extern const std::string V_KQUEUE;
-extern const std::string V_PORT;
-extern const std::string V_POLL;
-extern const std::string V_SELECT;
+extern const Pref* PREF_EVENT_POLL;
 // value: true | false
-extern const std::string PREF_ENABLE_RPC;
+extern const Pref* PREF_ENABLE_RPC;
 // value: 1*digit
-extern const std::string PREF_RPC_LISTEN_PORT;
+extern const Pref* PREF_RPC_LISTEN_PORT;
 // value: string
-extern const std::string PREF_RPC_USER;
+extern const Pref* PREF_RPC_USER;
 // value: string
-extern const std::string PREF_RPC_PASSWD;
+extern const Pref* PREF_RPC_PASSWD;
 // value: 1*digit
-extern const std::string PREF_RPC_MAX_REQUEST_SIZE;
+extern const Pref* PREF_RPC_MAX_REQUEST_SIZE;
 // value: true | false
-extern const std::string PREF_RPC_LISTEN_ALL;
+extern const Pref* PREF_RPC_LISTEN_ALL;
 // value: true | false
-extern const std::string PREF_RPC_ALLOW_ORIGIN_ALL;
+extern const Pref* PREF_RPC_ALLOW_ORIGIN_ALL;
 // value: true | false
-extern const std::string PREF_DRY_RUN;
+extern const Pref* PREF_DRY_RUN;
 // value: true | false
-extern const std::string PREF_REUSE_URI;
+extern const Pref* PREF_REUSE_URI;
 // value: string
-extern const std::string PREF_ON_DOWNLOAD_START;
-extern const std::string PREF_ON_DOWNLOAD_PAUSE;
-extern const std::string PREF_ON_DOWNLOAD_STOP;
-extern const std::string PREF_ON_DOWNLOAD_COMPLETE;
-extern const std::string PREF_ON_DOWNLOAD_ERROR;
+extern const Pref* PREF_ON_DOWNLOAD_START;
+extern const Pref* PREF_ON_DOWNLOAD_PAUSE;
+extern const Pref* PREF_ON_DOWNLOAD_STOP;
+extern const Pref* PREF_ON_DOWNLOAD_COMPLETE;
+extern const Pref* PREF_ON_DOWNLOAD_ERROR;
 // value: string
-extern const std::string PREF_INTERFACE;
+extern const Pref* PREF_INTERFACE;
 // value: true | false
-extern const std::string PREF_DISABLE_IPV6;
+extern const Pref* PREF_DISABLE_IPV6;
 // value: true | false
-extern const std::string PREF_HUMAN_READABLE;
+extern const Pref* PREF_HUMAN_READABLE;
 // value: true | false
-extern const std::string PREF_REMOVE_CONTROL_FILE;
+extern const Pref* PREF_REMOVE_CONTROL_FILE;
 // value: true | false
-extern const std::string PREF_ALWAYS_RESUME;
+extern const Pref* PREF_ALWAYS_RESUME;
 // value: 1*digit
-extern const std::string PREF_MAX_RESUME_FAILURE_TRIES;
+extern const Pref* PREF_MAX_RESUME_FAILURE_TRIES;
 // value: string that your file system recognizes as a file name.
-extern const std::string PREF_SAVE_SESSION;
+extern const Pref* PREF_SAVE_SESSION;
 // value: 1*digit
-extern const std::string PREF_MAX_CONNECTION_PER_SERVER;
+extern const Pref* PREF_MAX_CONNECTION_PER_SERVER;
 // value: 1*digit
-extern const std::string PREF_MIN_SPLIT_SIZE;
+extern const Pref* PREF_MIN_SPLIT_SIZE;
 // value: true | false
-extern const std::string PREF_CONDITIONAL_GET;
+extern const Pref* PREF_CONDITIONAL_GET;
 // value: true | false
-extern const std::string PREF_SELECT_LEAST_USED_HOST;
+extern const Pref* PREF_SELECT_LEAST_USED_HOST;
 // value: true | false
-extern const std::string PREF_ENABLE_ASYNC_DNS6;
+extern const Pref* PREF_ENABLE_ASYNC_DNS6;
 // value: 1*digit
-extern const std::string PREF_MAX_DOWNLOAD_RESULT;
+extern const Pref* PREF_MAX_DOWNLOAD_RESULT;
 // value: 1*digit
-extern const std::string PREF_RETRY_WAIT;
+extern const Pref* PREF_RETRY_WAIT;
 // value: string
-extern const std::string PREF_ASYNC_DNS_SERVER;
+extern const Pref* PREF_ASYNC_DNS_SERVER;
 // value: true | false
-extern const std::string PREF_SHOW_CONSOLE_READOUT;
+extern const Pref* PREF_SHOW_CONSOLE_READOUT;
 // value: default | inorder | geom
-extern const std::string PREF_STREAM_PIECE_SELECTOR;
+extern const Pref* PREF_STREAM_PIECE_SELECTOR;
 // value: true | false
-extern const std::string PREF_TRUNCATE_CONSOLE_READOUT;
+extern const Pref* PREF_TRUNCATE_CONSOLE_READOUT;
 // value: true | false
-extern const std::string PREF_PAUSE;
+extern const Pref* PREF_PAUSE;
 // value: default | full
-extern const std::string PREF_DOWNLOAD_RESULT;
+extern const Pref* PREF_DOWNLOAD_RESULT;
 // value: true | false
-extern const std::string PREF_HASH_CHECK_ONLY;
+extern const Pref* PREF_HASH_CHECK_ONLY;
 
 /**
  * FTP related preferences
  */
-extern const std::string PREF_FTP_USER;
-extern const std::string PREF_FTP_PASSWD;
+extern const Pref* PREF_FTP_USER;
+extern const Pref* PREF_FTP_PASSWD;
 // values: binary | ascii
-extern const std::string PREF_FTP_TYPE;
-extern const std::string V_BINARY;
-extern const std::string V_ASCII;
+extern const Pref* PREF_FTP_TYPE;
 // values: true | false
-extern const std::string PREF_FTP_PASV;
+extern const Pref* PREF_FTP_PASV;
 // values: true | false
-extern const std::string PREF_FTP_REUSE_CONNECTION;
+extern const Pref* PREF_FTP_REUSE_CONNECTION;
 // values: hashType=digest
-extern const std::string PREF_CHECKSUM;
+extern const Pref* PREF_CHECKSUM;
 
 /**
  * HTTP related preferences
  */
-extern const std::string PREF_HTTP_USER;
-extern const std::string PREF_HTTP_PASSWD;
+extern const Pref* PREF_HTTP_USER;
+extern const Pref* PREF_HTTP_PASSWD;
 // values: string
-extern const std::string PREF_USER_AGENT;
+extern const Pref* PREF_USER_AGENT;
 // value: string that your file system recognizes as a file name.
-extern const std::string PREF_LOAD_COOKIES;
+extern const Pref* PREF_LOAD_COOKIES;
 // value: string that your file system recognizes as a file name.
-extern const std::string PREF_SAVE_COOKIES;
+extern const Pref* PREF_SAVE_COOKIES;
 // values: true | false
-extern const std::string PREF_ENABLE_HTTP_KEEP_ALIVE;
+extern const Pref* PREF_ENABLE_HTTP_KEEP_ALIVE;
 // values: true | false
-extern const std::string PREF_ENABLE_HTTP_PIPELINING;
+extern const Pref* PREF_ENABLE_HTTP_PIPELINING;
 // value: 1*digit
-extern const std::string PREF_MAX_HTTP_PIPELINING;
+extern const Pref* PREF_MAX_HTTP_PIPELINING;
 // value: string
-extern const std::string PREF_HEADER;
+extern const Pref* PREF_HEADER;
 // value: string that your file system recognizes as a file name.
-extern const std::string PREF_CERTIFICATE;
+extern const Pref* PREF_CERTIFICATE;
 // value: string that your file system recognizes as a file name.
-extern const std::string PREF_PRIVATE_KEY;
+extern const Pref* PREF_PRIVATE_KEY;
 // value: string that your file system recognizes as a file name.
-extern const std::string PREF_CA_CERTIFICATE;
+extern const Pref* PREF_CA_CERTIFICATE;
 // value: true | false
-extern const std::string PREF_CHECK_CERTIFICATE;
+extern const Pref* PREF_CHECK_CERTIFICATE;
 // value: true | false
-extern const std::string PREF_USE_HEAD;
+extern const Pref* PREF_USE_HEAD;
 // value: true | false
-extern const std::string PREF_HTTP_AUTH_CHALLENGE;
+extern const Pref* PREF_HTTP_AUTH_CHALLENGE;
 // value: true | false
-extern const std::string PREF_HTTP_NO_CACHE;
+extern const Pref* PREF_HTTP_NO_CACHE;
 // value: true | false
-extern const std::string PREF_HTTP_ACCEPT_GZIP;
+extern const Pref* PREF_HTTP_ACCEPT_GZIP;
 
 /**;
  * Proxy related preferences
  */
-extern const std::string PREF_HTTP_PROXY;
-extern const std::string PREF_HTTPS_PROXY;
-extern const std::string PREF_FTP_PROXY;
-extern const std::string PREF_ALL_PROXY;
+extern const Pref* PREF_HTTP_PROXY;
+extern const Pref* PREF_HTTPS_PROXY;
+extern const Pref* PREF_FTP_PROXY;
+extern const Pref* PREF_ALL_PROXY;
 // values: comma separeted hostname or domain
-extern const std::string PREF_NO_PROXY;
+extern const Pref* PREF_NO_PROXY;
 // values: get | tunnel
-extern const std::string PREF_PROXY_METHOD;
-extern const std::string V_GET;
-extern const std::string V_TUNNEL;
-extern const std::string PREF_HTTP_PROXY_USER;
-extern const std::string PREF_HTTP_PROXY_PASSWD;
-extern const std::string PREF_HTTPS_PROXY_USER;
-extern const std::string PREF_HTTPS_PROXY_PASSWD;
-extern const std::string PREF_FTP_PROXY_USER;
-extern const std::string PREF_FTP_PROXY_PASSWD;
-extern const std::string PREF_ALL_PROXY_USER;
-extern const std::string PREF_ALL_PROXY_PASSWD;
+extern const Pref* PREF_PROXY_METHOD;
+extern const Pref* PREF_HTTP_PROXY_USER;
+extern const Pref* PREF_HTTP_PROXY_PASSWD;
+extern const Pref* PREF_HTTPS_PROXY_USER;
+extern const Pref* PREF_HTTPS_PROXY_PASSWD;
+extern const Pref* PREF_FTP_PROXY_USER;
+extern const Pref* PREF_FTP_PROXY_PASSWD;
+extern const Pref* PREF_ALL_PROXY_USER;
+extern const Pref* PREF_ALL_PROXY_PASSWD;
 
 /**
  * BitTorrent related preferences
  */
 // values: 1*digit
-extern const std::string PREF_PEER_CONNECTION_TIMEOUT;
+extern const Pref* PREF_PEER_CONNECTION_TIMEOUT;
 // values: 1*digit
-extern const std::string PREF_BT_TIMEOUT;
+extern const Pref* PREF_BT_TIMEOUT;
 // values: 1*digit
-extern const std::string PREF_BT_REQUEST_TIMEOUT;
+extern const Pref* PREF_BT_REQUEST_TIMEOUT;
 // values: true | false
-extern const std::string PREF_SHOW_FILES;
+extern const Pref* PREF_SHOW_FILES;
 // values: 1*digit
-extern const std::string PREF_MAX_OVERALL_UPLOAD_LIMIT;
+extern const Pref* PREF_MAX_OVERALL_UPLOAD_LIMIT;
 // values: 1*digit
-extern const std::string PREF_MAX_UPLOAD_LIMIT;
+extern const Pref* PREF_MAX_UPLOAD_LIMIT;
 // values: a string that your file system recognizes as a file name.
-extern const std::string PREF_TORRENT_FILE;
+extern const Pref* PREF_TORRENT_FILE;
 // values: 1*digit
-extern const std::string PREF_LISTEN_PORT;
+extern const Pref* PREF_LISTEN_PORT;
 // values: true | false | mem
-extern const std::string PREF_FOLLOW_TORRENT;
+extern const Pref* PREF_FOLLOW_TORRENT;
 // values: 1*digit *( (,|-) 1*digit)
-extern const std::string PREF_SELECT_FILE;
+extern const Pref* PREF_SELECT_FILE;
 // values: 1*digit
-extern const std::string PREF_SEED_TIME;
+extern const Pref* PREF_SEED_TIME;
 // values: 1*digit ['.' [ 1*digit ] ]
-extern const std::string PREF_SEED_RATIO;
+extern const Pref* PREF_SEED_RATIO;
 // values: 1*digit
-extern const std::string PREF_BT_KEEP_ALIVE_INTERVAL;
+extern const Pref* PREF_BT_KEEP_ALIVE_INTERVAL;
 // values: a string, less than or equals to 20 bytes length
-extern const std::string PREF_PEER_ID_PREFIX;
+extern const Pref* PREF_PEER_ID_PREFIX;
 // values: true | false
-extern const std::string PREF_ENABLE_PEER_EXCHANGE;
+extern const Pref* PREF_ENABLE_PEER_EXCHANGE;
 // values: true | false
-extern const std::string PREF_ENABLE_DHT;
+extern const Pref* PREF_ENABLE_DHT;
 // values: a string
-extern const std::string PREF_DHT_LISTEN_ADDR;
+extern const Pref* PREF_DHT_LISTEN_ADDR;
 // values: 1*digit
-extern const std::string PREF_DHT_LISTEN_PORT;
+extern const Pref* PREF_DHT_LISTEN_PORT;
 // values: a string
-extern const std::string PREF_DHT_ENTRY_POINT_HOST;
+extern const Pref* PREF_DHT_ENTRY_POINT_HOST;
 // values: 1*digit
-extern const std::string PREF_DHT_ENTRY_POINT_PORT;
+extern const Pref* PREF_DHT_ENTRY_POINT_PORT;
 // values: a string (hostname:port)
-extern const std::string PREF_DHT_ENTRY_POINT;
+extern const Pref* PREF_DHT_ENTRY_POINT;
 // values: a string
-extern const std::string PREF_DHT_FILE_PATH;
+extern const Pref* PREF_DHT_FILE_PATH;
 // values: true | false
-extern const std::string PREF_ENABLE_DHT6;
+extern const Pref* PREF_ENABLE_DHT6;
 // values: a string
-extern const std::string PREF_DHT_LISTEN_ADDR6;
+extern const Pref* PREF_DHT_LISTEN_ADDR6;
 // values: a string
-extern const std::string PREF_DHT_ENTRY_POINT_HOST6;
+extern const Pref* PREF_DHT_ENTRY_POINT_HOST6;
 // values: 1*digit
-extern const std::string PREF_DHT_ENTRY_POINT_PORT6;
+extern const Pref* PREF_DHT_ENTRY_POINT_PORT6;
 // values: a string (hostname:port)
-extern const std::string PREF_DHT_ENTRY_POINT6;
+extern const Pref* PREF_DHT_ENTRY_POINT6;
 // values: a string
-extern const std::string PREF_DHT_FILE_PATH6;
+extern const Pref* PREF_DHT_FILE_PATH6;
 // values: plain | arc4
-extern const std::string PREF_BT_MIN_CRYPTO_LEVEL;
-extern const std::string V_PLAIN;
-extern const std::string V_ARC4;
+extern const Pref* PREF_BT_MIN_CRYPTO_LEVEL;
 // values:: true | false
-extern const std::string PREF_BT_REQUIRE_CRYPTO;
+extern const Pref* PREF_BT_REQUIRE_CRYPTO;
 // values: 1*digit
-extern const std::string PREF_BT_REQUEST_PEER_SPEED_LIMIT;
+extern const Pref* PREF_BT_REQUEST_PEER_SPEED_LIMIT;
 // values: 1*digit
-extern const std::string PREF_BT_MAX_OPEN_FILES;
+extern const Pref* PREF_BT_MAX_OPEN_FILES;
 // values: true | false
-extern const std::string PREF_BT_SEED_UNVERIFIED;
+extern const Pref* PREF_BT_SEED_UNVERIFIED;
 // values: true | false
-extern const std::string PREF_BT_HASH_CHECK_SEED;
+extern const Pref* PREF_BT_HASH_CHECK_SEED;
 // values: 1*digit
-extern const std::string PREF_BT_MAX_PEERS;
+extern const Pref* PREF_BT_MAX_PEERS;
 // values: a string (IP address)
-extern const std::string PREF_BT_EXTERNAL_IP;
+extern const Pref* PREF_BT_EXTERNAL_IP;
 // values: 1*digit '=' a string that your file system recognizes as a file name.
-extern const std::string PREF_INDEX_OUT;
+extern const Pref* PREF_INDEX_OUT;
 // values: 1*digit
-extern const std::string PREF_BT_TRACKER_INTERVAL;
+extern const Pref* PREF_BT_TRACKER_INTERVAL;
 // values: 1*digit
-extern const std::string PREF_BT_STOP_TIMEOUT;
+extern const Pref* PREF_BT_STOP_TIMEOUT;
 // values: head[=SIZE]|tail[=SIZE], ...
-extern const std::string PREF_BT_PRIORITIZE_PIECE;
+extern const Pref* PREF_BT_PRIORITIZE_PIECE;
 // values: true | false
-extern const std::string PREF_BT_SAVE_METADATA;
+extern const Pref* PREF_BT_SAVE_METADATA;
 // values: true | false
-extern const std::string PREF_BT_METADATA_ONLY;
+extern const Pref* PREF_BT_METADATA_ONLY;
 // values: true | false
-extern const std::string PREF_BT_ENABLE_LPD;
+extern const Pref* PREF_BT_ENABLE_LPD;
 // values: string
-extern const std::string PREF_BT_LPD_INTERFACE;
+extern const Pref* PREF_BT_LPD_INTERFACE;
 // values: 1*digit
-extern const std::string PREF_BT_TRACKER_TIMEOUT;
+extern const Pref* PREF_BT_TRACKER_TIMEOUT;
 // values: 1*digit
-extern const std::string PREF_BT_TRACKER_CONNECT_TIMEOUT;
+extern const Pref* PREF_BT_TRACKER_CONNECT_TIMEOUT;
 // values: 1*digit
-extern const std::string PREF_DHT_MESSAGE_TIMEOUT;
+extern const Pref* PREF_DHT_MESSAGE_TIMEOUT;
 // values: string
-extern const std::string PREF_ON_BT_DOWNLOAD_COMPLETE;
+extern const Pref* PREF_ON_BT_DOWNLOAD_COMPLETE;
 // values: string
-extern const std::string PREF_BT_TRACKER;
+extern const Pref* PREF_BT_TRACKER;
 // values: string
-extern const std::string PREF_BT_EXCLUDE_TRACKER;
+extern const Pref* PREF_BT_EXCLUDE_TRACKER;
 
 /**
  * Metalink related preferences
  */
 // values: a string that your file system recognizes as a file name.
-extern const std::string PREF_METALINK_FILE;
+extern const Pref* PREF_METALINK_FILE;
 // values: a string
-extern const std::string PREF_METALINK_VERSION;
+extern const Pref* PREF_METALINK_VERSION;
 // values: a string
-extern const std::string PREF_METALINK_LANGUAGE;
+extern const Pref* PREF_METALINK_LANGUAGE;
 // values: a string
-extern const std::string PREF_METALINK_OS;
+extern const Pref* PREF_METALINK_OS;
 // values: a string
-extern const std::string PREF_METALINK_LOCATION;
+extern const Pref* PREF_METALINK_LOCATION;
 // values: 1*digit
-extern const std::string PREF_METALINK_SERVERS;
+extern const Pref* PREF_METALINK_SERVERS;
 // values: true | false | mem
-extern const std::string PREF_FOLLOW_METALINK;
+extern const Pref* PREF_FOLLOW_METALINK;
 // values: http | https | ftp | none
-extern const std::string PREF_METALINK_PREFERRED_PROTOCOL;
-extern const std::string V_HTTP;
-extern const std::string V_HTTPS;
-extern const std::string V_FTP;
+extern const Pref* PREF_METALINK_PREFERRED_PROTOCOL;
 // values: true | false
-extern const std::string PREF_METALINK_ENABLE_UNIQUE_PROTOCOL;
+extern const Pref* PREF_METALINK_ENABLE_UNIQUE_PROTOCOL;
 // values: a string
-extern const std::string PREF_METALINK_BASE_URI;
+extern const Pref* PREF_METALINK_BASE_URI;
 
 } // namespace aria2
 

+ 7 - 5
src/util.cc

@@ -71,6 +71,7 @@
 #include "DownloadContext.h"
 #include "BufferedFile.h"
 #include "SocketCore.h"
+#include "prefs.h"
 
 #ifdef ENABLE_MESSAGE_DIGEST
 # include "MessageDigest.h"
@@ -1698,15 +1699,16 @@ void executeHook
 
 void executeHookByOptName
 (const SharedHandle<RequestGroup>& group, const Option* option,
- const std::string& opt)
+ const Pref* pref)
 {
-  executeHookByOptName(group.get(), option, opt);
+  executeHookByOptName(group.get(), option, pref);
 }
 
 void executeHookByOptName
-(const RequestGroup* group, const Option* option, const std::string& opt)
+(const RequestGroup* group, const Option* option, const Pref* pref)
 {
-  if(!option->blank(opt)) {
+  const std::string& cmd = option->get(pref);
+  if(!cmd.empty()) {
     const SharedHandle<DownloadContext> dctx = group->getDownloadContext();
     std::string firstFilename;
     size_t numFiles = 0;
@@ -1717,7 +1719,7 @@ void executeHookByOptName
       }
       numFiles = dctx->countRequestedFileEntry();
     }
-    executeHook(option->get(opt), group->getGID(), numFiles, firstFilename);
+    executeHook(cmd, group->getGID(), numFiles, firstFilename);
   }
 }
 

+ 3 - 2
src/util.h

@@ -64,6 +64,7 @@ class BinaryStream;
 class FileEntry;
 class RequestGroup;
 class Option;
+class Pref;
 
 #define STRTOLL(X) strtoll(X, reinterpret_cast<char**>(0), 10)
 #define STRTOULL(X) strtoull(X, reinterpret_cast<char**>(0), 10)
@@ -441,11 +442,11 @@ void removeMetalinkContentTypes(RequestGroup* group);
 // No throw
 void executeHookByOptName
 (const SharedHandle<RequestGroup>& group, const Option* option,
- const std::string& opt);
+ const Pref* pref);
 
 // No throw
 void executeHookByOptName
-(const RequestGroup* group, const Option* option, const std::string& opt);
+(const RequestGroup* group, const Option* option, const Pref* pref);
 
 std::string createSafePath(const std::string& dir, const std::string& filename);
 

+ 54 - 54
test/OptionHandlerTest.cc

@@ -63,19 +63,19 @@ void OptionHandlerTest::testNullOptionHandler()
   CPPUNIT_ASSERT(handler.canHandle("foo"));
   Option option;
   handler.parse(option, "bar");
-  CPPUNIT_ASSERT(!option.defined("bar"));
+  CPPUNIT_ASSERT(!option.defined(PREF_TIMEOUT));
 }
 
 void OptionHandlerTest::testBooleanOptionHandler()
 {
-  BooleanOptionHandler handler("foo");
-  CPPUNIT_ASSERT(handler.canHandle("foo"));
-  CPPUNIT_ASSERT(!handler.canHandle("foobar"));
+  BooleanOptionHandler handler(PREF_DAEMON);
+  CPPUNIT_ASSERT(handler.canHandle(PREF_DAEMON->k));
+  CPPUNIT_ASSERT(!handler.canHandle(PREF_DIR->k));
   Option option;
   handler.parse(option, A2_V_TRUE);
-  CPPUNIT_ASSERT_EQUAL(std::string(A2_V_TRUE), option.get("foo"));
+  CPPUNIT_ASSERT_EQUAL(std::string(A2_V_TRUE), option.get(PREF_DAEMON));
   handler.parse(option, A2_V_FALSE);
-  CPPUNIT_ASSERT_EQUAL(std::string(A2_V_FALSE), option.get("foo"));
+  CPPUNIT_ASSERT_EQUAL(std::string(A2_V_FALSE), option.get(PREF_DAEMON));
   try {
     handler.parse(option, "hello");
     CPPUNIT_FAIL("exception must be thrown.");
@@ -86,22 +86,22 @@ void OptionHandlerTest::testBooleanOptionHandler()
 
 void OptionHandlerTest::testNumberOptionHandler()
 {
-  NumberOptionHandler handler("foo");
-  CPPUNIT_ASSERT(handler.canHandle("foo"));
-  CPPUNIT_ASSERT(!handler.canHandle("foobar"));
+  NumberOptionHandler handler(PREF_TIMEOUT);
+  CPPUNIT_ASSERT(handler.canHandle(PREF_TIMEOUT->k));
+  CPPUNIT_ASSERT(!handler.canHandle(PREF_DIR->k));
   Option option;
   handler.parse(option, "0");
-  CPPUNIT_ASSERT_EQUAL(std::string("0"), option.get("foo"));
+  CPPUNIT_ASSERT_EQUAL(std::string("0"), option.get(PREF_TIMEOUT));
   CPPUNIT_ASSERT_EQUAL(std::string("*-*"),
                        handler.createPossibleValuesString());
 }
 
 void OptionHandlerTest::testNumberOptionHandler_min()
 {
-  NumberOptionHandler handler("foo", "", "", 1);
+  NumberOptionHandler handler(PREF_TIMEOUT, "", "", 1);
   Option option;
   handler.parse(option, "1");
-  CPPUNIT_ASSERT_EQUAL(std::string("1"), option.get("foo"));
+  CPPUNIT_ASSERT_EQUAL(std::string("1"), option.get(PREF_TIMEOUT));
   try {
     handler.parse(option, "0");
     CPPUNIT_FAIL("exception must be thrown.");
@@ -112,10 +112,10 @@ void OptionHandlerTest::testNumberOptionHandler_min()
 
 void OptionHandlerTest::testNumberOptionHandler_max()
 {
-  NumberOptionHandler handler("foo", "", "", -1, 100);
+  NumberOptionHandler handler(PREF_TIMEOUT, "", "", -1, 100);
   Option option;
   handler.parse(option, "100");
-  CPPUNIT_ASSERT_EQUAL(std::string("100"), option.get("foo"));
+  CPPUNIT_ASSERT_EQUAL(std::string("100"), option.get(PREF_TIMEOUT));
   try {
     handler.parse(option, "101");
     CPPUNIT_FAIL("exception must be thrown.");
@@ -126,12 +126,12 @@ void OptionHandlerTest::testNumberOptionHandler_max()
 
 void OptionHandlerTest::testNumberOptionHandler_min_max()
 {
-  NumberOptionHandler handler("foo", "", "", 1, 100);
+  NumberOptionHandler handler(PREF_TIMEOUT, "", "", 1, 100);
   Option option;
   handler.parse(option, "1");
-  CPPUNIT_ASSERT_EQUAL(std::string("1"), option.get("foo"));
+  CPPUNIT_ASSERT_EQUAL(std::string("1"), option.get(PREF_TIMEOUT));
   handler.parse(option, "100");
-  CPPUNIT_ASSERT_EQUAL(std::string("100"), option.get("foo"));
+  CPPUNIT_ASSERT_EQUAL(std::string("100"), option.get(PREF_TIMEOUT));
   try {
     handler.parse(option, "0");
     CPPUNIT_FAIL("exception must be thrown.");
@@ -146,16 +146,16 @@ void OptionHandlerTest::testNumberOptionHandler_min_max()
 
 void OptionHandlerTest::testUnitNumberOptionHandler()
 {
-  UnitNumberOptionHandler handler("foo");
-  CPPUNIT_ASSERT(handler.canHandle("foo"));
+  UnitNumberOptionHandler handler(PREF_TIMEOUT);
+  CPPUNIT_ASSERT(handler.canHandle(PREF_TIMEOUT->k));
   CPPUNIT_ASSERT(!handler.canHandle("foobar"));
   Option option;
   handler.parse(option, "4294967296");
-  CPPUNIT_ASSERT_EQUAL(std::string("4294967296"), option.get("foo"));
+  CPPUNIT_ASSERT_EQUAL(std::string("4294967296"), option.get(PREF_TIMEOUT));
   handler.parse(option, "4096M");
-  CPPUNIT_ASSERT_EQUAL(std::string("4294967296"), option.get("foo"));
+  CPPUNIT_ASSERT_EQUAL(std::string("4294967296"), option.get(PREF_TIMEOUT));
   handler.parse(option, "4096K");
-  CPPUNIT_ASSERT_EQUAL(std::string("4194304"), option.get("foo"));
+  CPPUNIT_ASSERT_EQUAL(std::string("4194304"), option.get(PREF_TIMEOUT));
   try {
     handler.parse(option, "K");
     CPPUNIT_FAIL("exception must be thrown.");
@@ -171,12 +171,12 @@ void OptionHandlerTest::testUnitNumberOptionHandler()
 
 void OptionHandlerTest::testParameterOptionHandler_1argInit()
 {
-  ParameterOptionHandler handler("foo", "", "", "value1");
-  CPPUNIT_ASSERT(handler.canHandle("foo"));
+  ParameterOptionHandler handler(PREF_TIMEOUT, "", "", "value1");
+  CPPUNIT_ASSERT(handler.canHandle(PREF_TIMEOUT->k));
   CPPUNIT_ASSERT(!handler.canHandle("foobar"));
   Option option;
   handler.parse(option, "value1");
-  CPPUNIT_ASSERT_EQUAL(std::string("value1"), option.get("foo"));
+  CPPUNIT_ASSERT_EQUAL(std::string("value1"), option.get(PREF_TIMEOUT));
   try {
     handler.parse(option, "value3");
     CPPUNIT_FAIL("exception must be thrown.");
@@ -187,14 +187,14 @@ void OptionHandlerTest::testParameterOptionHandler_1argInit()
 
 void OptionHandlerTest::testParameterOptionHandler_2argsInit()
 {
-  ParameterOptionHandler handler("foo", "", "", "value1", "value2");
-  CPPUNIT_ASSERT(handler.canHandle("foo"));
+  ParameterOptionHandler handler(PREF_TIMEOUT, "", "", "value1", "value2");
+  CPPUNIT_ASSERT(handler.canHandle(PREF_TIMEOUT->k));
   CPPUNIT_ASSERT(!handler.canHandle("foobar"));
   Option option;
   handler.parse(option, "value1");
-  CPPUNIT_ASSERT_EQUAL(std::string("value1"), option.get("foo"));
+  CPPUNIT_ASSERT_EQUAL(std::string("value1"), option.get(PREF_TIMEOUT));
   handler.parse(option, "value2");
-  CPPUNIT_ASSERT_EQUAL(std::string("value2"), option.get("foo"));
+  CPPUNIT_ASSERT_EQUAL(std::string("value2"), option.get(PREF_TIMEOUT));
   try {
     handler.parse(option, "value3");
     CPPUNIT_FAIL("exception must be thrown.");
@@ -209,14 +209,14 @@ void OptionHandlerTest::testParameterOptionHandler_listInit()
   validValues.push_back("value1");
   validValues.push_back("value2");
 
-  ParameterOptionHandler handler("foo", "", "", validValues);
-  CPPUNIT_ASSERT(handler.canHandle("foo"));
+  ParameterOptionHandler handler(PREF_TIMEOUT, "", "", validValues);
+  CPPUNIT_ASSERT(handler.canHandle(PREF_TIMEOUT->k));
   CPPUNIT_ASSERT(!handler.canHandle("foobar"));
   Option option;
   handler.parse(option, "value1");
-  CPPUNIT_ASSERT_EQUAL(std::string("value1"), option.get("foo"));
+  CPPUNIT_ASSERT_EQUAL(std::string("value1"), option.get(PREF_TIMEOUT));
   handler.parse(option, "value2");
-  CPPUNIT_ASSERT_EQUAL(std::string("value2"), option.get("foo"));
+  CPPUNIT_ASSERT_EQUAL(std::string("value2"), option.get(PREF_TIMEOUT));
   try {
     handler.parse(option, "value3");
     CPPUNIT_FAIL("exception must be thrown.");
@@ -227,14 +227,14 @@ void OptionHandlerTest::testParameterOptionHandler_listInit()
 
 void OptionHandlerTest::testDefaultOptionHandler()
 {
-  DefaultOptionHandler handler("foo");
-  CPPUNIT_ASSERT(handler.canHandle("foo"));
+  DefaultOptionHandler handler(PREF_TIMEOUT);
+  CPPUNIT_ASSERT(handler.canHandle(PREF_TIMEOUT->k));
   CPPUNIT_ASSERT(!handler.canHandle("foobar"));
   Option option;
   handler.parse(option, "bar");
-  CPPUNIT_ASSERT_EQUAL(std::string("bar"), option.get("foo"));
+  CPPUNIT_ASSERT_EQUAL(std::string("bar"), option.get(PREF_TIMEOUT));
   handler.parse(option, "");
-  CPPUNIT_ASSERT_EQUAL(std::string(""), option.get("foo"));
+  CPPUNIT_ASSERT_EQUAL(std::string(""), option.get(PREF_TIMEOUT));
   CPPUNIT_ASSERT_EQUAL(std::string(""), handler.createPossibleValuesString());
 
   handler.addTag("apple");
@@ -248,22 +248,22 @@ void OptionHandlerTest::testDefaultOptionHandler()
 
 void OptionHandlerTest::testFloatNumberOptionHandler()
 {
-  FloatNumberOptionHandler handler("foo");
-  CPPUNIT_ASSERT(handler.canHandle("foo"));
+  FloatNumberOptionHandler handler(PREF_TIMEOUT);
+  CPPUNIT_ASSERT(handler.canHandle(PREF_TIMEOUT->k));
   CPPUNIT_ASSERT(!handler.canHandle("foobar"));
   Option option;
   handler.parse(option, "1.0");
-  CPPUNIT_ASSERT_EQUAL(std::string("1.0"), option.get("foo"));
+  CPPUNIT_ASSERT_EQUAL(std::string("1.0"), option.get(PREF_TIMEOUT));
   CPPUNIT_ASSERT_EQUAL(std::string("*-*"),
                        handler.createPossibleValuesString());
 }
 
 void OptionHandlerTest::testFloatNumberOptionHandler_min()
 {
-  FloatNumberOptionHandler handler("foo", "", "", 0.0);
+  FloatNumberOptionHandler handler(PREF_TIMEOUT, "", "", 0.0);
   Option option;
   handler.parse(option, "0.0");
-  CPPUNIT_ASSERT_EQUAL(std::string("0.0"), option.get("foo"));
+  CPPUNIT_ASSERT_EQUAL(std::string("0.0"), option.get(PREF_TIMEOUT));
   try {
     handler.parse(option, "-0.1");
     CPPUNIT_FAIL("exception must be thrown.");
@@ -274,10 +274,10 @@ void OptionHandlerTest::testFloatNumberOptionHandler_min()
 
 void OptionHandlerTest::testFloatNumberOptionHandler_max()
 {
-  FloatNumberOptionHandler handler("foo", "", "", -1, 10.0);
+  FloatNumberOptionHandler handler(PREF_TIMEOUT, "", "", -1, 10.0);
   Option option;
   handler.parse(option, "10.0");
-  CPPUNIT_ASSERT_EQUAL(std::string("10.0"), option.get("foo"));
+  CPPUNIT_ASSERT_EQUAL(std::string("10.0"), option.get(PREF_TIMEOUT));
   try {
     handler.parse(option, "10.1");
     CPPUNIT_FAIL("exception must be thrown.");
@@ -288,12 +288,12 @@ void OptionHandlerTest::testFloatNumberOptionHandler_max()
 
 void OptionHandlerTest::testFloatNumberOptionHandler_min_max()
 {
-  FloatNumberOptionHandler handler("foo", "", "", 0.0, 10.0);
+  FloatNumberOptionHandler handler(PREF_TIMEOUT, "", "", 0.0, 10.0);
   Option option;
   handler.parse(option, "0.0");
-  CPPUNIT_ASSERT_EQUAL(std::string("0.0"), option.get("foo"));
+  CPPUNIT_ASSERT_EQUAL(std::string("0.0"), option.get(PREF_TIMEOUT));
   handler.parse(option, "10.0");
-  CPPUNIT_ASSERT_EQUAL(std::string("10.0"), option.get("foo"));
+  CPPUNIT_ASSERT_EQUAL(std::string("10.0"), option.get(PREF_TIMEOUT));
   try {
     handler.parse(option, "-0.1");
     CPPUNIT_FAIL("exception must be thrown.");
@@ -309,7 +309,7 @@ void OptionHandlerTest::testFloatNumberOptionHandler_min_max()
 void OptionHandlerTest::testHttpProxyOptionHandler()
 {
   HttpProxyOptionHandler handler(PREF_HTTP_PROXY, "", "");
-  CPPUNIT_ASSERT(handler.canHandle(PREF_HTTP_PROXY));
+  CPPUNIT_ASSERT(handler.canHandle(PREF_HTTP_PROXY->k));
   CPPUNIT_ASSERT(!handler.canHandle("foobar"));
   Option option;
   handler.parse(option, "proxy:65535");
@@ -425,19 +425,19 @@ void OptionHandlerTest::testDeprecatedOptionHandler()
 {
   {
     DeprecatedOptionHandler handler
-      (SharedHandle<OptionHandler>(new DefaultOptionHandler("dep")));
+      (SharedHandle<OptionHandler>(new DefaultOptionHandler(PREF_TIMEOUT)));
     Option option;
     handler.parse(option, "foo");
-    CPPUNIT_ASSERT(!option.defined("dep"));
+    CPPUNIT_ASSERT(!option.defined(PREF_TIMEOUT));
   }
   {
     DeprecatedOptionHandler handler
-      (SharedHandle<OptionHandler>(new DefaultOptionHandler("dep")),
-       SharedHandle<OptionHandler>(new DefaultOptionHandler("rep")));
+      (SharedHandle<OptionHandler>(new DefaultOptionHandler(PREF_TIMEOUT)),
+       SharedHandle<OptionHandler>(new DefaultOptionHandler(PREF_DIR)));
     Option option;
     handler.parse(option, "foo");
-    CPPUNIT_ASSERT(!option.defined("dep"));
-    CPPUNIT_ASSERT_EQUAL(std::string("foo"), option.get("rep"));
+    CPPUNIT_ASSERT(!option.defined(PREF_TIMEOUT));
+    CPPUNIT_ASSERT_EQUAL(std::string("foo"), option.get(PREF_DIR));
   }
 }
 

+ 65 - 65
test/OptionParserTest.cc

@@ -10,6 +10,7 @@
 #include "util.h"
 #include "Option.h"
 #include "array_fun.h"
+#include "prefs.h"
 
 namespace aria2 {
 
@@ -33,30 +34,31 @@ public:
   {
     oparser_.reset(new OptionParser());
 
-    SharedHandle<OptionHandler> alpha
-      (new DefaultOptionHandler("alpha", NO_DESCRIPTION, "ALPHA", "",
+    SharedHandle<OptionHandler> timeout
+      (new DefaultOptionHandler(PREF_TIMEOUT, NO_DESCRIPTION, "ALPHA", "",
                                 OptionHandler::REQ_ARG, 'A'));
-    alpha->addTag("apple");
-    alpha->setEraseAfterParse(true);
-    oparser_->addOptionHandler(alpha);
-
-    SharedHandle<OptionHandler> bravo(new DefaultOptionHandler("bravo"));
-    bravo->addTag("apple");
-    bravo->addTag("orange");
-    bravo->addTag("pineapple");
-    oparser_->addOptionHandler(bravo);
-
-    SharedHandle<DefaultOptionHandler> charlie
-      (new DefaultOptionHandler("charlie", NO_DESCRIPTION, "CHARLIE", "",
+    timeout->addTag("apple");
+    timeout->setEraseAfterParse(true);
+    oparser_->addOptionHandler(timeout);
+
+    SharedHandle<OptionHandler> dir(new DefaultOptionHandler(PREF_DIR));
+    dir->addTag("apple");
+    dir->addTag("orange");
+    dir->addTag("pineapple");
+    oparser_->addOptionHandler(dir);
+
+    SharedHandle<DefaultOptionHandler> daemon
+      (new DefaultOptionHandler(PREF_DAEMON, NO_DESCRIPTION, "CHARLIE", "",
                                 OptionHandler::REQ_ARG, 'C'));
-    charlie->hide();
-    charlie->addTag("pineapple");
-    oparser_->addOptionHandler(charlie);
-
-    SharedHandle<OptionHandler> delta
-      (new UnitNumberOptionHandler("delta", NO_DESCRIPTION, "1M", -1, -1, 'D'));
-    delta->addTag("pineapple");
-    oparser_->addOptionHandler(delta);    
+    daemon->hide();
+    daemon->addTag("pineapple");
+    oparser_->addOptionHandler(daemon);
+
+    SharedHandle<OptionHandler> out
+      (new UnitNumberOptionHandler(PREF_OUT, NO_DESCRIPTION, "1M",
+                                   -1, -1, 'D'));
+    out->addTag("pineapple");
+    oparser_->addOptionHandler(out);    
   }
 
   void tearDown() {}
@@ -79,18 +81,18 @@ void OptionParserTest::testFindAll()
 {
   std::vector<SharedHandle<OptionHandler> > res = oparser_->findAll();
   CPPUNIT_ASSERT_EQUAL((size_t)3, res.size());
-  CPPUNIT_ASSERT_EQUAL(std::string("alpha"), res[0]->getName());
-  CPPUNIT_ASSERT_EQUAL(std::string("bravo"), res[1]->getName());
-  CPPUNIT_ASSERT_EQUAL(std::string("delta"), res[2]->getName());
+  CPPUNIT_ASSERT_EQUAL(std::string("timeout"), res[0]->getName());
+  CPPUNIT_ASSERT_EQUAL(std::string("dir"), res[1]->getName());
+  CPPUNIT_ASSERT_EQUAL(std::string("out"), res[2]->getName());
 }
 
 void OptionParserTest::testFindByNameSubstring()
 {
   std::vector<SharedHandle<OptionHandler> > res =
-    oparser_->findByNameSubstring("l");
+    oparser_->findByNameSubstring("i");
   CPPUNIT_ASSERT_EQUAL((size_t)2, res.size());
-  CPPUNIT_ASSERT_EQUAL(std::string("alpha"), res[0]->getName());
-  CPPUNIT_ASSERT_EQUAL(std::string("delta"), res[1]->getName());
+  CPPUNIT_ASSERT_EQUAL(std::string("timeout"), res[0]->getName());
+  CPPUNIT_ASSERT_EQUAL(std::string("dir"), res[1]->getName());
 }
 
 void OptionParserTest::testFindByTag()
@@ -98,37 +100,37 @@ void OptionParserTest::testFindByTag()
   std::vector<SharedHandle<OptionHandler> > res =
     oparser_->findByTag("pineapple");
   CPPUNIT_ASSERT_EQUAL((size_t)2, res.size());
-  CPPUNIT_ASSERT_EQUAL(std::string("bravo"), res[0]->getName());
-  CPPUNIT_ASSERT_EQUAL(std::string("delta"), res[1]->getName());
+  CPPUNIT_ASSERT_EQUAL(std::string("dir"), res[0]->getName());
+  CPPUNIT_ASSERT_EQUAL(std::string("out"), res[1]->getName());
 }
 
 void OptionParserTest::testFindByName()
 {
-  SharedHandle<OptionHandler> bravo = oparser_->findByName("bravo");
-  CPPUNIT_ASSERT(bravo);
-  CPPUNIT_ASSERT_EQUAL(std::string("bravo"), bravo->getName());
+  SharedHandle<OptionHandler> dir = oparser_->findByName("dir");
+  CPPUNIT_ASSERT(dir);
+  CPPUNIT_ASSERT_EQUAL(std::string("dir"), dir->getName());
 
-  SharedHandle<OptionHandler> charlie = oparser_->findByName("charlie");
-  CPPUNIT_ASSERT(!charlie);
+  SharedHandle<OptionHandler> daemon = oparser_->findByName("daemon");
+  CPPUNIT_ASSERT(!daemon);
 
-  SharedHandle<OptionHandler> alpha2 = oparser_->findByName("alpha2");
-  CPPUNIT_ASSERT(!alpha2);
+  SharedHandle<OptionHandler> timeout2 = oparser_->findByName("timeout2");
+  CPPUNIT_ASSERT(!timeout2);
 }
 
 void OptionParserTest::testFindByShortName()
 {
-  SharedHandle<OptionHandler> alpha = oparser_->findByShortName('A');
-  CPPUNIT_ASSERT(alpha);
-  CPPUNIT_ASSERT_EQUAL(std::string("alpha"), alpha->getName());
+  SharedHandle<OptionHandler> timeout = oparser_->findByShortName('A');
+  CPPUNIT_ASSERT(timeout);
+  CPPUNIT_ASSERT_EQUAL(std::string("timeout"), timeout->getName());
 
   CPPUNIT_ASSERT(!oparser_->findByShortName('C'));
 }
 
 void OptionParserTest::testFindByID()
 {
-  SharedHandle<OptionHandler> alpha = oparser_->findByID(1);
-  CPPUNIT_ASSERT(alpha);
-  CPPUNIT_ASSERT_EQUAL(std::string("alpha"), alpha->getName());
+  SharedHandle<OptionHandler> timeout = oparser_->findByID(1);
+  CPPUNIT_ASSERT(timeout);
+  CPPUNIT_ASSERT_EQUAL(std::string("timeout"), timeout->getName());
 
   CPPUNIT_ASSERT(!oparser_->findByID(3));
 }
@@ -137,10 +139,10 @@ void OptionParserTest::testParseDefaultValues()
 {
   Option option;
   oparser_->parseDefaultValues(option);
-  CPPUNIT_ASSERT_EQUAL(std::string("ALPHA"), option.get("alpha"));
-  CPPUNIT_ASSERT_EQUAL(std::string("1048576"), option.get("delta"));
-  CPPUNIT_ASSERT_EQUAL(std::string("CHARLIE"), option.get("charlie"));
-  CPPUNIT_ASSERT(!option.defined("bravo"));
+  CPPUNIT_ASSERT_EQUAL(std::string("ALPHA"), option.get(PREF_TIMEOUT));
+  CPPUNIT_ASSERT_EQUAL(std::string("1048576"), option.get(PREF_OUT));
+  CPPUNIT_ASSERT_EQUAL(std::string("CHARLIE"), option.get(PREF_DAEMON));
+  CPPUNIT_ASSERT(!option.defined(PREF_DIR));
 }
 
 void OptionParserTest::testParseArg()
@@ -149,21 +151,21 @@ void OptionParserTest::testParseArg()
   char prog[7];
   strncpy(prog, "aria2c", sizeof(prog));
 
-  char optionAlpha[3];
-  strncpy(optionAlpha, "-A", sizeof(optionAlpha));
-  char argAlpha[6];
-  strncpy(argAlpha, "ALPHA", sizeof(argAlpha));
-  char optionBravo[8];
-  strncpy(optionBravo, "--bravo", sizeof(optionBravo));
-  char argBravo[6];
-  strncpy(argBravo, "BRAVO", sizeof(argBravo));
+  char optionTimeout[3];
+  strncpy(optionTimeout, "-A", sizeof(optionTimeout));
+  char argTimeout[6];
+  strncpy(argTimeout, "ALPHA", sizeof(argTimeout));
+  char optionDir[8];
+  strncpy(optionDir, "--dir", sizeof(optionDir));
+  char argDir[6];
+  strncpy(argDir, "BRAVO", sizeof(argDir));
 
   char nonopt1[8];
   strncpy(nonopt1, "nonopt1", sizeof(nonopt1));
   char nonopt2[8];
   strncpy(nonopt2, "nonopt2", sizeof(nonopt2));
 
-  char* argv[] = { prog, optionAlpha, argAlpha, optionBravo, argBravo,
+  char* argv[] = { prog, optionTimeout, argTimeout, optionDir, argDir,
                    nonopt1, nonopt2 };
   int argc = A2_ARRAY_LEN(argv);
 
@@ -172,28 +174,26 @@ void OptionParserTest::testParseArg()
 
   oparser_->parseArg(s, nonopts, argc, argv);
 
-  CPPUNIT_ASSERT_EQUAL(std::string("alpha=ALPHA\n"
-                                   "bravo=BRAVO\n"), s.str());
+  CPPUNIT_ASSERT_EQUAL(std::string("timeout=ALPHA\n"
+                                   "dir=BRAVO\n"), s.str());
 
   CPPUNIT_ASSERT_EQUAL((size_t)2, nonopts.size());
   CPPUNIT_ASSERT_EQUAL(std::string("nonopt1"), nonopts[0]);
   CPPUNIT_ASSERT_EQUAL(std::string("nonopt2"), nonopts[1]);
 
-  CPPUNIT_ASSERT_EQUAL(std::string("*****"), std::string(argAlpha));
+  CPPUNIT_ASSERT_EQUAL(std::string("*****"), std::string(argTimeout));
 }
 
 void OptionParserTest::testParse()
 {
   Option option;
-  std::istringstream in("alpha=Hello\n"
+  std::istringstream in("timeout=Hello\n"
                         "UNKNOWN=x\n"
                         "\n"
-                        "bravo=World");
+                        "dir=World");
   oparser_->parse(option, in);
-  CPPUNIT_ASSERT_EQUAL
-    ((std::ptrdiff_t)2, std::distance(option.begin(), option.end()));
-  CPPUNIT_ASSERT_EQUAL(std::string("Hello"), option.get("alpha"));
-  CPPUNIT_ASSERT_EQUAL(std::string("World"), option.get("bravo"));
+  CPPUNIT_ASSERT_EQUAL(std::string("Hello"), option.get(PREF_TIMEOUT));
+  CPPUNIT_ASSERT_EQUAL(std::string("World"), option.get(PREF_DIR));
 }
 
 } // namespace aria2

+ 22 - 18
test/OptionTest.cc

@@ -1,7 +1,11 @@
 #include "Option.h"
+
 #include <string>
+
 #include <cppunit/extensions/HelperMacros.h>
 
+#include "prefs.h"
+
 namespace aria2 {
 
 class OptionTest:public CppUnit::TestFixture {
@@ -31,45 +35,45 @@ CPPUNIT_TEST_SUITE_REGISTRATION( OptionTest );
 
 void OptionTest::testPutAndGet() {
   Option op;
-  op.put("key", "value");
+  op.put(PREF_TIMEOUT, "value");
   
-  CPPUNIT_ASSERT(op.defined("key"));
-  CPPUNIT_ASSERT_EQUAL(std::string("value"), op.get("key"));
+  CPPUNIT_ASSERT(op.defined(PREF_TIMEOUT));
+  CPPUNIT_ASSERT_EQUAL(std::string("value"), op.get(PREF_TIMEOUT));
 }
 
 void OptionTest::testPutAndGetAsInt() {
   Option op;
-  op.put("key", "1000");
+  op.put(PREF_TIMEOUT, "1000");
 
-  CPPUNIT_ASSERT(op.defined("key"));
-  CPPUNIT_ASSERT_EQUAL((int32_t)1000, op.getAsInt("key"));
+  CPPUNIT_ASSERT(op.defined(PREF_TIMEOUT));
+  CPPUNIT_ASSERT_EQUAL((int32_t)1000, op.getAsInt(PREF_TIMEOUT));
 }
 
 void OptionTest::testPutAndGetAsDouble() {
   Option op;
-  op.put("key", "10.0");
+  op.put(PREF_TIMEOUT, "10.0");
   
-  CPPUNIT_ASSERT_EQUAL(10.0, op.getAsDouble("key"));
+  CPPUNIT_ASSERT_EQUAL(10.0, op.getAsDouble(PREF_TIMEOUT));
 }
 
 void OptionTest::testDefined()
 {
   Option op;
-  op.put("k", "v");
-  op.put("k1", "");
-  CPPUNIT_ASSERT(op.defined("k"));
-  CPPUNIT_ASSERT(op.defined("k1"));
-  CPPUNIT_ASSERT(!op.defined("undefined"));
+  op.put(PREF_TIMEOUT, "v");
+  op.put(PREF_DIR, "");
+  CPPUNIT_ASSERT(op.defined(PREF_TIMEOUT));
+  CPPUNIT_ASSERT(op.defined(PREF_DIR));
+  CPPUNIT_ASSERT(!op.defined(PREF_DAEMON));
 }
 
 void OptionTest::testBlank()
 {
   Option op;
-  op.put("k", "v");
-  op.put("k1", "");
-  CPPUNIT_ASSERT(!op.blank("k"));
-  CPPUNIT_ASSERT(op.blank("k1"));
-  CPPUNIT_ASSERT(op.blank("undefined"));
+  op.put(PREF_TIMEOUT, "v");
+  op.put(PREF_DIR, "");
+  CPPUNIT_ASSERT(!op.blank(PREF_TIMEOUT));
+  CPPUNIT_ASSERT(op.blank(PREF_DIR));
+  CPPUNIT_ASSERT(op.blank(PREF_DAEMON));
 }
 
 } // namespace aria2

+ 14 - 14
test/RpcMethodTest.cc

@@ -171,7 +171,7 @@ void RpcMethodTest::testAddUri()
   }
   // with options
   SharedHandle<Dict> opt = Dict::g();
-  opt->put(PREF_DIR, "/sink");
+  opt->put(PREF_DIR->k, "/sink");
   req.params->append(opt);
   {
     RpcResponse res = m.execute(req, e_.get());
@@ -209,7 +209,7 @@ void RpcMethodTest::testAddUri_withBadOption()
   urisParam->append("http://localhost");
   req.params->append(urisParam);
   SharedHandle<Dict> opt = Dict::g();
-  opt->put(PREF_FILE_ALLOCATION, "badvalue");
+  opt->put(PREF_FILE_ALLOCATION->k, "badvalue");
   req.params->append(opt);
   RpcResponse res = m.execute(req, e_.get());
   CPPUNIT_ASSERT_EQUAL(1, res.code);
@@ -288,7 +288,7 @@ void RpcMethodTest::testAddTorrent()
   std::string dir = A2_TEST_OUT_DIR"/aria2_RpcMethodTest_testAddTorrent";
   File(dir).mkdirs();
   SharedHandle<Dict> opt = Dict::g();
-  opt->put(PREF_DIR, dir);
+  opt->put(PREF_DIR->k, dir);
   File(dir+"/0a3893293e27ac0490424c06de4d09242215f0a6.torrent").remove();
   req.params->append(opt);
   {
@@ -379,7 +379,7 @@ void RpcMethodTest::testAddMetalink()
   std::string dir = A2_TEST_OUT_DIR"/aria2_RpcMethodTest_testAddMetalink";
   File(dir).mkdirs();
   SharedHandle<Dict> opt = Dict::g();
-  opt->put(PREF_DIR, dir);
+  opt->put(PREF_DIR->k, dir);
   File(dir+"/c908634fbc257fd56f0114912c2772aeeb4064f4.meta4").remove();
   req.params->append(opt);
   {
@@ -446,11 +446,11 @@ void RpcMethodTest::testChangeOption()
   RpcRequest req(ChangeOptionRpcMethod::getMethodName(), List::g());
   req.params->append("1");
   SharedHandle<Dict> opt = Dict::g();
-  opt->put(PREF_MAX_DOWNLOAD_LIMIT, "100K");
+  opt->put(PREF_MAX_DOWNLOAD_LIMIT->k, "100K");
 #ifdef ENABLE_BITTORRENT
-  opt->put(PREF_BT_MAX_PEERS, "100");
-  opt->put(PREF_BT_REQUEST_PEER_SPEED_LIMIT, "300K");
-  opt->put(PREF_MAX_UPLOAD_LIMIT, "50K");
+  opt->put(PREF_BT_MAX_PEERS->k, "100");
+  opt->put(PREF_BT_REQUEST_PEER_SPEED_LIMIT->k, "300K");
+  opt->put(PREF_MAX_UPLOAD_LIMIT->k, "50K");
 
   BtObject btObject;
   btObject.btRuntime_ = SharedHandle<BtRuntime>(new BtRuntime());
@@ -489,7 +489,7 @@ void RpcMethodTest::testChangeOption_withBadOption()
   RpcRequest req(ChangeOptionRpcMethod::getMethodName(), List::g());
   req.params->append("1");
   SharedHandle<Dict> opt = Dict::g();
-  opt->put(PREF_MAX_DOWNLOAD_LIMIT, "badvalue");
+  opt->put(PREF_MAX_DOWNLOAD_LIMIT->k, "badvalue");
   req.params->append(opt);
   RpcResponse res = m.execute(req, e_.get());
   CPPUNIT_ASSERT_EQUAL(1, res.code);
@@ -504,7 +504,7 @@ void RpcMethodTest::testChangeOption_withNotAllowedOption()
   RpcRequest req(ChangeOptionRpcMethod::getMethodName(), List::g());
   req.params->append("1");
   SharedHandle<Dict> opt = Dict::g();
-  opt->put(PREF_MAX_OVERALL_DOWNLOAD_LIMIT, "100K");
+  opt->put(PREF_MAX_OVERALL_DOWNLOAD_LIMIT->k, "100K");
   req.params->append(opt);
   RpcResponse res = m.execute(req, e_.get());
   CPPUNIT_ASSERT_EQUAL(1, res.code);
@@ -524,9 +524,9 @@ void RpcMethodTest::testChangeGlobalOption()
   RpcRequest req
     (ChangeGlobalOptionRpcMethod::getMethodName(), List::g());
   SharedHandle<Dict> opt = Dict::g();
-  opt->put(PREF_MAX_OVERALL_DOWNLOAD_LIMIT, "100K");
+  opt->put(PREF_MAX_OVERALL_DOWNLOAD_LIMIT->k, "100K");
 #ifdef ENABLE_BITTORRENT
-  opt->put(PREF_MAX_OVERALL_UPLOAD_LIMIT, "50K");
+  opt->put(PREF_MAX_OVERALL_UPLOAD_LIMIT->k, "50K");
 #endif // ENABLE_BITTORRENT
   req.params->append(opt);
   RpcResponse res = m.execute(req, e_.get());
@@ -552,7 +552,7 @@ void RpcMethodTest::testChangeGlobalOption_withBadOption()
   RpcRequest req
     (ChangeGlobalOptionRpcMethod::getMethodName(), List::g());
   SharedHandle<Dict> opt = Dict::g();
-  opt->put(PREF_MAX_OVERALL_DOWNLOAD_LIMIT, "badvalue");
+  opt->put(PREF_MAX_OVERALL_DOWNLOAD_LIMIT->k, "badvalue");
   req.params->append(opt);
   RpcResponse res = m.execute(req, e_.get());
   CPPUNIT_ASSERT_EQUAL(1, res.code);
@@ -564,7 +564,7 @@ void RpcMethodTest::testChangeGlobalOption_withNotAllowedOption()
   RpcRequest req
     (ChangeGlobalOptionRpcMethod::getMethodName(), List::g());
   SharedHandle<Dict> opt = Dict::g();
-  opt->put(PREF_MAX_DOWNLOAD_LIMIT, "100K");
+  opt->put(PREF_MAX_DOWNLOAD_LIMIT->k, "100K");
   req.params->append(opt);
   RpcResponse res = m.execute(req, e_.get());
   CPPUNIT_ASSERT_EQUAL(1, res.code);

+ 2 - 2
test/UTMetadataPostDownloadHandlerTest.cc

@@ -107,8 +107,8 @@ void UTMetadataPostDownloadHandlerTest::testGetNextRequestGroups()
     newAttrs->announceList;
   CPPUNIT_ASSERT_EQUAL((size_t)1, newAnnounceList.size());
   CPPUNIT_ASSERT_EQUAL(std::string("http://tracker"), newAnnounceList[0][0]);
-  CPPUNIT_ASSERT_EQUAL(option_->get("Hello"),
-                       newRg->getOption()->get("Hello"));
+  CPPUNIT_ASSERT_EQUAL(option_->get(PREF_DIR),
+                       newRg->getOption()->get(PREF_DIR));
   CPPUNIT_ASSERT
     (std::find(requestGroup_->followedBy().begin(),
                requestGroup_->followedBy().end(),