Переглянути джерело

OptionHandler now knows its option can be used in -i list option,
changeable in aria2.changeOption or aria2.changeGlobalOption.

OptionHandler also now its option is cumulative.

Tatsuhiro Tsujikawa 14 роки тому
батько
коміт
5a29813d24

+ 5 - 1
src/NameMatchOptionHandler.cc

@@ -56,7 +56,11 @@ NameMatchOptionHandler::NameMatchOptionHandler
     argType_(argType),
     argType_(argType),
     shortName_(shortName),
     shortName_(shortName),
     hidden_(false),
     hidden_(false),
-    eraseAfterParse_(false)
+    eraseAfterParse_(false),
+    initialOption_(false),
+    changeOption_(false),
+    globalChangeOption_(false),
+    cumulative_(false)
 {}
 {}
 
 
 NameMatchOptionHandler::~NameMatchOptionHandler() {}
 NameMatchOptionHandler::~NameMatchOptionHandler() {}

+ 45 - 0
src/NameMatchOptionHandler.h

@@ -66,6 +66,11 @@ protected:
 
 
   bool eraseAfterParse_;
   bool eraseAfterParse_;
 
 
+  bool initialOption_;
+  bool changeOption_;
+  bool globalChangeOption_;
+  bool cumulative_;
+
   virtual void parseArg(Option& option, const std::string& arg) = 0;
   virtual void parseArg(Option& option, const std::string& arg) = 0;
 public:
 public:
   NameMatchOptionHandler(const Pref* pref,
   NameMatchOptionHandler(const Pref* pref,
@@ -142,6 +147,46 @@ public:
   {
   {
     eraseAfterParse_ = eraseAfterParse;
     eraseAfterParse_ = eraseAfterParse;
   }
   }
+
+  virtual bool getInitialOption() const
+  {
+    return initialOption_;
+  }
+
+  virtual void setInitialOption(bool f)
+  {
+    initialOption_ = f;
+  }
+
+  virtual bool getChangeOption() const
+  {
+    return changeOption_;
+  }
+
+  virtual void setChangeOption(bool f)
+  {
+    changeOption_ = f;
+  }
+
+  virtual bool getGlobalChangeOption() const
+  {
+    return globalChangeOption_;
+  }
+
+  virtual void setGlobalChangeOption(bool f)
+  {
+    globalChangeOption_ = f;
+  }
+
+  virtual bool getCumulative() const
+  {
+    return cumulative_;
+  }
+
+  virtual void setCumulative(bool f)
+  {
+    cumulative_ = f;
+  }
 };
 };
 
 
 typedef SharedHandle<NameMatchOptionHandler> NameMatchOptionHandlerHandle;
 typedef SharedHandle<NameMatchOptionHandler> NameMatchOptionHandlerHandle;

+ 11 - 0
src/Option.cc

@@ -142,4 +142,15 @@ void Option::clear()
   std::fill(table_.begin(), table_.end(), "");
   std::fill(table_.begin(), table_.end(), "");
 }
 }
 
 
+void Option::merge(const Option& option)
+{
+  size_t bits = option.use_.size()*8;
+  for(size_t i = 1, len = table_.size(); i < len; ++i) {
+    if(bitfield::test(option.use_, bits, i)) {
+      use_[i/8] |= 128 >> (i%8);
+      table_[i] = option.table_[i];
+    }
+  }
+}
+
 } // namespace aria2
 } // namespace aria2

+ 3 - 0
src/Option.h

@@ -75,6 +75,9 @@ public:
   {
   {
     return table_;
     return table_;
   }
   }
+
+  // Copy option values defined in option to this option.
+  void merge(const Option& option);
 };
 };
 
 
 } // namespace aria2
 } // namespace aria2

+ 9 - 0
src/OptionHandler.h

@@ -104,6 +104,15 @@ public:
   virtual bool getEraseAfterParse() const = 0;
   virtual bool getEraseAfterParse() const = 0;
 
 
   virtual void setEraseAfterParse(bool eraseAfterParse) = 0;
   virtual void setEraseAfterParse(bool eraseAfterParse) = 0;
+
+  virtual bool getInitialOption() const = 0;
+  virtual void setInitialOption(bool f) = 0;
+  virtual bool getChangeOption() const = 0;
+  virtual void setChangeOption(bool f) = 0;
+  virtual bool getGlobalChangeOption() const = 0;
+  virtual void setGlobalChangeOption(bool f) = 0;
+  virtual bool getCumulative() const = 0;
+  virtual void setCumulative(bool f) = 0;
 };
 };
 
 
 class OptionHandlerNameLesser:public std::binary_function
 class OptionHandlerNameLesser:public std::binary_function

+ 118 - 7
src/OptionHandlerFactory.cc

@@ -57,6 +57,7 @@ OptionHandlers OptionHandlerFactory::createOptionHandlers()
                                     OptionHandler::OPT_ARG));
                                     OptionHandler::OPT_ARG));
     op->addTag(TAG_ADVANCED);
     op->addTag(TAG_ADVANCED);
     op->addTag(TAG_FILE);
     op->addTag(TAG_FILE);
+    op->setInitialOption(true);
     handlers.push_back(op);
     handlers.push_back(op);
   }
   }
   {
   {
@@ -66,6 +67,7 @@ OptionHandlers OptionHandlerFactory::createOptionHandlers()
                                     A2_V_FALSE,
                                     A2_V_FALSE,
                                     OptionHandler::OPT_ARG));
                                     OptionHandler::OPT_ARG));
     op->addTag(TAG_ADVANCED);
     op->addTag(TAG_ADVANCED);
+    op->setInitialOption(true);
     handlers.push_back(op);
     handlers.push_back(op);
   }
   }
   {
   {
@@ -77,6 +79,7 @@ OptionHandlers OptionHandlerFactory::createOptionHandlers()
     op->addTag(TAG_ADVANCED);
     op->addTag(TAG_ADVANCED);
     op->addTag(TAG_FTP);
     op->addTag(TAG_FTP);
     op->addTag(TAG_HTTP);
     op->addTag(TAG_HTTP);
+    op->setInitialOption(true);
     handlers.push_back(op);
     handlers.push_back(op);
   }
   }
 #ifdef ENABLE_ASYNC_DNS
 #ifdef ENABLE_ASYNC_DNS
@@ -87,6 +90,7 @@ OptionHandlers OptionHandlerFactory::createOptionHandlers()
                                     A2_V_TRUE,
                                     A2_V_TRUE,
                                     OptionHandler::OPT_ARG));
                                     OptionHandler::OPT_ARG));
     op->addTag(TAG_ADVANCED);
     op->addTag(TAG_ADVANCED);
+    op->setInitialOption(true);
     handlers.push_back(op);
     handlers.push_back(op);
   }
   }
 #if defined HAVE_ARES_SET_SERVERS && HAVE_ARES_ADDR_NODE
 #if defined HAVE_ARES_SET_SERVERS && HAVE_ARES_ADDR_NODE
@@ -108,6 +112,7 @@ OptionHandlers OptionHandlerFactory::createOptionHandlers()
                                     OptionHandler::OPT_ARG));
                                     OptionHandler::OPT_ARG));
     op->addTag(TAG_ADVANCED);
     op->addTag(TAG_ADVANCED);
     op->addTag(TAG_FILE);
     op->addTag(TAG_FILE);
+    op->setInitialOption(true);
     handlers.push_back(op);
     handlers.push_back(op);
   }
   }
   {
   {
@@ -132,6 +137,7 @@ OptionHandlers OptionHandlerFactory::createOptionHandlers()
     op->addTag(TAG_METALINK);
     op->addTag(TAG_METALINK);
     op->addTag(TAG_FILE);
     op->addTag(TAG_FILE);
     op->addTag(TAG_CHECKSUM);
     op->addTag(TAG_CHECKSUM);
+    op->setInitialOption(true);
     handlers.push_back(op);
     handlers.push_back(op);
   }
   }
 #endif // ENABLE_MESSAGE_DIGEST
 #endif // ENABLE_MESSAGE_DIGEST
@@ -143,6 +149,7 @@ OptionHandlers OptionHandlerFactory::createOptionHandlers()
                                     OptionHandler::OPT_ARG));
                                     OptionHandler::OPT_ARG));
     op->addTag(TAG_ADVANCED);
     op->addTag(TAG_ADVANCED);
     op->addTag(TAG_HTTP);
     op->addTag(TAG_HTTP);
+    op->setInitialOption(true);
     handlers.push_back(op);
     handlers.push_back(op);
   }
   }
   {
   {
@@ -164,6 +171,7 @@ OptionHandlers OptionHandlerFactory::createOptionHandlers()
     op->addTag(TAG_BASIC);
     op->addTag(TAG_BASIC);
     op->addTag(TAG_FTP);
     op->addTag(TAG_FTP);
     op->addTag(TAG_HTTP);
     op->addTag(TAG_HTTP);
+    op->setInitialOption(true);
     handlers.push_back(op);
     handlers.push_back(op);
   }
   }
   {
   {
@@ -186,6 +194,7 @@ OptionHandlers OptionHandlerFactory::createOptionHandlers()
                                     'd'));
                                     'd'));
     op->addTag(TAG_BASIC);
     op->addTag(TAG_BASIC);
     op->addTag(TAG_FILE);
     op->addTag(TAG_FILE);
+    op->setInitialOption(true);
     handlers.push_back(op);
     handlers.push_back(op);
   }
   }
   {
   {
@@ -224,6 +233,7 @@ OptionHandlers OptionHandlerFactory::createOptionHandlers()
                                     A2_V_FALSE,
                                     A2_V_FALSE,
                                     OptionHandler::OPT_ARG));
                                     OptionHandler::OPT_ARG));
     op->addTag(TAG_ADVANCED);
     op->addTag(TAG_ADVANCED);
+    op->setInitialOption(true);
     handlers.push_back(op);
     handlers.push_back(op);
   }
   }
 #endif // ENABLE_ASYNC_DNS
 #endif // ENABLE_ASYNC_DNS
@@ -295,6 +305,7 @@ OptionHandlers OptionHandlerFactory::createOptionHandlers()
                                     'a'));
                                     'a'));
     op->addTag(TAG_BASIC);
     op->addTag(TAG_BASIC);
     op->addTag(TAG_FILE);
     op->addTag(TAG_FILE);
