diff options
author | Taku Kudo <taku@google.com> | 2017-03-07 13:43:50 +0300 |
---|---|---|
committer | Taku Kudo <taku@google.com> | 2017-03-07 13:43:50 +0300 |
commit | 2928ce5307224ea4c012fc6cbd7a098c486590b6 (patch) | |
tree | 38b679886855a7a6b80fdc61f2f62c952cf3bfb7 /src/flags.cc |
Initialize repository
Diffstat (limited to 'src/flags.cc')
-rw-r--r-- | src/flags.cc | 238 |
1 files changed, 238 insertions, 0 deletions
diff --git a/src/flags.cc b/src/flags.cc new file mode 100644 index 0000000..bdc4571 --- /dev/null +++ b/src/flags.cc @@ -0,0 +1,238 @@ +// Copyright 2016 Google Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License.! + +#include "flags.h" +#include "common.h" + +#include <algorithm> +#include <cctype> +#include <iostream> +#include <map> +#include <sstream> +#include <string> + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +namespace sentencepiece { +namespace flags { + +struct Flag { + int type; + void *storage; + const void *default_storage; + std::string help; +}; + +namespace { +using FlagMap = std::map<std::string, Flag *>; + +FlagMap *GetFlagMap() { + static FlagMap flag_map; + return &flag_map; +} + +bool IsTrue(const std::string &value) { + const char *kTrue[] = {"1", "t", "true", "y", "yes"}; + const char *kFalse[] = {"0", "f", "false", "n", "no"}; + std::string lower_value = value; + std::transform(lower_value.begin(), lower_value.end(), lower_value.begin(), + ::tolower); + for (size_t i = 0; i < 5; ++i) { + if (lower_value == kTrue[i]) { + return true; + } else if (lower_value == kFalse[i]) { + return false; + } + } + LOG(FATAL) << "cannot parse boolean value: " << value; + return false; +} + +bool SetFlag(const std::string &name, const std::string &value) { + auto it = GetFlagMap()->find(name); + if (it == GetFlagMap()->end()) { + return false; + } + + std::string v = value; + Flag *flag = it->second; + + // If empty value is set, we assume true or emtpy string is set + // for boolean or string option. With other types, setting fails. + if (value.empty()) { + switch (flag->type) { + case B: + v = "true"; + break; + case S: + v = ""; + break; + default: + return false; + } + } + + switch (flag->type) { + case I: + *reinterpret_cast<int32 *>(flag->storage) = atoi(v.c_str()); + break; + case B: + *(reinterpret_cast<bool *>(flag->storage)) = IsTrue(v); + break; + case I64: + *reinterpret_cast<int64 *>(flag->storage) = atoll(v.c_str()); + break; + case U64: + *reinterpret_cast<uint64 *>(flag->storage) = atoll(v.c_str()); + break; + case D: + *reinterpret_cast<double *>(flag->storage) = strtod(v.c_str(), nullptr); + break; + case S: + *reinterpret_cast<std::string *>(flag->storage) = v; + break; + default: + break; + } + + return true; +} + +bool CommandLineGetFlag(int argc, char **argv, std::string *key, + std::string *value, int *used_args) { + key->clear(); + value->clear(); + + *used_args = 1; + const char *start = argv[0]; + if (start[0] != '-') { + return false; + } + + ++start; + if (start[0] == '-') ++start; + const std::string arg = start; + const size_t n = arg.find("="); + if (n != std::string::npos) { + *key = arg.substr(0, n); + *value = arg.substr(n + 1, arg.size() - n); + return true; + } + + key->assign(arg); + value->clear(); + + if (argc == 1) { + return true; + } + start = argv[1]; + if (start[0] == '-') { + return true; + } + + *used_args = 2; + value->assign(start); + return true; +} +} // namespace + +FlagRegister::FlagRegister(const char *name, void *storage, + const void *default_storage, int shortype, + const char *help) + : flag_(new Flag) { + flag_->type = shortype; + flag_->storage = storage; + flag_->default_storage = default_storage; + flag_->help = help; + GetFlagMap()->insert(std::make_pair(std::string(name), flag_.get())); +} + +FlagRegister::~FlagRegister() {} + +std::string PrintHelp(const char *programname) { + std::ostringstream os; + os << PACKAGE_STRING << "\n\n"; + os << "Usage: " << programname << " [options] files\n\n"; + + for (const auto &it : *GetFlagMap()) { + os << " --" << it.first << " (" << it.second->help << ")"; + const Flag *flag = it.second; + switch (flag->type) { + case I: + os << " type: int32 default: " + << *(reinterpret_cast<const int *>(flag->default_storage)) << '\n'; + break; + case B: + os << " type: bool default: " + << (*(reinterpret_cast<const bool *>(flag->default_storage)) + ? "true" + : "false") + << '\n'; + break; + case I64: + os << " type: int64 default: " + << *(reinterpret_cast<const int64 *>(flag->default_storage)) << '\n'; + break; + case U64: + os << " type: uint64 default: " + << *(reinterpret_cast<const uint64 *>(flag->default_storage)) + << '\n'; + break; + case D: + os << " type: double default: " + << *(reinterpret_cast<const double *>(flag->default_storage)) + << '\n'; + break; + case S: + os << " type: string default: " + << *(reinterpret_cast<const std::string *>(flag->default_storage)) + << '\n'; + break; + default: + break; + } + } + + os << "\n\n"; + + return os.str(); +} + +void ParseCommandLineFlags(int argc, char **argv, + std::vector<std::string> *rest_flags) { + int used_argc = 0; + std::string key, value; + + for (int i = 1; i < argc; i += used_argc) { + if (!CommandLineGetFlag(argc - i, argv + i, &key, &value, &used_argc)) { + if (rest_flags) rest_flags->push_back(std::string(argv[i])); + continue; + } + if (key == "help") { + std::cout << PrintHelp(argv[0]); + error::Exit(0); + } else if (key == "version") { + std::cout << PACKAGE_STRING << " " << VERSION << std::endl; + error::Exit(0); + } else if (!SetFlag(key, value)) { + std::cerr << "Unknown/Invalid flag " << key << "\n\n" + << PrintHelp(argv[0]); + error::Exit(1); + } + } +} +} // namespace flags +} // namespace sentencepiece |