From 295a62f538df8115d932f09e69e2950484e038c0 Mon Sep 17 00:00:00 2001 From: Tatsuhiro Tsujikawa Date: Sun, 23 Sep 2012 14:59:05 +0900 Subject: [PATCH] Rewritten help tags and various internal flag handling in OptionHandler Now help tags are defined as enum values to avoid vector of strings. The internal flags are represented by bitmask to shrink size. --- src/AbstractOptionHandler.cc | 111 ++++++++++++++++++++++++++++++---- src/AbstractOptionHandler.h | 114 ++++++++++++----------------------- src/Makefile.am | 2 +- src/OptionHandler.h | 6 +- src/OptionHandlerFactory.cc | 27 +++------ src/OptionHandlerImpl.cc | 4 +- src/OptionHandlerImpl.h | 5 +- src/OptionParser.cc | 2 +- src/OptionParser.h | 2 +- src/help_tags.cc | 83 +++++++++++++++++++++++++ src/help_tags.h | 51 ++++++++++------ src/option_processing.cc | 6 +- src/version_usage.cc | 9 +-- test/OptionHandlerTest.cc | 17 +++--- test/OptionParserTest.cc | 17 +++--- 15 files changed, 296 insertions(+), 160 deletions(-) create mode 100644 src/help_tags.cc diff --git a/src/AbstractOptionHandler.cc b/src/AbstractOptionHandler.cc index f06c9ea3..46ba7c7a 100644 --- a/src/AbstractOptionHandler.cc +++ b/src/AbstractOptionHandler.cc @@ -40,6 +40,7 @@ #include "a2functional.h" #include "Option.h" #include "prefs.h" +#include "help_tags.h" namespace aria2 { @@ -54,17 +55,12 @@ AbstractOptionHandler::AbstractOptionHandler defaultValue_(defaultValue), argType_(argType), shortName_(shortName), - hidden_(false), - eraseAfterParse_(false), - initialOption_(false), - changeOption_(false), - changeOptionForReserved_(false), - globalChangeOption_(false), - cumulative_(false) + tags_(0), + flags_(0) {} AbstractOptionHandler::~AbstractOptionHandler() {} - + void AbstractOptionHandler::parse(Option& option, const std::string& arg) { try { @@ -74,19 +70,29 @@ void AbstractOptionHandler::parse(Option& option, const std::string& arg) } } -bool AbstractOptionHandler::hasTag(const std::string& tag) const +bool AbstractOptionHandler::hasTag(uint32_t tag) const { - return std::find(tags_.begin(), tags_.end(), tag) != tags_.end(); + return (tags_ & (1 << tag)); } -void AbstractOptionHandler::addTag(const std::string& tag) +void AbstractOptionHandler::addTag(uint32_t tag) { - tags_.push_back(tag); + tags_ |= (1 << tag); } std::string AbstractOptionHandler::toTagString() const { - return strjoin(tags_.begin(), tags_.end(), ", "); + std::string s; + for(int i = 0; i < MAX_HELP_TAG; ++i) { + if(tags_ & (1 << i)) { + s += strHelpTag(i); + s += ", "; + } + } + if(!s.empty()) { + s.resize(s.size() - 2); + } + return s; } const char* AbstractOptionHandler::getName() const @@ -94,4 +100,83 @@ const char* AbstractOptionHandler::getName() const return pref_->k; } +void AbstractOptionHandler::updateFlags(int flag, bool val) +{ + if(val) { + flags_ |= flag; + } else { + flags_ &= ~flag; + } +} + +bool AbstractOptionHandler::isHidden() const +{ + return flags_ & FLAG_HIDDEN; +} + +void AbstractOptionHandler::hide() +{ + updateFlags(FLAG_HIDDEN, true); +} + +bool AbstractOptionHandler::getEraseAfterParse() const +{ + return flags_ & FLAG_ERASE_AFTER_PARSE; +} + +void AbstractOptionHandler::setEraseAfterParse(bool f) +{ + updateFlags(FLAG_ERASE_AFTER_PARSE, f); +} + +bool AbstractOptionHandler::getInitialOption() const +{ + return flags_ & FLAG_INITIAL_OPTION; +} + +void AbstractOptionHandler::setInitialOption(bool f) +{ + updateFlags(FLAG_INITIAL_OPTION, f); +} + +bool AbstractOptionHandler::getChangeOption() const +{ + return flags_ & FLAG_CHANGE_OPTION; +} + +void AbstractOptionHandler::setChangeOption(bool f) +{ + updateFlags(FLAG_CHANGE_OPTION, f); +} + +bool AbstractOptionHandler::getChangeOptionForReserved() const +{ + return flags_ & FLAG_CHANGE_OPTION_FOR_RESERVED; +} + +void AbstractOptionHandler::setChangeOptionForReserved(bool f) +{ + updateFlags(FLAG_CHANGE_OPTION_FOR_RESERVED, f); +} + +bool AbstractOptionHandler::getChangeGlobalOption() const +{ + return flags_ & FLAG_CHANGE_GLOBAL_OPTION; +} + +void AbstractOptionHandler::setChangeGlobalOption(bool f) +{ + updateFlags(FLAG_CHANGE_GLOBAL_OPTION, f); +} + +bool AbstractOptionHandler::getCumulative() const +{ + return flags_ & FLAG_CUMULATIVE; +} + +void AbstractOptionHandler::setCumulative(bool f) +{ + updateFlags(FLAG_CUMULATIVE, f); +} + } // namespace aria2 diff --git a/src/AbstractOptionHandler.h b/src/AbstractOptionHandler.h index c7faf4b9..296852b6 100644 --- a/src/AbstractOptionHandler.h +++ b/src/AbstractOptionHandler.h @@ -37,10 +37,6 @@ #include "OptionHandler.h" -#include - -#include "A2STR.h" - namespace aria2 { class Option; @@ -54,22 +50,10 @@ protected: std::string defaultValue_; - std::vector tags_; - OptionHandler::ARG_TYPE argType_; char shortName_; - bool hidden_; - - bool eraseAfterParse_; - - bool initialOption_; - bool changeOption_; - bool changeOptionForReserved_; - bool globalChangeOption_; - bool cumulative_; - virtual void parseArg(Option& option, const std::string& arg) = 0; public: AbstractOptionHandler(const Pref* pref, @@ -79,12 +63,12 @@ public: char shortName = 0); virtual ~AbstractOptionHandler(); - + virtual void parse(Option& option, const std::string& arg); - virtual bool hasTag(const std::string& tag) const; + virtual bool hasTag(uint32_t tag) const; - virtual void addTag(const std::string& tag); + virtual void addTag(uint32_t tag); virtual std::string toTagString() const; @@ -100,16 +84,6 @@ public: return defaultValue_; } - virtual bool isHidden() const - { - return hidden_; - } - - virtual void hide() - { - hidden_ = true; - } - virtual const Pref* getPref() const { return pref_; @@ -125,65 +99,51 @@ public: return argType_; } - virtual bool getEraseAfterParse() const - { - return eraseAfterParse_; - } + virtual bool isHidden() const; - virtual void setEraseAfterParse(bool eraseAfterParse) - { - eraseAfterParse_ = eraseAfterParse; - } + virtual void hide(); - virtual bool getInitialOption() const - { - return initialOption_; - } + virtual bool getEraseAfterParse() const; - virtual void setInitialOption(bool f) - { - initialOption_ = f; - } + virtual void setEraseAfterParse(bool f); - virtual bool getChangeOption() const - { - return changeOption_; - } + virtual bool getInitialOption() const; - virtual void setChangeOption(bool f) - { - changeOption_ = f; - } + virtual void setInitialOption(bool f); - virtual bool getChangeOptionForReserved() const - { - return changeOptionForReserved_; - } + virtual bool getChangeOption() const; - virtual void setChangeOptionForReserved(bool f) - { - changeOptionForReserved_ = f; - } + virtual void setChangeOption(bool f); - virtual bool getChangeGlobalOption() const - { - return globalChangeOption_; - } + virtual bool getChangeOptionForReserved() const; - virtual void setChangeGlobalOption(bool f) - { - globalChangeOption_ = f; - } + virtual void setChangeOptionForReserved(bool f); - virtual bool getCumulative() const - { - return cumulative_; - } + virtual bool getChangeGlobalOption() const; - virtual void setCumulative(bool f) - { - cumulative_ = f; - } + virtual void setChangeGlobalOption(bool f); + + virtual bool getCumulative() const; + + virtual void setCumulative(bool f); + + enum Flag { + FLAG_HIDDEN = 1, + FLAG_ERASE_AFTER_PARSE = 1 << 1, + FLAG_INITIAL_OPTION = 1 << 2, + FLAG_CHANGE_OPTION = 1 << 3, + FLAG_CHANGE_OPTION_FOR_RESERVED = 1 << 4, + FLAG_CHANGE_GLOBAL_OPTION = 1 << 5, + FLAG_CUMULATIVE = 1 << 6 + }; +private: + // bitwise OR of (1 << HelpTag value) defined in help_tags.h. + uint32_t tags_; + + // bitwise OR of Flag values. + uint8_t flags_; + + void updateFlags(int flag, bool val); }; } // namespace aria2 diff --git a/src/Makefile.am b/src/Makefile.am index a4a88790..d129221f 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -149,7 +149,7 @@ SRCS = Socket.h\ a2netcompat.h\ a2time.h\ array_fun.h\ - help_tags.h\ + help_tags.cc help_tags.h\ prefs.cc prefs.h\ usage_text.h\ ProtocolDetector.cc ProtocolDetector.h\ diff --git a/src/OptionHandler.h b/src/OptionHandler.h index 3e17ada7..a0f0ed8a 100644 --- a/src/OptionHandler.h +++ b/src/OptionHandler.h @@ -62,14 +62,14 @@ struct Pref; class OptionHandler { public: virtual ~OptionHandler() {} - + virtual void parse(Option& option, const std::string& arg) = 0; virtual std::string createPossibleValuesString() const = 0; - virtual bool hasTag(const std::string& tag) const = 0; + virtual bool hasTag(uint32_t tag) const = 0; - virtual void addTag(const std::string& tag) = 0; + virtual void addTag(uint32_t tag) = 0; virtual std::string toTagString() const = 0; diff --git a/src/OptionHandlerFactory.cc b/src/OptionHandlerFactory.cc index 1910f81c..cfb47001 100644 --- a/src/OptionHandlerFactory.cc +++ b/src/OptionHandlerFactory.cc @@ -2173,29 +2173,16 @@ OptionHandlerFactory::createOptionHandlers() } // Help Option { - static std::string tags[] = { - TAG_BASIC, - TAG_ADVANCED, - TAG_HTTP, - TAG_HTTPS, - TAG_FTP, - TAG_METALINK, - TAG_BITTORRENT, - TAG_COOKIE, - TAG_HOOK, - TAG_FILE, - TAG_RPC, - TAG_CHECKSUM, - TAG_EXPERIMENTAL, - TAG_DEPRECATED, - TAG_HELP, - TAG_ALL - }; - static std::string tagsStr = strjoin(vbegin(tags), vend(tags), ", "); + std::string tagsStr; + for(int i = 0; i < MAX_HELP_TAG; ++i) { + tagsStr += strHelpTag(i); + tagsStr += ", "; + } + tagsStr += STR_TAG_ALL; SharedHandle op(new DefaultOptionHandler (PREF_HELP, TEXT_HELP, - TAG_BASIC, + strHelpTag(TAG_BASIC), tagsStr, OptionHandler::OPT_ARG, 'h')); diff --git a/src/OptionHandlerImpl.cc b/src/OptionHandlerImpl.cc index 89c39298..86cc9d28 100644 --- a/src/OptionHandlerImpl.cc +++ b/src/OptionHandlerImpl.cc @@ -630,12 +630,12 @@ std::string DeprecatedOptionHandler::createPossibleValuesString() const return depOptHandler_->createPossibleValuesString(); } -bool DeprecatedOptionHandler::hasTag(const std::string& tag) const +bool DeprecatedOptionHandler::hasTag(uint32_t tag) const { return depOptHandler_->hasTag(tag); } -void DeprecatedOptionHandler::addTag(const std::string& tag) +void DeprecatedOptionHandler::addTag(uint32_t tag) { depOptHandler_->addTag(tag); } diff --git a/src/OptionHandlerImpl.h b/src/OptionHandlerImpl.h index b046cd8a..7537ffbd 100644 --- a/src/OptionHandlerImpl.h +++ b/src/OptionHandlerImpl.h @@ -40,6 +40,7 @@ #include #include "AbstractOptionHandler.h" +#include "A2STR.h" namespace aria2 { @@ -278,8 +279,8 @@ public: SharedHandle()); virtual void parse(Option& option, const std::string& arg); virtual std::string createPossibleValuesString() const; - virtual bool hasTag(const std::string& tag) const; - virtual void addTag(const std::string& tag); + virtual bool hasTag(uint32_t tag) const; + virtual void addTag(uint32_t tag); virtual std::string toTagString() const; virtual const char* getName() const; virtual const char* getDescription() const; diff --git a/src/OptionParser.cc b/src/OptionParser.cc index 04778f78..53e0c2c0 100644 --- a/src/OptionParser.cc +++ b/src/OptionParser.cc @@ -268,7 +268,7 @@ void OptionParser::parseDefaultValues(Option& option) const } std::vector > -OptionParser::findByTag(const std::string& tag) const +OptionParser::findByTag(uint32_t tag) const { std::vector > result; for(std::vector >::const_iterator i = diff --git a/src/OptionParser.h b/src/OptionParser.h index 8d28bbeb..901fe8ec 100644 --- a/src/OptionParser.h +++ b/src/OptionParser.h @@ -76,7 +76,7 @@ public: // Hidden options are not returned. std::vector > - findByTag(const std::string& tag) const; + findByTag(uint32_t tag) const; // Hidden options are not returned. std::vector > diff --git a/src/help_tags.cc b/src/help_tags.cc new file mode 100644 index 00000000..9b32729f --- /dev/null +++ b/src/help_tags.cc @@ -0,0 +1,83 @@ +/* */ +#include "help_tags.h" + +#include + +#include "array_fun.h" + +namespace aria2 { + +namespace { +const char* HELP_TAG_NAMES[] = { + "#basic", + "#advanced", + "#http", + "#https", + "#ftp", + "#metalink", + "#bittorrent", + "#cookie", + "#hook", + "#file", + "#rpc", + "#checksum", + "#experimental", + "#deprecated", + "#help" +}; +} // namespace + +const char* strHelpTag(uint32_t tag) +{ + if(tag >= MAX_HELP_TAG) { + return "UNKNOWN"; + } else { + return HELP_TAG_NAMES[tag]; + } +} + +uint32_t idHelpTag(const char* tagName) +{ + for(const char** p = vbegin(HELP_TAG_NAMES), ** eop = vend(HELP_TAG_NAMES); + p != eop; ++p) { + if(strcmp(*p, tagName) == 0) { + return p - vbegin(HELP_TAG_NAMES); + } + } + return MAX_HELP_TAG; +} + +} // namespace aria2 diff --git a/src/help_tags.h b/src/help_tags.h index 13665dbe..e6f5de1c 100644 --- a/src/help_tags.h +++ b/src/help_tags.h @@ -2,7 +2,7 @@ /* * aria2 - The high speed download utility * - * Copyright (C) 2006 Tatsuhiro Tsujikawa + * Copyright (C) 2012 Tatsuhiro Tsujikawa * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -35,21 +35,38 @@ #ifndef D_HELP_TAGS_H #define D_HELP_TAGS_H -#define TAG_BASIC "#basic" -#define TAG_ADVANCED "#advanced" -#define TAG_HTTP "#http" -#define TAG_HTTPS "#https" -#define TAG_FTP "#ftp" -#define TAG_METALINK "#metalink" -#define TAG_BITTORRENT "#bittorrent" -#define TAG_COOKIE "#cookie" -#define TAG_HOOK "#hook" -#define TAG_FILE "#file" -#define TAG_RPC "#rpc" -#define TAG_CHECKSUM "#checksum" -#define TAG_EXPERIMENTAL "#experimental" -#define TAG_DEPRECATED "#deprecated" -#define TAG_HELP "#help" -#define TAG_ALL "#all" +#include "common.h" + +namespace aria2 { + +enum HelpTag { + TAG_BASIC, + TAG_ADVANCED, + TAG_HTTP, + TAG_HTTPS, + TAG_FTP, + TAG_METALINK, + TAG_BITTORRENT, + TAG_COOKIE, + TAG_HOOK, + TAG_FILE, + TAG_RPC, + TAG_CHECKSUM, + TAG_EXPERIMENTAL, + TAG_DEPRECATED, + TAG_HELP, + MAX_HELP_TAG +}; + +#define STR_TAG_ALL "#all" + +// Returns tag name of the given |tag| ID. +const char* strHelpTag(uint32_t tag); + +// Returns the corresponding enum value of the given |tagName|. If +// there is no such tag, returns MAX_HELP_TAG. +uint32_t idHelpTag(const char* tagName); + +} // namespace aria2 #endif // D_HELP_TAGS_H diff --git a/src/option_processing.cc b/src/option_processing.cc index c1c6d065..66be040e 100644 --- a/src/option_processing.cc +++ b/src/option_processing.cc @@ -198,7 +198,7 @@ void option_processing(Option& op, std::vector& uris, if(op.defined(PREF_HELP)) { std::string keyword; if(op.get(PREF_HELP).empty()) { - keyword = TAG_BASIC; + keyword = strHelpTag(TAG_BASIC); } else { keyword = op.get(PREF_HELP); if(util::startsWith(keyword, "--")) { @@ -217,7 +217,7 @@ void option_processing(Option& op, std::vector& uris, oparser->parseDefaultValues(op); if(!noConf) { - std::string cfname = + std::string cfname = ucfname.empty() ? oparser->find(PREF_CONF_PATH)->getDefaultValue() : ucfname; @@ -249,7 +249,7 @@ void option_processing(Option& op, std::vector& uris, global::cerr()->printf(_("Configuration file %s is not found."), cfname.c_str()); global::cerr()->printf("\n"); - showUsage(TAG_HELP, oparser, global::cerr()); + showUsage(strHelpTag(TAG_HELP), oparser, global::cerr()); exit(error_code::UNKNOWN_ERROR); } } diff --git a/src/version_usage.cc b/src/version_usage.cc index 26f3a63e..77dd9e98 100644 --- a/src/version_usage.cc +++ b/src/version_usage.cc @@ -94,8 +94,9 @@ void showUsage return; } else if(keyword[0] == '#') { std::vector > handlers = - keyword == TAG_ALL ? oparser->findAll() : oparser->findByTag(keyword); - if(keyword == TAG_ALL) { + keyword == STR_TAG_ALL ? oparser->findAll() : + oparser->findByTag(idHelpTag(keyword.c_str())); + if(keyword == STR_TAG_ALL) { out->printf(_("Printing all options.")); } else { out->printf(_("Printing options tagged with '%s'."), @@ -111,7 +112,7 @@ void showUsage write(out, *(*i)); out->printf("\n"); } - } else { + } else { std::vector > handlers = oparser->findByNameSubstring(keyword); if(!handlers.empty()) { @@ -132,7 +133,7 @@ void showUsage write(out, *oparser->find(PREF_HELP)); } } - if(keyword == TAG_BASIC) { + if(keyword == strHelpTag(TAG_BASIC)) { out->printf("URI, MAGNET, TORRENT_FILE, METALINK_FILE:\n"); out->printf(_(" You can specify multiple HTTP(S)/FTP URIs. Unless you specify -Z option, all\n" " URIs must point to the same file or downloading will fail.")); diff --git a/test/OptionHandlerTest.cc b/test/OptionHandlerTest.cc index d3da8902..1d01b6a8 100644 --- a/test/OptionHandlerTest.cc +++ b/test/OptionHandlerTest.cc @@ -5,6 +5,7 @@ #include "Option.h" #include "prefs.h" #include "Exception.h" +#include "help_tags.h" namespace aria2 { @@ -28,7 +29,7 @@ class OptionHandlerTest:public CppUnit::TestFixture { CPPUNIT_TEST(testHttpProxyOptionHandler); CPPUNIT_TEST(testDeprecatedOptionHandler); CPPUNIT_TEST_SUITE_END(); - + public: void testBooleanOptionHandler(); void testNumberOptionHandler(); @@ -207,13 +208,13 @@ void OptionHandlerTest::testDefaultOptionHandler() CPPUNIT_ASSERT_EQUAL(std::string(""), option.get(PREF_TIMEOUT)); CPPUNIT_ASSERT_EQUAL(std::string(""), handler.createPossibleValuesString()); - handler.addTag("apple"); - CPPUNIT_ASSERT_EQUAL(std::string("apple"), handler.toTagString()); - handler.addTag("orange"); - CPPUNIT_ASSERT_EQUAL(std::string("apple, orange"), handler.toTagString()); - CPPUNIT_ASSERT(handler.hasTag("apple")); - CPPUNIT_ASSERT(handler.hasTag("orange")); - CPPUNIT_ASSERT(!handler.hasTag("pineapple")); + handler.addTag(TAG_ADVANCED); + CPPUNIT_ASSERT_EQUAL(std::string("#advanced"), handler.toTagString()); + handler.addTag(TAG_BASIC); + CPPUNIT_ASSERT_EQUAL(std::string("#basic, #advanced"), handler.toTagString()); + CPPUNIT_ASSERT(handler.hasTag(TAG_ADVANCED)); + CPPUNIT_ASSERT(handler.hasTag(TAG_BASIC)); + CPPUNIT_ASSERT(!handler.hasTag(TAG_HTTP)); } void OptionHandlerTest::testFloatNumberOptionHandler() diff --git a/test/OptionParserTest.cc b/test/OptionParserTest.cc index 727432f0..f8c07985 100644 --- a/test/OptionParserTest.cc +++ b/test/OptionParserTest.cc @@ -11,6 +11,7 @@ #include "Option.h" #include "array_fun.h" #include "prefs.h" +#include "help_tags.h" namespace aria2 { @@ -37,28 +38,28 @@ public: SharedHandle timeout (new DefaultOptionHandler(PREF_TIMEOUT, NO_DESCRIPTION, "ALPHA", "", OptionHandler::REQ_ARG, 'A')); - timeout->addTag("apple"); + timeout->addTag(TAG_BASIC); timeout->setEraseAfterParse(true); oparser_->addOptionHandler(timeout); SharedHandle dir(new DefaultOptionHandler(PREF_DIR)); - dir->addTag("apple"); - dir->addTag("orange"); - dir->addTag("pineapple"); + dir->addTag(TAG_BASIC); + dir->addTag(TAG_HTTP); + dir->addTag(TAG_FILE); oparser_->addOptionHandler(dir); SharedHandle daemon (new DefaultOptionHandler(PREF_DAEMON, NO_DESCRIPTION, "CHARLIE", "", OptionHandler::REQ_ARG, 'C')); daemon->hide(); - daemon->addTag("pineapple"); + daemon->addTag(TAG_FILE); oparser_->addOptionHandler(daemon); SharedHandle out (new UnitNumberOptionHandler(PREF_OUT, NO_DESCRIPTION, "1M", -1, -1, 'D')); - out->addTag("pineapple"); - oparser_->addOptionHandler(out); + out->addTag(TAG_FILE); + oparser_->addOptionHandler(out); } void tearDown() {} @@ -98,7 +99,7 @@ void OptionParserTest::testFindByNameSubstring() void OptionParserTest::testFindByTag() { std::vector > res = - oparser_->findByTag("pineapple"); + oparser_->findByTag(TAG_FILE); CPPUNIT_ASSERT_EQUAL((size_t)2, res.size()); CPPUNIT_ASSERT_EQUAL(std::string("dir"), std::string(res[0]->getName())); CPPUNIT_ASSERT_EQUAL(std::string("out"), std::string(res[1]->getName()));