+    op->setInitialOption(true);
     handlers.push_back(op);
     handlers.push_back(op);
   }
   }
   {
   {
@@ -319,6 +330,7 @@ OptionHandlers OptionHandlerFactory::createOptionHandlers()
     op->addTag(TAG_METALINK);
     op->addTag(TAG_METALINK);
     op->addTag(TAG_FILE);
     op->addTag(TAG_FILE);
     op->addTag(TAG_CHECKSUM);
     op->addTag(TAG_CHECKSUM);
+    op->setInitialOption(true);
     handlers.push_back(op);
     handlers.push_back(op);
   }
   }
 #endif // ENABLE_MESSAGE_DIGEST
 #endif // ENABLE_MESSAGE_DIGEST
@@ -361,6 +373,7 @@ OptionHandlers OptionHandlerFactory::createOptionHandlers()
                                     OptionHandler::REQ_ARG,
                                     OptionHandler::REQ_ARG,
                                     'l'));
                                     'l'));
     op->addTag(TAG_BASIC);
     op->addTag(TAG_BASIC);
+    op->setGlobalChangeOption(true);
     handlers.push_back(op);
     handlers.push_back(op);
   }
   }
   {
   {
@@ -372,6 +385,7 @@ OptionHandlers OptionHandlerFactory::createOptionHandlers()
                                     std::vector<std::string>
                                     std::vector<std::string>
                                     (vbegin(params), vend(params))));
                                     (vbegin(params), vend(params))));
     op->addTag(TAG_ADVANCED);
     op->addTag(TAG_ADVANCED);
+    op->setGlobalChangeOption(true);
     handlers.push_back(op);
     handlers.push_back(op);
   }
   }
   {
   {
@@ -382,6 +396,7 @@ OptionHandlers OptionHandlerFactory::createOptionHandlers()
                                     1, -1,
                                     1, -1,
                                     'j'));
                                     'j'));
     op->addTag(TAG_BASIC);
     op->addTag(TAG_BASIC);
+    op->setGlobalChangeOption(true);
     handlers.push_back(op);
     handlers.push_back(op);
   }
   }
   {
   {
@@ -394,6 +409,7 @@ OptionHandlers OptionHandlerFactory::createOptionHandlers()
     op->addTag(TAG_BASIC);
     op->addTag(TAG_BASIC);
     op->addTag(TAG_FTP);
     op->addTag(TAG_FTP);
     op->addTag(TAG_HTTP);
     op->addTag(TAG_HTTP);
+    op->setInitialOption(true);
     handlers.push_back(op);
     handlers.push_back(op);
   }
   }
   {
   {
@@ -405,6 +421,8 @@ OptionHandlers OptionHandlerFactory::createOptionHandlers()
     op->addTag(TAG_BITTORRENT);
     op->addTag(TAG_BITTORRENT);
     op->addTag(TAG_FTP);
     op->addTag(TAG_FTP);
     op->addTag(TAG_HTTP);
     op->addTag(TAG_HTTP);
+    op->setInitialOption(true);
+    op->setChangeOption(true);
     handlers.push_back(op);
     handlers.push_back(op);
   }
   }
   {
   {
@@ -425,6 +443,7 @@ OptionHandlers OptionHandlerFactory::createOptionHandlers()
     op->addTag(TAG_BITTORRENT);
     op->addTag(TAG_BITTORRENT);
     op->addTag(TAG_FTP);
     op->addTag(TAG_FTP);
     op->addTag(TAG_HTTP);
     op->addTag(TAG_HTTP);
+    op->setGlobalChangeOption(true);
     handlers.push_back(op);
     handlers.push_back(op);
   }
   }
   {
   {
@@ -436,7 +455,8 @@ OptionHandlers OptionHandlerFactory::createOptionHandlers()
     op->addTag(TAG_ADVANCED);
     op->addTag(TAG_ADVANCED);
     op->addTag(TAG_FTP);
     op->addTag(TAG_FTP);
     op->addTag(TAG_HTTP);
     op->addTag(TAG_HTTP);
-    handlers.push_back(op);    
+    op->setInitialOption(true);
+    handlers.push_back(op);
   }
   }
   {
   {
     SharedHandle<OptionHandler> op(new UnitNumberOptionHandler
     SharedHandle<OptionHandler> op(new UnitNumberOptionHandler
@@ -448,7 +468,8 @@ OptionHandlers OptionHandlerFactory::createOptionHandlers()
     op->addTag(TAG_BASIC);
     op->addTag(TAG_BASIC);
     op->addTag(TAG_FTP);
     op->addTag(TAG_FTP);
     op->addTag(TAG_HTTP);
     op->addTag(TAG_HTTP);
-    handlers.push_back(op);    
+    op->setInitialOption(true);
+    handlers.push_back(op);
   }
   }
   {
   {
     SharedHandle<OptionHandler> op(new BooleanOptionHandler
     SharedHandle<OptionHandler> op(new BooleanOptionHandler
@@ -467,6 +488,7 @@ OptionHandlers OptionHandlerFactory::createOptionHandlers()
                                     0));
                                     0));
     op->addTag(TAG_ADVANCED);
     op->addTag(TAG_ADVANCED);
     op->addTag(TAG_FILE);
     op->addTag(TAG_FILE);
+    op->setInitialOption(true);
     handlers.push_back(op);
     handlers.push_back(op);
   }
   }
   {
   {
@@ -525,8 +547,9 @@ OptionHandlers OptionHandlerFactory::createOptionHandlers()
                                     TEXT_PARAMETERIZED_URI,
                                     TEXT_PARAMETERIZED_URI,
                                     A2_V_FALSE,
                                     A2_V_FALSE,
                                     OptionHandler::OPT_ARG,
                                     OptionHandler::OPT_ARG,
-                                    'P'));  
+                                    'P'));
     op->addTag(TAG_ADVANCED);
     op->addTag(TAG_ADVANCED);
+    op->setInitialOption(true);
     handlers.push_back(op);
     handlers.push_back(op);
   }
   }
   {
   {
@@ -537,6 +560,7 @@ OptionHandlers OptionHandlerFactory::createOptionHandlers()
                                     OptionHandler::OPT_ARG));
                                     OptionHandler::OPT_ARG));
     op->addTag(TAG_ADVANCED);
     op->addTag(TAG_ADVANCED);
     op->addTag(TAG_RPC);
     op->addTag(TAG_RPC);
+    op->setInitialOption(true);
     handlers.push_back(op);
     handlers.push_back(op);
   }
   }
   {
   {
@@ -558,6 +582,7 @@ OptionHandlers OptionHandlerFactory::createOptionHandlers()
                                     OptionHandler::OPT_ARG));
                                     OptionHandler::OPT_ARG));
     op->addTag(TAG_METALINK);
     op->addTag(TAG_METALINK);
     op->addTag(TAG_CHECKSUM);
     op->addTag(TAG_CHECKSUM);
+    op->setInitialOption(true);
     handlers.push_back(op);
     handlers.push_back(op);
   }
   }
 #endif // ENABLE_MESSAGE_DIGEST
 #endif // ENABLE_MESSAGE_DIGEST
@@ -568,6 +593,7 @@ OptionHandlers OptionHandlerFactory::createOptionHandlers()
                                     A2_V_FALSE,
                                     A2_V_FALSE,
                                     OptionHandler::OPT_ARG));
                                     OptionHandler::OPT_ARG));
     op->addTag(TAG_ADVANCED);
     op->addTag(TAG_ADVANCED);
+    op->setInitialOption(true);
     handlers.push_back(op);
     handlers.push_back(op);
   }
   }
   {
   {
@@ -657,7 +683,7 @@ OptionHandlers OptionHandlerFactory::createOptionHandlers()
                                     0));
                                     0));
     op->addTag(TAG_RPC);
     op->addTag(TAG_RPC);
     handlers.push_back(op);
     handlers.push_back(op);
-  }                         
+  }
   {
   {
     SharedHandle<OptionHandler> op(new DefaultOptionHandler
     SharedHandle<OptionHandler> op(new DefaultOptionHandler
                                    (PREF_RPC_USER,
                                    (PREF_RPC_USER,
@@ -683,6 +709,7 @@ OptionHandlers OptionHandlerFactory::createOptionHandlers()
     op->addTag(TAG_FTP);
     op->addTag(TAG_FTP);
     op->addTag(TAG_HTTP);
     op->addTag(TAG_HTTP);
     op->addTag(TAG_CHECKSUM);
     op->addTag(TAG_CHECKSUM);
+    op->setInitialOption(true);
     handlers.push_back(op);
     handlers.push_back(op);
   }
   }
 #endif // ENABLE_MESSAGE_DIGEST
 #endif // ENABLE_MESSAGE_DIGEST
@@ -694,6 +721,7 @@ OptionHandlers OptionHandlerFactory::createOptionHandlers()
                                     1, 600));
                                     1, 600));
     op->addTag(TAG_FTP);
     op->addTag(TAG_FTP);
     op->addTag(TAG_HTTP);
     op->addTag(TAG_HTTP);
+    op->setInitialOption(true);
     handlers.push_back(op);
     handlers.push_back(op);
   }
   }
   {
   {
@@ -704,6 +732,7 @@ OptionHandlers OptionHandlerFactory::createOptionHandlers()
                                     OptionHandler::OPT_ARG));
                                     OptionHandler::OPT_ARG));
     op->addTag(TAG_FTP);
     op->addTag(TAG_FTP);
     op->addTag(TAG_HTTP);
     op->addTag(TAG_HTTP);
+    op->setInitialOption(true);
     handlers.push_back(op);
     handlers.push_back(op);
   }
   }
   {
   {
@@ -714,6 +743,7 @@ OptionHandlers OptionHandlerFactory::createOptionHandlers()
                                     0));
                                     0));
     op->addTag(TAG_FTP);
     op->addTag(TAG_FTP);
     op->addTag(TAG_HTTP);
     op->addTag(TAG_HTTP);
+    op->setInitialOption(true);
     handlers.push_back(op);
     handlers.push_back(op);
   }
   }
   {
   {
@@ -724,6 +754,7 @@ OptionHandlers OptionHandlerFactory::createOptionHandlers()
                                     0));
                                     0));
     op->addTag(TAG_FTP);
     op->addTag(TAG_FTP);
     op->addTag(TAG_HTTP);
     op->addTag(TAG_HTTP);
+    op->setInitialOption(true);
     handlers.push_back(op);
     handlers.push_back(op);
   }
   }
   {
   {
@@ -735,6 +766,7 @@ OptionHandlers OptionHandlerFactory::createOptionHandlers()
                                     'm'));
                                     'm'));
     op->addTag(TAG_FTP);
     op->addTag(TAG_FTP);
     op->addTag(TAG_HTTP);
     op->addTag(TAG_HTTP);
+    op->setInitialOption(true);
     handlers.push_back(op);
     handlers.push_back(op);
   }
   }
   {
   {
@@ -746,6 +778,7 @@ OptionHandlers OptionHandlerFactory::createOptionHandlers()
                                     'n'));
                                     'n'));
     op->addTag(TAG_FTP);
     op->addTag(TAG_FTP);
     op->addTag(TAG_HTTP);
     op->addTag(TAG_HTTP);
+    op->setInitialOption(true);
     handlers.push_back(op);
     handlers.push_back(op);
   }
   }
   {
   {
@@ -760,6 +793,7 @@ OptionHandlers OptionHandlerFactory::createOptionHandlers()
     op->addTag(TAG_FTP);
     op->addTag(TAG_FTP);
     op->addTag(TAG_HTTP);
     op->addTag(TAG_HTTP);
     op->addTag(TAG_FILE);
     op->addTag(TAG_FILE);
+    op->setInitialOption(true);
     handlers.push_back(op);
     handlers.push_back(op);
   }
   }
   {
   {
@@ -772,6 +806,7 @@ OptionHandlers OptionHandlerFactory::createOptionHandlers()
     op->addTag(TAG_ADVANCED);
     op->addTag(TAG_ADVANCED);
     op->addTag(TAG_FTP);
     op->addTag(TAG_FTP);
     op->addTag(TAG_HTTP);
     op->addTag(TAG_HTTP);
+    op->setInitialOption(true);
     handlers.push_back(op);
     handlers.push_back(op);
   }
   }
   {
   {
@@ -783,6 +818,7 @@ OptionHandlers OptionHandlerFactory::createOptionHandlers()
                                     'R'));
                                     'R'));
     op->addTag(TAG_FTP);
     op->addTag(TAG_FTP);
     op->addTag(TAG_HTTP);
     op->addTag(TAG_HTTP);
+    op->setInitialOption(true);
     handlers.push_back(op);
     handlers.push_back(op);
   }
   }
   {
   {
@@ -793,6 +829,7 @@ OptionHandlers OptionHandlerFactory::createOptionHandlers()
                                     0, 600));
                                     0, 600));
     op->addTag(TAG_FTP);
     op->addTag(TAG_FTP);
     op->addTag(TAG_HTTP);
     op->addTag(TAG_HTTP);
+    op->setInitialOption(true);
     handlers.push_back(op);
     handlers.push_back(op);
   }
   }
   {
   {
@@ -803,6 +840,7 @@ OptionHandlers OptionHandlerFactory::createOptionHandlers()
                                     OptionHandler::OPT_ARG));
                                     OptionHandler::OPT_ARG));
     op->addTag(TAG_FTP);
     op->addTag(TAG_FTP);
     op->addTag(TAG_HTTP);
     op->addTag(TAG_HTTP);
+    op->setInitialOption(true);
     handlers.push_back(op);
     handlers.push_back(op);
   }
   }
   {
   {
@@ -845,6 +883,7 @@ OptionHandlers OptionHandlerFactory::createOptionHandlers()
     op->addTag(TAG_BASIC);
     op->addTag(TAG_BASIC);
     op->addTag(TAG_FTP);
     op->addTag(TAG_FTP);
     op->addTag(TAG_HTTP);
     op->addTag(TAG_HTTP);
+    op->setInitialOption(true);
     handlers.push_back(op);
     handlers.push_back(op);
   }
   }
   {
   {
@@ -866,6 +905,7 @@ OptionHandlers OptionHandlerFactory::createOptionHandlers()
                                     A2_V_GEOM));
                                     A2_V_GEOM));
     op->addTag(TAG_FTP);
     op->addTag(TAG_FTP);
     op->addTag(TAG_HTTP);
     op->addTag(TAG_HTTP);
+    op->setInitialOption(true);
     handlers.push_back(op);
     handlers.push_back(op);
   }
   }
   {
   {
@@ -877,6 +917,7 @@ OptionHandlers OptionHandlerFactory::createOptionHandlers()
                                     't'));
                                     't'));
     op->addTag(TAG_FTP);
     op->addTag(TAG_FTP);
     op->addTag(TAG_HTTP);
     op->addTag(TAG_HTTP);
+    op->setInitialOption(true);
     handlers.push_back(op);
     handlers.push_back(op);
   }
   }
   {
   {
@@ -929,6 +970,7 @@ OptionHandlers OptionHandlerFactory::createOptionHandlers()
                                     A2_V_TRUE,
                                     A2_V_TRUE,
                                     OptionHandler::OPT_ARG));
                                     OptionHandler::OPT_ARG));
     op->addTag(TAG_HTTP);
     op->addTag(TAG_HTTP);
+    op->setInitialOption(true);
     handlers.push_back(op);
     handlers.push_back(op);
   }
   }
   {
   {
@@ -938,6 +980,7 @@ OptionHandlers OptionHandlerFactory::createOptionHandlers()
                                     A2_V_FALSE,
                                     A2_V_FALSE,
                                     OptionHandler::OPT_ARG));
                                     OptionHandler::OPT_ARG));
     op->addTag(TAG_HTTP);
     op->addTag(TAG_HTTP);
+    op->setInitialOption(true);
     handlers.push_back(op);
     handlers.push_back(op);
   }
   }
   {
   {
@@ -947,6 +990,8 @@ OptionHandlers OptionHandlerFactory::createOptionHandlers()
                                     NO_DEFAULT_VALUE,
                                     NO_DEFAULT_VALUE,
                                     "\n"));
                                     "\n"));
     op->addTag(TAG_HTTP);
     op->addTag(TAG_HTTP);
+    op->setInitialOption(true);
+    op->setCumulative(true);
     handlers.push_back(op);
     handlers.push_back(op);
   }
   }
   {
   {
@@ -956,6 +1001,7 @@ OptionHandlers OptionHandlerFactory::createOptionHandlers()
                                     A2_V_FALSE,
                                     A2_V_FALSE,
                                     OptionHandler::OPT_ARG));
                                     OptionHandler::OPT_ARG));
     op->addTag(TAG_HTTP);
     op->addTag(TAG_HTTP);
+    op->setInitialOption(true);
     handlers.push_back(op);
     handlers.push_back(op);
   }
   }
   {
   {
@@ -965,6 +1011,7 @@ OptionHandlers OptionHandlerFactory::createOptionHandlers()
                                     A2_V_FALSE,
                                     A2_V_FALSE,
                                     OptionHandler::OPT_ARG));
                                     OptionHandler::OPT_ARG));
     op->addTag(TAG_HTTP);
     op->addTag(TAG_HTTP);
+    op->setInitialOption(true);
     handlers.push_back(op);
     handlers.push_back(op);
   }
   }
   {
   {
@@ -974,6 +1021,7 @@ OptionHandlers OptionHandlerFactory::createOptionHandlers()
                                     A2_V_TRUE,
                                     A2_V_TRUE,
                                     OptionHandler::OPT_ARG));
                                     OptionHandler::OPT_ARG));
     op->addTag(TAG_HTTP);
     op->addTag(TAG_HTTP);
+    op->setInitialOption(true);
     handlers.push_back(op);
     handlers.push_back(op);
   }
   }
   {
   {
@@ -983,6 +1031,7 @@ OptionHandlers OptionHandlerFactory::createOptionHandlers()
     op->addTag(TAG_BASIC);
     op->addTag(TAG_BASIC);
     op->addTag(TAG_HTTP);
     op->addTag(TAG_HTTP);
     op->setEraseAfterParse(true);
     op->setEraseAfterParse(true);
+    op->setInitialOption(true);
     handlers.push_back(op);
     handlers.push_back(op);
   }
   }
   {
   {
@@ -992,6 +1041,7 @@ OptionHandlers OptionHandlerFactory::createOptionHandlers()
     op->addTag(TAG_BASIC);
     op->addTag(TAG_BASIC);
     op->addTag(TAG_HTTP);
     op->addTag(TAG_HTTP);
     op->setEraseAfterParse(true);
     op->setEraseAfterParse(true);
+    op->setInitialOption(true);
     handlers.push_back(op);
     handlers.push_back(op);
   }
   }
   {
   {
@@ -1019,6 +1069,7 @@ OptionHandlers OptionHandlerFactory::createOptionHandlers()
                                    (PREF_METALINK_LOCATION,
                                    (PREF_METALINK_LOCATION,
                                     TEXT_METALINK_LOCATION));
                                     TEXT_METALINK_LOCATION));
     op->addTag(TAG_METALINK);
     op->addTag(TAG_METALINK);
+    op->setInitialOption(true);
     handlers.push_back(op);
     handlers.push_back(op);
   }
   }
   {
   {
@@ -1036,6 +1087,7 @@ OptionHandlers OptionHandlerFactory::createOptionHandlers()
                                    (PREF_REFERER,
                                    (PREF_REFERER,
                                     TEXT_REFERER));
                                     TEXT_REFERER));
     op->addTag(TAG_HTTP);
     op->addTag(TAG_HTTP);
+    op->setInitialOption(true);
     handlers.push_back(op);
     handlers.push_back(op);
   }
   }
   {
   {
@@ -1055,6 +1107,7 @@ OptionHandlers OptionHandlerFactory::createOptionHandlers()
                                     A2_V_FALSE,
                                     A2_V_FALSE,
                                     OptionHandler::OPT_ARG));
                                     OptionHandler::OPT_ARG));
     op->addTag(TAG_HTTP);
     op->addTag(TAG_HTTP);
+    op->setInitialOption(true);
     handlers.push_back(op);
     handlers.push_back(op);
   }
   }
   {
   {
@@ -1066,6 +1119,7 @@ OptionHandlers OptionHandlerFactory::createOptionHandlers()
                                     OptionHandler::REQ_ARG,
                                     OptionHandler::REQ_ARG,
                                     'U'));
                                     'U'));
     op->addTag(TAG_HTTP);
     op->addTag(TAG_HTTP);
+    op->setInitialOption(true);
     handlers.push_back(op);
     handlers.push_back(op);
   }
   }
   // FTP Specific Options
   // FTP Specific Options
@@ -1076,8 +1130,9 @@ OptionHandlers OptionHandlerFactory::createOptionHandlers()
     op->addTag(TAG_BASIC);
     op->addTag(TAG_BASIC);
     op->addTag(TAG_FTP);
     op->addTag(TAG_FTP);
     op->setEraseAfterParse(true);
     op->setEraseAfterParse(true);
+    op->setInitialOption(true);
     handlers.push_back(op);
     handlers.push_back(op);
-  }    
+  }
   {
   {
     SharedHandle<OptionHandler> op(new BooleanOptionHandler
     SharedHandle<OptionHandler> op(new BooleanOptionHandler
                                    (PREF_FTP_PASV,
                                    (PREF_FTP_PASV,
@@ -1086,6 +1141,7 @@ OptionHandlers OptionHandlerFactory::createOptionHandlers()
                                     OptionHandler::OPT_ARG,
                                     OptionHandler::OPT_ARG,
                                     'p'));
                                     'p'));
     op->addTag(TAG_FTP);
     op->addTag(TAG_FTP);
+    op->setInitialOption(true);
     handlers.push_back(op);
     handlers.push_back(op);
   }
   }
   {
   {
@@ -1095,6 +1151,7 @@ OptionHandlers OptionHandlerFactory::createOptionHandlers()
                                     A2_V_TRUE,
                                     A2_V_TRUE,
                                     OptionHandler::OPT_ARG));
                                     OptionHandler::OPT_ARG));
     op->addTag(TAG_FTP);
     op->addTag(TAG_FTP);
+    op->setInitialOption(true);
     handlers.push_back(op);
     handlers.push_back(op);
   }
   }
   {
   {
@@ -1104,6 +1161,7 @@ OptionHandlers OptionHandlerFactory::createOptionHandlers()
                                     V_BINARY,
                                     V_BINARY,
                                     V_BINARY, V_ASCII));
                                     V_BINARY, V_ASCII));
     op->addTag(TAG_FTP);
     op->addTag(TAG_FTP);
+    op->setInitialOption(true);
     handlers.push_back(op);
     handlers.push_back(op);
   }
   }
   {
   {
@@ -1113,6 +1171,7 @@ OptionHandlers OptionHandlerFactory::createOptionHandlers()
     op->addTag(TAG_BASIC);
     op->addTag(TAG_BASIC);
     op->addTag(TAG_FTP);
     op->addTag(TAG_FTP);
     op->setEraseAfterParse(true);
     op->setEraseAfterParse(true);
+    op->setInitialOption(true);
     handlers.push_back(op);
     handlers.push_back(op);
   }
   }
   {
   {
@@ -1131,6 +1190,7 @@ OptionHandlers OptionHandlerFactory::createOptionHandlers()
                                     TEXT_HTTP_PROXY,
                                     TEXT_HTTP_PROXY,
                                     NO_DEFAULT_VALUE));
                                     NO_DEFAULT_VALUE));
     op->addTag(TAG_HTTP);
     op->addTag(TAG_HTTP);
+    op->setInitialOption(true);
     handlers.push_back(op);
     handlers.push_back(op);
   }
   }
   {
   {
@@ -1140,6 +1200,7 @@ OptionHandlers OptionHandlerFactory::createOptionHandlers()
                                     NO_DEFAULT_VALUE));
                                     NO_DEFAULT_VALUE));
     op->addTag(TAG_HTTP);
     op->addTag(TAG_HTTP);
     op->setEraseAfterParse(true);
     op->setEraseAfterParse(true);
+    op->setInitialOption(true);
     handlers.push_back(op);
     handlers.push_back(op);
   }
   }
   {
   {
@@ -1149,6 +1210,7 @@ OptionHandlers OptionHandlerFactory::createOptionHandlers()
                                     NO_DEFAULT_VALUE));
                                     NO_DEFAULT_VALUE));
     op->addTag(TAG_HTTP);
     op->addTag(TAG_HTTP);
     op->setEraseAfterParse(true);
     op->setEraseAfterParse(true);
+    op->setInitialOption(true);
     handlers.push_back(op);
     handlers.push_back(op);
   }
   }
   {
   {
@@ -1158,6 +1220,7 @@ OptionHandlers OptionHandlerFactory::createOptionHandlers()
                                     NO_DEFAULT_VALUE));
                                     NO_DEFAULT_VALUE));
     op->addTag(TAG_HTTP);
     op->addTag(TAG_HTTP);
     op->addTag(TAG_HTTPS);
     op->addTag(TAG_HTTPS);
+    op->setInitialOption(true);
     handlers.push_back(op);
     handlers.push_back(op);
   }
   }
   {
   {
@@ -1168,6 +1231,7 @@ OptionHandlers OptionHandlerFactory::createOptionHandlers()
     op->addTag(TAG_HTTP);
     op->addTag(TAG_HTTP);
     op->addTag(TAG_HTTPS);
     op->addTag(TAG_HTTPS);
     op->setEraseAfterParse(true);
     op->setEraseAfterParse(true);
+    op->setInitialOption(true);
     handlers.push_back(op);
     handlers.push_back(op);
   }
   }
   {
   {
@@ -1178,6 +1242,7 @@ OptionHandlers OptionHandlerFactory::createOptionHandlers()
     op->addTag(TAG_HTTP);
     op->addTag(TAG_HTTP);
     op->addTag(TAG_HTTPS);
     op->addTag(TAG_HTTPS);
     op->setEraseAfterParse(true);
     op->setEraseAfterParse(true);
+    op->setInitialOption(true);
     handlers.push_back(op);
     handlers.push_back(op);
   }
   }
   {
   {
@@ -1186,6 +1251,7 @@ OptionHandlers OptionHandlerFactory::createOptionHandlers()
                                     TEXT_FTP_PROXY,
                                     TEXT_FTP_PROXY,
                                     NO_DEFAULT_VALUE));
                                     NO_DEFAULT_VALUE));
     op->addTag(TAG_FTP);
     op->addTag(TAG_FTP);
+    op->setInitialOption(true);
     handlers.push_back(op);
     handlers.push_back(op);
   }
   }
   {
   {
@@ -1195,6 +1261,7 @@ OptionHandlers OptionHandlerFactory::createOptionHandlers()
                                     NO_DEFAULT_VALUE));
                                     NO_DEFAULT_VALUE));
     op->addTag(TAG_FTP);
     op->addTag(TAG_FTP);
     op->setEraseAfterParse(true);
     op->setEraseAfterParse(true);
+    op->setInitialOption(true);
     handlers.push_back(op);
     handlers.push_back(op);
   }
   }
   {
   {
@@ -1204,6 +1271,7 @@ OptionHandlers OptionHandlerFactory::createOptionHandlers()
                                     NO_DEFAULT_VALUE));
                                     NO_DEFAULT_VALUE));
     op->addTag(TAG_FTP);
     op->addTag(TAG_FTP);
     op->setEraseAfterParse(true);
     op->setEraseAfterParse(true);
+    op->setInitialOption(true);
     handlers.push_back(op);
     handlers.push_back(op);
   }
   }
   {
   {
@@ -1214,6 +1282,7 @@ OptionHandlers OptionHandlerFactory::createOptionHandlers()
     op->addTag(TAG_FTP);
     op->addTag(TAG_FTP);
     op->addTag(TAG_HTTP);
     op->addTag(TAG_HTTP);
     op->addTag(TAG_HTTPS);
     op->addTag(TAG_HTTPS);
+    op->setInitialOption(true);
     handlers.push_back(op);
     handlers.push_back(op);
   }
   }
   {
   {
@@ -1225,6 +1294,7 @@ OptionHandlers OptionHandlerFactory::createOptionHandlers()
     op->addTag(TAG_HTTP);
     op->addTag(TAG_HTTP);
     op->addTag(TAG_HTTPS);
     op->addTag(TAG_HTTPS);
     op->setEraseAfterParse(true);
     op->setEraseAfterParse(true);
+    op->setInitialOption(true);
     handlers.push_back(op);
     handlers.push_back(op);
   }
   }
   {
   {
@@ -1236,6 +1306,7 @@ OptionHandlers OptionHandlerFactory::createOptionHandlers()
     op->addTag(TAG_HTTP);
     op->addTag(TAG_HTTP);
     op->addTag(TAG_HTTPS);
     op->addTag(TAG_HTTPS);
     op->setEraseAfterParse(true);
     op->setEraseAfterParse(true);
+    op->setInitialOption(true);
     handlers.push_back(op);
     handlers.push_back(op);
   }
   }
   {
   {
@@ -1247,6 +1318,7 @@ OptionHandlers OptionHandlerFactory::createOptionHandlers()
     op->addTag(TAG_FTP);
     op->addTag(TAG_FTP);
     op->addTag(TAG_HTTP);
     op->addTag(TAG_HTTP);
     op->addTag(TAG_HTTPS);
     op->addTag(TAG_HTTPS);
+    op->setInitialOption(true);
     handlers.push_back(op);
     handlers.push_back(op);
   }
   }
   {
   {
@@ -1257,6 +1329,7 @@ OptionHandlers OptionHandlerFactory::createOptionHandlers()
                                     V_GET, V_TUNNEL));
                                     V_GET, V_TUNNEL));
     op->addTag(TAG_FTP);
     op->addTag(TAG_FTP);
     op->addTag(TAG_HTTP);
     op->addTag(TAG_HTTP);
+    op->setInitialOption(true);
     handlers.push_back(op);
     handlers.push_back(op);
   }
   }
   // BitTorrent/Metalink Options
   // BitTorrent/Metalink Options
@@ -1269,6 +1342,7 @@ OptionHandlers OptionHandlerFactory::createOptionHandlers()
                                     1, INT32_MAX));
                                     1, INT32_MAX));
     op->addTag(TAG_BITTORRENT);
     op->addTag(TAG_BITTORRENT);
     op->addTag(TAG_METALINK);
     op->addTag(TAG_METALINK);
+    op->setInitialOption(true);
     handlers.push_back(op);
     handlers.push_back(op);
   }
   }
   {
   {
@@ -1293,6 +1367,7 @@ OptionHandlers OptionHandlerFactory::createOptionHandlers()
                                     A2_V_FALSE,
                                     A2_V_FALSE,
                                     OptionHandler::OPT_ARG));
                                     OptionHandler::OPT_ARG));
     op->addTag(TAG_BITTORRENT);
     op->addTag(TAG_BITTORRENT);
+    op->setInitialOption(true);
     handlers.push_back(op);
     handlers.push_back(op);
   }
   }
   {
   {
@@ -1303,6 +1378,7 @@ OptionHandlers OptionHandlerFactory::createOptionHandlers()
                                            "URI,... "
                                            "URI,... "
                                            "or *"));
                                            "or *"));
     op->addTag(TAG_BITTORRENT);
     op->addTag(TAG_BITTORRENT);
+    op->setInitialOption(true);
     handlers.push_back(op);
     handlers.push_back(op);
   }
   }
   {
   {
@@ -1312,6 +1388,7 @@ OptionHandlers OptionHandlerFactory::createOptionHandlers()
                                     NO_DEFAULT_VALUE,
                                     NO_DEFAULT_VALUE,
                                     "a numeric IP address"));
                                     "a numeric IP address"));
     op->addTag(TAG_BITTORRENT);
     op->addTag(TAG_BITTORRENT);
+    op->setInitialOption(true);
     handlers.push_back(op);
     handlers.push_back(op);
   }
   }
   {
   {
@@ -1331,6 +1408,7 @@ OptionHandlers OptionHandlerFactory::createOptionHandlers()
                                     OptionHandler::OPT_ARG));
                                     OptionHandler::OPT_ARG));
     op->addTag(TAG_BITTORRENT);
     op->addTag(TAG_BITTORRENT);
     op->addTag(TAG_CHECKSUM);
     op->addTag(TAG_CHECKSUM);
+    op->setInitialOption(true);
     handlers.push_back(op);
     handlers.push_back(op);
   }
   }
   {
   {
@@ -1350,6 +1428,7 @@ OptionHandlers OptionHandlerFactory::createOptionHandlers()
                                     "100",
                                     "100",
                                     1));
                                     1));
     op->addTag(TAG_BITTORRENT);
     op->addTag(TAG_BITTORRENT);
+    op->setInitialOption(true);
     handlers.push_back(op);
     handlers.push_back(op);
   }
   }
   {
   {
@@ -1359,8 +1438,10 @@ OptionHandlers OptionHandlerFactory::createOptionHandlers()
                                     "55",
                                     "55",
                                     0));
                                     0));
     op->addTag(TAG_BITTORRENT);
     op->addTag(TAG_BITTORRENT);
+    op->setInitialOption(true);
+    op->setChangeOption(true);
     handlers.push_back(op);
     handlers.push_back(op);
-                                   
+
   }
   }
   {
   {
     SharedHandle<OptionHandler> op(new BooleanOptionHandler
     SharedHandle<OptionHandler> op(new BooleanOptionHandler
@@ -1369,6 +1450,7 @@ OptionHandlers OptionHandlerFactory::createOptionHandlers()
                                     A2_V_FALSE,
                                     A2_V_FALSE,
                                     OptionHandler::OPT_ARG));
                                     OptionHandler::OPT_ARG));
     op->addTag(TAG_BITTORRENT);
     op->addTag(TAG_BITTORRENT);
+    op->setInitialOption(true);
     handlers.push_back(op);
     handlers.push_back(op);
   }
   }
   {
   {
@@ -1378,6 +1460,7 @@ OptionHandlers OptionHandlerFactory::createOptionHandlers()
                                     V_PLAIN,
                                     V_PLAIN,
                                     V_PLAIN, V_ARC4));
                                     V_PLAIN, V_ARC4));
     op->addTag(TAG_BITTORRENT);
     op->addTag(TAG_BITTORRENT);
+    op->setInitialOption(true);
     handlers.push_back(op);
     handlers.push_back(op);
   }
   }
   {
   {
@@ -1385,6 +1468,7 @@ OptionHandlers OptionHandlerFactory::createOptionHandlers()
                                    (PREF_BT_PRIORITIZE_PIECE,
                                    (PREF_BT_PRIORITIZE_PIECE,
                                     TEXT_BT_PRIORITIZE_PIECE));
                                     TEXT_BT_PRIORITIZE_PIECE));
     op->addTag(TAG_BITTORRENT);
     op->addTag(TAG_BITTORRENT);
+    op->setInitialOption(true);
     handlers.push_back(op);
     handlers.push_back(op);
   }
   }
   {
   {
@@ -1394,6 +1478,8 @@ OptionHandlers OptionHandlerFactory::createOptionHandlers()
                                     "50K",
                                     "50K",
                                     0));
                                     0));
     op->addTag(TAG_BITTORRENT);
     op->addTag(TAG_BITTORRENT);
+    op->setInitialOption(true);
+    op->setChangeOption(true);
     handlers.push_back(op);
     handlers.push_back(op);
   }
   }
   {
   {
@@ -1403,6 +1489,7 @@ OptionHandlers OptionHandlerFactory::createOptionHandlers()
                                     A2_V_FALSE,
                                     A2_V_FALSE,
                                     OptionHandler::OPT_ARG));
                                     OptionHandler::OPT_ARG));
     op->addTag(TAG_BITTORRENT);
     op->addTag(TAG_BITTORRENT);
+    op->setInitialOption(true);
     handlers.push_back(op);
     handlers.push_back(op);
   }
   }
   {
   {
@@ -1421,6 +1508,7 @@ OptionHandlers OptionHandlerFactory::createOptionHandlers()
                                     A2_V_FALSE,
                                     A2_V_FALSE,
                                     OptionHandler::OPT_ARG));
                                     OptionHandler::OPT_ARG));
     op->addTag(TAG_BITTORRENT);
     op->addTag(TAG_BITTORRENT);
+    op->setInitialOption(true);
     handlers.push_back(op);
     handlers.push_back(op);
   }
   }
   {
   {
@@ -1430,6 +1518,7 @@ OptionHandlers OptionHandlerFactory::createOptionHandlers()
                                     A2_V_FALSE,
                                     A2_V_FALSE,
                                     OptionHandler::OPT_ARG));
                                     OptionHandler::OPT_ARG));
     op->addTag(TAG_BITTORRENT);
     op->addTag(TAG_BITTORRENT);
+    op->setInitialOption(true);
     handlers.push_back(op);
     handlers.push_back(op);
   }
   }
   {
   {
@@ -1439,6 +1528,7 @@ OptionHandlers OptionHandlerFactory::createOptionHandlers()
                                     "0",
                                     "0",
                                     0));
                                     0));
     op->addTag(TAG_BITTORRENT);
     op->addTag(TAG_BITTORRENT);
+    op->setInitialOption(true);
     handlers.push_back(op);
     handlers.push_back(op);
   }
   }
   {
   {
@@ -1457,6 +1547,7 @@ OptionHandlers OptionHandlerFactory::createOptionHandlers()
                                            NO_DESCRIPTION,
                                            NO_DESCRIPTION,
                                            "URI,..."));
                                            "URI,..."));
     op->addTag(TAG_BITTORRENT);
     op->addTag(TAG_BITTORRENT);
+    op->setInitialOption(true);
     handlers.push_back(op);
     handlers.push_back(op);
   }
   }
   {
   {
@@ -1466,6 +1557,7 @@ OptionHandlers OptionHandlerFactory::createOptionHandlers()
                                           "60",
                                           "60",
                                           1, 600));
                                           1, 600));
     op->addTag(TAG_BITTORRENT);
     op->addTag(TAG_BITTORRENT);
+    op->setInitialOption(true);
     handlers.push_back(op);
     handlers.push_back(op);
   }
   }
   {
   {
@@ -1475,6 +1567,7 @@ OptionHandlers OptionHandlerFactory::createOptionHandlers()
                                           "0",
                                           "0",
                                           0));
                                           0));
     op->addTag(TAG_BITTORRENT);
     op->addTag(TAG_BITTORRENT);
+    op->setInitialOption(true);
     handlers.push_back(op);
     handlers.push_back(op);
   }
   }
   {
   {
@@ -1484,6 +1577,7 @@ OptionHandlers OptionHandlerFactory::createOptionHandlers()
                                           "60",
                                           "60",
                                           1, 600));
                                           1, 600));
     op->addTag(TAG_BITTORRENT);
     op->addTag(TAG_BITTORRENT);
+    op->setInitialOption(true);
     handlers.push_back(op);
     handlers.push_back(op);
   }
   }
   {
   {
@@ -1589,6 +1683,7 @@ OptionHandlers OptionHandlerFactory::createOptionHandlers()
                                     A2_V_TRUE,
                                     A2_V_TRUE,
                                     OptionHandler::OPT_ARG));
                                     OptionHandler::OPT_ARG));
     op->addTag(TAG_BITTORRENT);
     op->addTag(TAG_BITTORRENT);
+    op->setInitialOption(true);
     handlers.push_back(op);
     handlers.push_back(op);
   }
   }
   {
   {
@@ -1598,6 +1693,7 @@ OptionHandlers OptionHandlerFactory::createOptionHandlers()
                                     A2_V_TRUE,
                                     A2_V_TRUE,
                                     A2_V_TRUE, V_MEM, A2_V_FALSE));
                                     A2_V_TRUE, V_MEM, A2_V_FALSE));
     op->addTag(TAG_BITTORRENT);
     op->addTag(TAG_BITTORRENT);
+    op->setInitialOption(true);
     handlers.push_back(op);
     handlers.push_back(op);
   }
   }
   {
   {
@@ -1606,6 +1702,8 @@ OptionHandlers OptionHandlerFactory::createOptionHandlers()
                                     TEXT_INDEX_OUT,
                                     TEXT_INDEX_OUT,
                                     'O'));
                                     'O'));
     op->addTag(TAG_BITTORRENT);
     op->addTag(TAG_BITTORRENT);
+    op->setInitialOption(true);
+    op->setCumulative(true);
     handlers.push_back(op);
     handlers.push_back(op);
   }
   }
   {
   {
@@ -1626,6 +1724,7 @@ OptionHandlers OptionHandlerFactory::createOptionHandlers()
                                     0));
                                     0));
     op->addTag(TAG_BASIC);
     op->addTag(TAG_BASIC);
     op->addTag(TAG_BITTORRENT);
     op->addTag(TAG_BITTORRENT);
+    op->setGlobalChangeOption(true);
     handlers.push_back(op);
     handlers.push_back(op);
   }
   }
   {
   {
@@ -1637,6 +1736,8 @@ OptionHandlers OptionHandlerFactory::createOptionHandlers()
                                     'u'));
                                     'u'));
     op->addTag(TAG_BASIC);
     op->addTag(TAG_BASIC);
     op->addTag(TAG_BITTORRENT);
     op->addTag(TAG_BITTORRENT);
+    op->setInitialOption(true);
+    op->setChangeOption(true);
     handlers.push_back(op);
     handlers.push_back(op);
   }
   }
   {
   {
@@ -1673,6 +1774,7 @@ OptionHandlers OptionHandlerFactory::createOptionHandlers()
                                     NO_DEFAULT_VALUE,
                                     NO_DEFAULT_VALUE,
                                     0));
                                     0));
     op->addTag(TAG_BITTORRENT);
     op->addTag(TAG_BITTORRENT);
+    op->setInitialOption(true);
     handlers.push_back(op);
     handlers.push_back(op);
   }
   }
   {
   {
@@ -1682,6 +1784,7 @@ OptionHandlers OptionHandlerFactory::createOptionHandlers()
                                     "1.0",
                                     "1.0",
                                     0.0));
                                     0.0));
     op->addTag(TAG_BITTORRENT);
     op->addTag(TAG_BITTORRENT);
+    op->setInitialOption(true);
     handlers.push_back(op);
     handlers.push_back(op);
   }
   }
   {
   {
@@ -1705,6 +1808,7 @@ OptionHandlers OptionHandlerFactory::createOptionHandlers()
                                     A2_V_TRUE,
                                     A2_V_TRUE,
                                     A2_V_TRUE, V_MEM, A2_V_FALSE));
                                     A2_V_TRUE, V_MEM, A2_V_FALSE));
     op->addTag(TAG_METALINK);
     op->addTag(TAG_METALINK);
+    op->setInitialOption(true);
     handlers.push_back(op);
     handlers.push_back(op);
   }
   }
   {
   {
@@ -1713,6 +1817,7 @@ OptionHandlers OptionHandlerFactory::createOptionHandlers()
                                     TEXT_METALINK_BASE_URI,
                                     TEXT_METALINK_BASE_URI,
                                     NO_DEFAULT_VALUE));
                                     NO_DEFAULT_VALUE));
     op->addTag(TAG_METALINK);
     op->addTag(TAG_METALINK);
+    op->setInitialOption(true);
     handlers.push_back(op);
     handlers.push_back(op);
   }
   }
   {
   {
@@ -1722,6 +1827,7 @@ OptionHandlers OptionHandlerFactory::createOptionHandlers()
                                     A2_V_TRUE,
                                     A2_V_TRUE,
                                     OptionHandler::OPT_ARG));
                                     OptionHandler::OPT_ARG));
     op->addTag(TAG_METALINK);
     op->addTag(TAG_METALINK);
+    op->setInitialOption(true);
     handlers.push_back(op);
     handlers.push_back(op);
   }
   }
   {
   {
@@ -1740,6 +1846,7 @@ OptionHandlers OptionHandlerFactory::createOptionHandlers()
                                    (PREF_METALINK_LANGUAGE,
                                    (PREF_METALINK_LANGUAGE,
                                     TEXT_METALINK_LANGUAGE));
                                     TEXT_METALINK_LANGUAGE));
     op->addTag(TAG_METALINK);
     op->addTag(TAG_METALINK);
+    op->setInitialOption(true);
     handlers.push_back(op);
     handlers.push_back(op);
   }
   }
   {
   {
@@ -1747,6 +1854,7 @@ OptionHandlers OptionHandlerFactory::createOptionHandlers()
                                    (PREF_METALINK_OS,
                                    (PREF_METALINK_OS,
                                     TEXT_METALINK_OS));
                                     TEXT_METALINK_OS));
     op->addTag(TAG_METALINK);
     op->addTag(TAG_METALINK);
+    op->setInitialOption(true);
     handlers.push_back(op);
     handlers.push_back(op);
   }
   }
   {
   {
@@ -1758,6 +1866,7 @@ OptionHandlers OptionHandlerFactory::createOptionHandlers()
                                     std::vector<std::string>
                                     std::vector<std::string>
                                     (vbegin(params), vend(params))));
                                     (vbegin(params), vend(params))));
     op->addTag(TAG_METALINK);
     op->addTag(TAG_METALINK);
+    op->setInitialOption(true);
     handlers.push_back(op);
     handlers.push_back(op);
   }
   }
   {
   {
@@ -1768,6 +1877,7 @@ OptionHandlers OptionHandlerFactory::createOptionHandlers()
                                     1, -1,
                                     1, -1,
                                     'C'));
                                     'C'));
     op->addTag(TAG_METALINK);
     op->addTag(TAG_METALINK);
+    op->setInitialOption(true);
     handlers.push_back(op);
     handlers.push_back(op);
   }
   }
   {
   {
@@ -1775,6 +1885,7 @@ OptionHandlers OptionHandlerFactory::createOptionHandlers()
                                    (PREF_METALINK_VERSION,
                                    (PREF_METALINK_VERSION,
                                     TEXT_METALINK_VERSION));
                                     TEXT_METALINK_VERSION));
     op->addTag(TAG_METALINK);
     op->addTag(TAG_METALINK);
+    op->setInitialOption(true);
     handlers.push_back(op);
     handlers.push_back(op);
   }
   }
 #endif // ENABLE_METALINK
 #endif // ENABLE_METALINK
@@ -1822,7 +1933,7 @@ OptionHandlers OptionHandlerFactory::createOptionHandlers()
     op->addTag(TAG_HELP);
     op->addTag(TAG_HELP);
     handlers.push_back(op);
     handlers.push_back(op);
   }
   }
-  
+
   return handlers;
   return handlers;
 }
 }
 
 

+ 40 - 0
src/OptionHandlerImpl.cc

@@ -800,4 +800,44 @@ void DeprecatedOptionHandler::setEraseAfterParse(bool eraseAfterParse)
   depOptHandler_->setEraseAfterParse(eraseAfterParse);
   depOptHandler_->setEraseAfterParse(eraseAfterParse);
 }
 }
 
 
+bool DeprecatedOptionHandler::getInitialOption() const
+{
+  return depOptHandler_->getInitialOption();
+}
+
+void DeprecatedOptionHandler::setInitialOption(bool f)
+{
+  depOptHandler_->setInitialOption(f);
+}
+
+bool DeprecatedOptionHandler::getChangeOption() const
+{
+  return depOptHandler_->getChangeOption();
+}
+
+void DeprecatedOptionHandler::setChangeOption(bool f)
+{
+  depOptHandler_->setChangeOption(f);
+}
+
+bool DeprecatedOptionHandler::getGlobalChangeOption() const
+{
+  return depOptHandler_->getGlobalChangeOption();
+}
+
+void DeprecatedOptionHandler::setGlobalChangeOption(bool f)
+{
+  depOptHandler_->setGlobalChangeOption(f);
+}
+
+bool DeprecatedOptionHandler::getCumulative() const
+{
+  return depOptHandler_->getCumulative();
+}
+
+void DeprecatedOptionHandler::setCumulative(bool f)
+{
+  depOptHandler_->setCumulative(f);
+}
+
 } // namespace aria2
 } // namespace aria2

+ 8 - 0
src/OptionHandlerImpl.h

@@ -312,6 +312,14 @@ public:
   virtual void setOptionID(int id);
   virtual void setOptionID(int id);
   virtual bool getEraseAfterParse() const;
   virtual bool getEraseAfterParse() const;
   virtual void setEraseAfterParse(bool eraseAfterParse);
   virtual void setEraseAfterParse(bool eraseAfterParse);
+  virtual bool getInitialOption() const;
+  virtual void setInitialOption(bool f);
+  virtual bool getChangeOption() const;
+  virtual void setChangeOption(bool f);
+  virtual bool getGlobalChangeOption() const;
+  virtual void setGlobalChangeOption(bool f);
+  virtual bool getCumulative() const;
+  virtual void setCumulative(bool f);
 };
 };
 
 
 } // namespace aria2
 } // namespace aria2

+ 31 - 92
src/RpcMethod.cc

@@ -47,6 +47,7 @@
 #include "prefs.h"
 #include "prefs.h"
 #include "fmt.h"
 #include "fmt.h"
 #include "DlAbortEx.h"
 #include "DlAbortEx.h"
+#include "a2functional.h"
 
 
 namespace aria2 {
 namespace aria2 {
 
 
@@ -79,41 +80,37 @@ RpcResponse RpcMethod::execute
 }
 }
 
 
 namespace {
 namespace {
-template<typename InputIterator>
+template<typename InputIterator, typename Pred>
 void gatherOption
 void gatherOption
 (InputIterator first, InputIterator last,
 (InputIterator first, InputIterator last,
- const std::set<std::string>& allowedOptions,
- const SharedHandle<Option>& option,
+ Pred pred,
+ Option* option,
  const SharedHandle<OptionParser>& optionParser)
  const SharedHandle<OptionParser>& optionParser)
 {
 {
   for(; first != last; ++first) {
   for(; first != last; ++first) {
     const std::string& optionName = (*first).first;
     const std::string& optionName = (*first).first;
-    if(allowedOptions.count(optionName) == 0) {
+    const Pref* pref = option::k2p(optionName);
+    if(!pref) {
       throw DL_ABORT_EX
       throw DL_ABORT_EX
-        (fmt("%s option cannot be used in this context.",
-             optionName.c_str()));
-    } else {
-      const Pref* pref = option::k2p(optionName);
-      const SharedHandle<OptionHandler>& handler = optionParser->find(pref);
-      if(!handler) {
-        throw DL_ABORT_EX
-          (fmt("We don't know how to deal with %s option",
-               optionName.c_str()));
-      }
-      const String* opval = downcast<String>((*first).second);
-      if(opval) {
-        handler->parse(*option.get(), opval->s());
-      } else {
-        // header and index-out option can take array as value
-        const List* oplist = downcast<List>((*first).second);
-        if(oplist &&
-           (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);
-            if(opval) {
-              handler->parse(*option.get(), opval->s());
-            }
+        (fmt("We don't know how to deal with %s option", optionName.c_str()));
+    }
+    const SharedHandle<OptionHandler>& handler = optionParser->find(pref);
+    if(!handler || !pred(handler)) {
+      throw DL_ABORT_EX
+        (fmt("%s option cannot be used in this context.", optionName.c_str()));
+    }
+    const String* opval = downcast<String>((*first).second);
+    if(opval) {
+      handler->parse(*option, opval->s());
+    } else if(handler->getCumulative()) {
+      // header and index-out option can take array as value
+      const List* oplist = downcast<List>((*first).second);
+      if(oplist) {
+        for(List::ValueType::const_iterator argiter = oplist->begin(),
+              eoi = oplist->end(); argiter != eoi; ++argiter) {
+          const String* opval = downcast<String>(*argiter);
+          if(opval) {
+            handler->parse(*option, opval->s());
           }
           }
         }
         }
       }
       }
@@ -122,92 +119,34 @@ void gatherOption
 }
 }
 } // namespace
 } // namespace
 
 
-void RpcMethod::gatherRequestOption
-(const SharedHandle<Option>& option, const Dict* optionsDict)
+void RpcMethod::gatherRequestOption(Option* option, const Dict* optionsDict)
 {
 {
   if(optionsDict) {
   if(optionsDict) {
     gatherOption(optionsDict->begin(), optionsDict->end(),
     gatherOption(optionsDict->begin(), optionsDict->end(),
-                 listRequestOptions(),
+                 mem_fun_sh(&OptionHandler::getInitialOption),
                  option, optionParser_);
                  option, optionParser_);
   }
   }
 }
 }
 
 
-namespace {
-// Copy option in the range [optNameFirst, optNameLast) from src to
-// dest.
-template<typename InputIterator>
-void applyOption(InputIterator optNameFirst,
-                 InputIterator optNameLast,
-                 Option* dest,
-                 Option* src)
-{
-  for(; optNameFirst != optNameLast; ++optNameFirst) {
-    const Pref* pref = option::k2p(*optNameFirst);
-    if(src->defined(pref)) {
-      dest->put(pref, src->get(pref));
-    }
-  }
-}
-} // namespace
-
-const std::set<std::string>& listChangeableOptions()
-{
-  static const std::string OPTIONS[] = {
-    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;
-}
-
-void RpcMethod::gatherChangeableOption
-(const SharedHandle<Option>& option, const Dict* optionsDict)
+void RpcMethod::gatherChangeableOption(Option* option, const Dict* optionsDict)
 {
 {
   if(optionsDict) {
   if(optionsDict) {
     gatherOption(optionsDict->begin(), optionsDict->end(),
     gatherOption(optionsDict->begin(), optionsDict->end(),
-                 listChangeableOptions(),
+                 mem_fun_sh(&OptionHandler::getChangeOption),
                  option, optionParser_);
                  option, optionParser_);
   }
   }
 }
 }
 
 
-void RpcMethod::applyChangeableOption(Option* dest, Option* src) const
-{
-  applyOption(listChangeableOptions().begin(), listChangeableOptions().end(),
-              dest, src);
-}
-
-const std::set<std::string>& listChangeableGlobalOptions()
-{
-  static const std::string OPTIONS[] = {
-    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;
-}
-
 void RpcMethod::gatherChangeableGlobalOption
 void RpcMethod::gatherChangeableGlobalOption
-(const SharedHandle<Option>& option, const Dict* optionsDict)
+(Option* option, const Dict* optionsDict)
 {
 {
   if(optionsDict) {
   if(optionsDict) {
     gatherOption(optionsDict->begin(), optionsDict->end(),
     gatherOption(optionsDict->begin(), optionsDict->end(),
-                 listChangeableGlobalOptions(),
+                 mem_fun_sh(&OptionHandler::getGlobalChangeOption),
                  option, optionParser_);
                  option, optionParser_);
   }
   }
 }
 }
 
 
-void RpcMethod::applyChangeableGlobalOption(Option* dest, Option* src) const
-{
-  applyOption(listChangeableGlobalOptions().begin(),
-              listChangeableGlobalOptions().end(),
-              dest, src);
-}
-
 } // namespace rpc
 } // namespace rpc
 
 
 } // namespace aria2
 } // namespace aria2

+ 3 - 14
src/RpcMethod.h

@@ -72,22 +72,11 @@ protected:
   virtual SharedHandle<ValueBase> process
   virtual SharedHandle<ValueBase> process
   (const RpcRequest& req, DownloadEngine* e) = 0;
   (const RpcRequest& req, DownloadEngine* e) = 0;
 
 
-  void gatherRequestOption
-  (const SharedHandle<Option>& option, const Dict* optionsDict);
+  void gatherRequestOption(Option* option, const Dict* optionsDict);
 
 
-  void gatherChangeableOption
-  (const SharedHandle<Option>& option, const Dict* optionDict);
+  void gatherChangeableOption(Option* option, const Dict* optionDict);
 
 
-  // Copy options which is changeable in RPC changeOption command to
-  // dest.
-  void applyChangeableOption(Option* dest, Option* src) const;
-
-  void gatherChangeableGlobalOption(const SharedHandle<Option>& option,
-                                    const Dict* optionDict);
-
-  // Copy options which is changeable in RPC changeGlobalOption
-  // command to dest.
-  void applyChangeableGlobalOption(Option* dest, Option* src) const;
+  void gatherChangeableGlobalOption(Option* option, const Dict* optionDict);
 
 
   SharedHandle<ValueBase> createErrorResponse
   SharedHandle<ValueBase> createErrorResponse
   (const Exception& e, const RpcRequest& req);
   (const Exception& e, const RpcRequest& req);

+ 32 - 30
src/RpcMethodImpl.cc

@@ -230,7 +230,7 @@ SharedHandle<ValueBase> AddUriRpcMethod::process
   }
   }
 
 
   SharedHandle<Option> requestOption(new Option(*e->getOption()));
   SharedHandle<Option> requestOption(new Option(*e->getOption()));
-  gatherRequestOption(requestOption, optsParam);
+  gatherRequestOption(requestOption.get(), optsParam);
 
 
   bool posGiven = checkPosParam(posParam);
   bool posGiven = checkPosParam(posParam);
   size_t pos = posGiven ? posParam->i() : 0;
   size_t pos = posGiven ? posParam->i() : 0;
@@ -277,7 +277,7 @@ SharedHandle<ValueBase> AddTorrentRpcMethod::process
   extractUris(std::back_inserter(uris), urisParam);
   extractUris(std::back_inserter(uris), urisParam);
 
 
   SharedHandle<Option> requestOption(new Option(*e->getOption()));
   SharedHandle<Option> requestOption(new Option(*e->getOption()));
-  gatherRequestOption(requestOption, optsParam);
+  gatherRequestOption(requestOption.get(), optsParam);
 
 
   bool posGiven = checkPosParam(posParam);
   bool posGiven = checkPosParam(posParam);
   size_t pos = posGiven ? posParam->i() : 0;
   size_t pos = posGiven ? posParam->i() : 0;
@@ -320,7 +320,7 @@ SharedHandle<ValueBase> AddMetalinkRpcMethod::process
     metalinkParam = tempMetalinkParam.get();
     metalinkParam = tempMetalinkParam.get();
   }
   }
   SharedHandle<Option> requestOption(new Option(*e->getOption()));
   SharedHandle<Option> requestOption(new Option(*e->getOption()));
-  gatherRequestOption(requestOption, optsParam);
+  gatherRequestOption(requestOption.get(), optsParam);
 
 
   bool posGiven = checkPosParam(posParam);
   bool posGiven = checkPosParam(posParam);
   size_t pos = posGiven ? posParam->i() : 0;
   size_t pos = posGiven ? posParam->i() : 0;
@@ -1127,21 +1127,21 @@ SharedHandle<ValueBase> ChangeOptionRpcMethod::process
       (fmt("Cannot change option for GID#%s",
       (fmt("Cannot change option for GID#%s",
            util::itos(gid).c_str()));
            util::itos(gid).c_str()));
   }
   }
-  SharedHandle<Option> option(new Option());
-  gatherChangeableOption(option, optsParam);
-  applyChangeableOption(group->getOption().get(), option.get());
-  if(option->defined(PREF_MAX_DOWNLOAD_LIMIT)) {
+  Option option;
+  gatherChangeableOption(&option, optsParam);
+  group->getOption()->merge(option);
+  if(option.defined(PREF_MAX_DOWNLOAD_LIMIT)) {
     group->setMaxDownloadSpeedLimit
     group->setMaxDownloadSpeedLimit
-      (option->getAsInt(PREF_MAX_DOWNLOAD_LIMIT));
+      (option.getAsInt(PREF_MAX_DOWNLOAD_LIMIT));
   }
   }
-  if(option->defined(PREF_MAX_UPLOAD_LIMIT)) {
-    group->setMaxUploadSpeedLimit(option->getAsInt(PREF_MAX_UPLOAD_LIMIT));
+  if(option.defined(PREF_MAX_UPLOAD_LIMIT)) {
+    group->setMaxUploadSpeedLimit(option.getAsInt(PREF_MAX_UPLOAD_LIMIT));
   }
   }
 #ifdef ENABLE_BITTORRENT
 #ifdef ENABLE_BITTORRENT
   BtObject btObject = e->getBtRegistry()->get(group->getGID());
   BtObject btObject = e->getBtRegistry()->get(group->getGID());
   if(!btObject.isNull()) {
   if(!btObject.isNull()) {
-    if(option->defined(PREF_BT_MAX_PEERS)) {
-      btObject.btRuntime_->setMaxPeers(option->getAsInt(PREF_BT_MAX_PEERS));
+    if(option.defined(PREF_BT_MAX_PEERS)) {
+      btObject.btRuntime_->setMaxPeers(option.getAsInt(PREF_BT_MAX_PEERS));
     }
     }
   }
   }
 #endif // ENABLE_BITTORRENT
 #endif // ENABLE_BITTORRENT
@@ -1153,28 +1153,28 @@ SharedHandle<ValueBase> ChangeGlobalOptionRpcMethod::process
 {
 {
   const Dict* optsParam = checkRequiredParam<Dict>(req, 0);
   const Dict* optsParam = checkRequiredParam<Dict>(req, 0);
 
 
-  SharedHandle<Option> option(new Option());
-  gatherChangeableGlobalOption(option, optsParam);
-  applyChangeableGlobalOption(e->getOption(), option.get());
+  Option option;
+  gatherChangeableGlobalOption(&option, optsParam);
+  e->getOption()->merge(option);
 
 
-  if(option->defined(PREF_MAX_OVERALL_DOWNLOAD_LIMIT)) {
+  if(option.defined(PREF_MAX_OVERALL_DOWNLOAD_LIMIT)) {
     e->getRequestGroupMan()->setMaxOverallDownloadSpeedLimit
     e->getRequestGroupMan()->setMaxOverallDownloadSpeedLimit
-      (option->getAsInt(PREF_MAX_OVERALL_DOWNLOAD_LIMIT));
+      (option.getAsInt(PREF_MAX_OVERALL_DOWNLOAD_LIMIT));
   }
   }
-  if(option->defined(PREF_MAX_OVERALL_UPLOAD_LIMIT)) {
+  if(option.defined(PREF_MAX_OVERALL_UPLOAD_LIMIT)) {
     e->getRequestGroupMan()->setMaxOverallUploadSpeedLimit
     e->getRequestGroupMan()->setMaxOverallUploadSpeedLimit
-      (option->getAsInt(PREF_MAX_OVERALL_UPLOAD_LIMIT));
+      (option.getAsInt(PREF_MAX_OVERALL_UPLOAD_LIMIT));
   }
   }
-  if(option->defined(PREF_MAX_CONCURRENT_DOWNLOADS)) {
+  if(option.defined(PREF_MAX_CONCURRENT_DOWNLOADS)) {
     e->getRequestGroupMan()->setMaxSimultaneousDownloads
     e->getRequestGroupMan()->setMaxSimultaneousDownloads
-      (option->getAsInt(PREF_MAX_CONCURRENT_DOWNLOADS));
+      (option.getAsInt(PREF_MAX_CONCURRENT_DOWNLOADS));
     e->getRequestGroupMan()->requestQueueCheck();
     e->getRequestGroupMan()->requestQueueCheck();
   }
   }
-  if(option->defined(PREF_LOG_LEVEL)) {
-    LogFactory::setLogLevel(option->get(PREF_LOG_LEVEL));
+  if(option.defined(PREF_LOG_LEVEL)) {
+    LogFactory::setLogLevel(option.get(PREF_LOG_LEVEL));
   }
   }
-  if(option->defined(PREF_LOG)) {
-    LogFactory::setLogFile(option->get(PREF_LOG));
+  if(option.defined(PREF_LOG)) {
+    LogFactory::setLogFile(option.get(PREF_LOG));
     try {
     try {
       LogFactory::reconfigure();
       LogFactory::reconfigure();
     } catch(RecoverableException& e) {
     } catch(RecoverableException& e) {
@@ -1204,12 +1204,14 @@ SharedHandle<ValueBase> GetVersionRpcMethod::process
 
 
 namespace {
 namespace {
 void pushRequestOption
 void pushRequestOption
-(const SharedHandle<Dict>& dict, const SharedHandle<Option>& option)
+(const SharedHandle<Dict>& dict,
+ const SharedHandle<Option>& option,
+ const SharedHandle<OptionParser>& oparser)
 {
 {
-  const std::set<std::string>& requestOptions = listRequestOptions();
-  for(size_t i = 0, len = option->getTable().size(); i < len; ++i) {
+  for(size_t i = 1, len = option::countOption(); i < len; ++i) {
     const Pref* pref = option::i2p(i);
     const Pref* pref = option::i2p(i);
-    if(requestOptions.count(pref->k) && option->defined(pref)) {
+    const SharedHandle<OptionHandler>& h = oparser->find(pref);
+    if(h && h->getInitialOption() && option->defined(pref)) {
       dict->put(pref->k, option->get(pref));
       dict->put(pref->k, option->get(pref));
     }
     }
   }
   }
@@ -1231,7 +1233,7 @@ SharedHandle<ValueBase> GetOptionRpcMethod::process
   }
   }
   SharedHandle<Dict> result = Dict::g();
   SharedHandle<Dict> result = Dict::g();
   SharedHandle<Option> option = group->getOption();
   SharedHandle<Option> option = group->getOption();
-  pushRequestOption(result, option);
+  pushRequestOption(result, option, getOptionParser());
   return result;
   return result;
 }
 }
 
 

+ 19 - 49
src/SessionSerializer.cc

@@ -49,6 +49,8 @@
 #include "util.h"
 #include "util.h"
 #include "array_fun.h"
 #include "array_fun.h"
 #include "BufferedFile.h"
 #include "BufferedFile.h"
+#include "OptionParser.h"
+#include "OptionHandler.h"
 
 
 namespace aria2 {
 namespace aria2 {
 
 
@@ -74,58 +76,26 @@ bool SessionSerializer::save(const std::string& filename) const
   return File(tempFilename).renameTo(filename);
   return File(tempFilename).renameTo(filename);
 }
 }
 
 
-
-namespace {
-const std::vector<std::string>& getCumulativeOpts()
-{
-  static std::string cumulativeOpts[] = { PREF_INDEX_OUT->k, PREF_HEADER->k };
-  static std::vector<std::string> opts
-    (vbegin(cumulativeOpts), vend(cumulativeOpts));
-  return opts;
-}
-} // namespace
-
-namespace {
-bool inCumulativeOpts(const std::string& opt)
-{
-  const std::vector<std::string>& cumopts = getCumulativeOpts();
-  for(std::vector<std::string>::const_iterator itr = cumopts.begin(),
-        eoi = cumopts.end(); itr != eoi; ++itr) {
-    if(opt == *itr) {
-      return true;
-    }
-  }
-  return false;
-}
-} // namespace
-
 namespace {
 namespace {
 bool writeOption(BufferedFile& fp, const SharedHandle<Option>& op)
 bool writeOption(BufferedFile& fp, const SharedHandle<Option>& op)
 {
 {
-  const std::set<std::string>& requestOptions = listRequestOptions();
-  for(std::set<std::string>::const_iterator itr = requestOptions.begin(),
-        eoi = requestOptions.end(); itr != eoi; ++itr) {
-    if(inCumulativeOpts(*itr)) {
-      continue;
-    }
-    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;
-      }
-    }
-  }
-  const std::vector<std::string>& cumopts = getCumulativeOpts();
-  for(std::vector<std::string>::const_iterator opitr = cumopts.begin(),
-        eoi = cumopts.end(); opitr != eoi; ++opitr) {
-    const Pref* pref = option::k2p(*opitr);
-    if(op->defined(pref)) {
-      std::vector<std::string> v;
-      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) {
-        if(fp.printf(" %s=%s\n", (*opitr).c_str(), (*i).c_str()) < 0) {
+  const SharedHandle<OptionParser>& oparser = OptionParser::getInstance();
+  for(size_t i = 1, len = option::countOption(); i < len; ++i) {
+    const Pref* pref = option::i2p(i);
+    const SharedHandle<OptionHandler>& h = oparser->find(pref);
+    if(h && h->getInitialOption() && op->defined(pref)) {
+      if(h->getCumulative()) {
+        std::vector<std::string> v;
+        util::split(op->get(pref), std::back_inserter(v), "\n",
+                    false, false);
+        for(std::vector<std::string>::const_iterator j = v.begin(),
+              eoj = v.end(); j != eoj; ++j) {
+          if(fp.printf(" %s=%s\n", pref->k.c_str(), (*j).c_str()) < 0) {
+            return false;
+          }
+        }
+      } else {
+        if(fp.printf(" %s=%s\n", pref->k.c_str(), op->get(pref).c_str()) < 0) {
           return false;
           return false;
         }
         }
       }
       }

+ 9 - 119
src/download_helper.cc

@@ -61,6 +61,7 @@
 #include "a2functional.h"
 #include "a2functional.h"
 #include "ByteArrayDiskWriterFactory.h"
 #include "ByteArrayDiskWriterFactory.h"
 #include "MetadataInfo.h"
 #include "MetadataInfo.h"
+#include "OptionParser.h"
 #ifdef ENABLE_BITTORRENT
 #ifdef ENABLE_BITTORRENT
 # include "bittorrent_helper.h"
 # include "bittorrent_helper.h"
 # include "BtConstants.h"
 # include "BtConstants.h"
@@ -69,115 +70,6 @@
 
 
 namespace aria2 {
 namespace aria2 {
 
 
-const std::set<std::string>& listRequestOptions()
-{
-  static const std::string REQUEST_OPTIONS[] = {
-    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));
-  return requestOptions;
-}
-
 namespace {
 namespace {
 void unfoldURI
 void unfoldURI
 (std::vector<std::string>& result, const std::vector<std::string>& args)
 (std::vector<std::string>& result, const std::vector<std::string>& args)
@@ -523,23 +415,21 @@ void createRequestGroupForUriList
   UriListParser p(filename);
   UriListParser p(filename);
   while(p.hasNext()) {
   while(p.hasNext()) {
     std::vector<std::string> uris;
     std::vector<std::string> uris;
-    SharedHandle<Option> tempOption(new Option());
-    p.parseNext(uris, *tempOption.get());
+    Option tempOption;
+    p.parseNext(uris, tempOption);
     if(uris.empty()) {
     if(uris.empty()) {
       continue;
       continue;
     }
     }
-
     SharedHandle<Option> requestOption(new Option(*option.get()));
     SharedHandle<Option> requestOption(new Option(*option.get()));
     requestOption->remove(PREF_OUT);
     requestOption->remove(PREF_OUT);
-    for(std::set<std::string>::const_iterator i =
-          listRequestOptions().begin(), eoi = listRequestOptions().end();
-        i != eoi; ++i) {
-      const Pref* pref = option::k2p(*i);
-      if(tempOption->defined(pref)) {
-        requestOption->put(pref, tempOption->get(pref));
+    const SharedHandle<OptionParser>& oparser = OptionParser::getInstance();
+    for(size_t i = 1, len = option::countOption(); i < len; ++i) {
+      const Pref* pref = option::i2p(i);
+      const SharedHandle<OptionHandler>& h = oparser->find(pref);
+      if(h && h->getInitialOption() && tempOption.defined(pref)) {
+        requestOption->put(pref, tempOption.get(pref));
       }
       }
     }
     }
-
     createRequestGroupForUri(result, requestOption, uris);
     createRequestGroupForUri(result, requestOption, uris);
   }
   }
 }
 }

+ 0 - 2
src/download_helper.h

@@ -50,8 +50,6 @@ class Option;
 class MetadataInfo;
 class MetadataInfo;
 class DownloadContext;
 class DownloadContext;
 
 
-const std::set<std::string>& listRequestOptions();
-
 #ifdef ENABLE_BITTORRENT
 #ifdef ENABLE_BITTORRENT
 // Create RequestGroup object using torrent file specified by
 // Create RequestGroup object using torrent file specified by
 // torrent-file option.  If non-empty torrentData is specified, then
 // torrent-file option.  If non-empty torrentData is specified, then

+ 17 - 0
test/OptionTest.cc

@@ -16,6 +16,7 @@ class OptionTest:public CppUnit::TestFixture {
   CPPUNIT_TEST(testPutAndGetAsDouble);
   CPPUNIT_TEST(testPutAndGetAsDouble);
   CPPUNIT_TEST(testDefined);
   CPPUNIT_TEST(testDefined);
   CPPUNIT_TEST(testBlank);
   CPPUNIT_TEST(testBlank);
+  CPPUNIT_TEST(testMerge);
   CPPUNIT_TEST_SUITE_END();
   CPPUNIT_TEST_SUITE_END();
 private:
 private:
 
 
@@ -28,6 +29,7 @@ public:
   void testPutAndGetAsDouble();
   void testPutAndGetAsDouble();
   void testDefined();
   void testDefined();
   void testBlank();
   void testBlank();
+  void testMerge();
 };
 };
 
 
 
 
@@ -76,4 +78,19 @@ void OptionTest::testBlank()
   CPPUNIT_ASSERT(op.blank(PREF_DAEMON));
   CPPUNIT_ASSERT(op.blank(PREF_DAEMON));
 }
 }
 
 
+void OptionTest::testMerge()
+{
+  Option src;
+  src.put(PREF_TIMEOUT, "100");
+  src.put(PREF_DAEMON, "true");
+  Option dest;
+  dest.put(PREF_DAEMON, "false");
+  dest.put(PREF_DIR, "foo");
+  dest.merge(src);
+  CPPUNIT_ASSERT_EQUAL(100, dest.getAsInt(PREF_TIMEOUT));
+  CPPUNIT_ASSERT(dest.getAsBool(PREF_DAEMON));
+  CPPUNIT_ASSERT_EQUAL(std::string("foo"), dest.get(PREF_DIR));
+  CPPUNIT_ASSERT(!dest.defined(PREF_OUT));
+}
+
 } // namespace aria2
 } // namespace aria2