flags.h revision f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2
1// flags.h 2// 3// Licensed under the Apache License, Version 2.0 (the "License"); 4// you may not use this file except in compliance with the License. 5// You may obtain a copy of the License at 6// 7// http://www.apache.org/licenses/LICENSE-2.0 8// 9// Unless required by applicable law or agreed to in writing, software 10// distributed under the License is distributed on an "AS IS" BASIS, 11// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12// See the License for the specific language governing permissions and 13// limitations under the License. 14// 15// Author: riley@google.com (Michael Riley) 16// 17// \file 18// Google-style flag handling declarations and inline definitions. 19 20#ifndef FST_LIB_FLAGS_H__ 21#define FST_LIB_FLAGS_H__ 22 23#include <iostream> 24#include <map> 25#include <string> 26 27#include <fst/types.h> 28#include <fst/lock.h> 29 30using std::string; 31 32// 33// FLAGS USAGE: 34// 35// Definition example: 36// 37// DEFINE_int32(length, 0, "length"); 38// 39// This defines variable FLAGS_length, initialized to 0. 40// 41// Declaration example: 42// 43// DECLARE_int32(length); 44// 45// SetFlags() can be used to set flags from the command line 46// using, for example, '--length=2'. 47// 48// ShowUsage() can be used to print out command and flag usage. 49// 50 51#define DECLARE_bool(name) extern bool FLAGS_ ## name 52#define DECLARE_string(name) extern string FLAGS_ ## name 53#define DECLARE_int32(name) extern int32 FLAGS_ ## name 54#define DECLARE_int64(name) extern int64 FLAGS_ ## name 55#define DECLARE_double(name) extern double FLAGS_ ## name 56 57template <typename T> 58struct FlagDescription { 59 FlagDescription(T *addr, const char *doc, const char *type, const T val) 60 : address(addr), doc_string(doc), type_name(type), default_value(val) {} 61 62 T *address; 63 const char *doc_string; 64 const char *type_name; 65 const T default_value; 66}; 67 68template <typename T> 69class FlagRegister { 70 public: 71 static FlagRegister<T> *GetRegister() { 72 fst::FstOnceInit(®ister_init_, &FlagRegister<T>::Init); 73 return register_; 74 } 75 76 const FlagDescription<T> &GetFlagDescription(const string &name) const { 77 fst::MutexLock l(register_lock_); 78 typename std::map< string, FlagDescription<T> >::const_iterator it = 79 flag_table_.find(name); 80 return it != flag_table_.end() ? it->second : 0; 81 } 82 void SetDescription(const string &name, 83 const FlagDescription<T> &desc) { 84 fst::MutexLock l(register_lock_); 85 flag_table_.insert(make_pair(name, desc)); 86 } 87 88 bool SetFlag(const string &val, bool *address) const { 89 if (val == "true" || val == "1" || val.empty()) { 90 *address = true; 91 return true; 92 } else if (val == "false" || val == "0") { 93 *address = false; 94 return true; 95 } 96 else { 97 return false; 98 } 99 } 100 bool SetFlag(const string &val, string *address) const { 101 *address = val; 102 return true; 103 } 104 bool SetFlag(const string &val, int32 *address) const { 105 char *p = 0; 106 *address = strtol(val.c_str(), &p, 0); 107 return !val.empty() && *p == '\0'; 108 } 109 bool SetFlag(const string &val, int64 *address) const { 110 char *p = 0; 111 *address = strtoll(val.c_str(), &p, 0); 112 return !val.empty() && *p == '\0'; 113 } 114 bool SetFlag(const string &val, double *address) const { 115 char *p = 0; 116 *address = strtod(val.c_str(), &p); 117 return !val.empty() && *p == '\0'; 118 } 119 120 bool SetFlag(const string &arg, const string &val) const { 121 for (typename std::map< string, 122 FlagDescription<T> >::const_iterator it = 123 flag_table_.begin(); 124 it != flag_table_.end(); 125 ++it) { 126 const string &name = it->first; 127 const FlagDescription<T> &desc = it->second; 128 if (arg == name) 129 return SetFlag(val, desc.address); 130 } 131 return false; 132 } 133 134 void ShowDefault(bool default_value) const { 135 std::cout << ", default = "; 136 std::cout << (default_value ? "true" : "false"); 137 } 138 void ShowDefault(const string &default_value) const { 139 std::cout << ", default = "; 140 std::cout << "\"" << default_value << "\""; 141 } 142 template<typename V> void ShowDefault(const V& default_value) const { 143 std::cout << ", default = "; 144 std::cout << default_value; 145 } 146 void ShowUsage() const { 147 for (typename std::map< string, 148 FlagDescription<T> >::const_iterator it = 149 flag_table_.begin(); 150 it != flag_table_.end(); 151 ++it) { 152 const string &name = it->first; 153 const FlagDescription<T> &desc = it->second; 154 std::cout << " --" << name 155 << ": type = " << desc.type_name; 156 ShowDefault(desc.default_value); 157 std::cout << "\n " << desc.doc_string << "\n"; 158 } 159 } 160 161 private: 162 static void Init() { 163 register_lock_ = new fst::Mutex; 164 register_ = new FlagRegister<T>; 165 } 166 static fst::FstOnceType register_init_; // ensures only called once 167 static fst::Mutex* register_lock_; // multithreading lock 168 static FlagRegister<T> *register_; 169 170 std::map< string, FlagDescription<T> > flag_table_; 171}; 172 173template <class T> 174fst::FstOnceType FlagRegister<T>::register_init_ = fst::FST_ONCE_INIT; 175 176template <class T> 177fst::Mutex *FlagRegister<T>::register_lock_ = 0; 178 179template <class T> 180FlagRegister<T> *FlagRegister<T>::register_ = 0; 181 182 183template <typename T> 184class FlagRegisterer { 185 public: 186 FlagRegisterer(const string &name, const FlagDescription<T> &desc) { 187 FlagRegister<T> *registr = FlagRegister<T>::GetRegister(); 188 registr->SetDescription(name, desc); 189 } 190 191 private: 192 DISALLOW_COPY_AND_ASSIGN(FlagRegisterer); 193}; 194 195 196#define DEFINE_VAR(type, name, value, doc) \ 197 type FLAGS_ ## name = value; \ 198 static FlagRegisterer<type> \ 199 name ## _flags_registerer(#name, FlagDescription<type>(&FLAGS_ ## name, \ 200 doc, \ 201 #type, \ 202 value)) 203 204#define DEFINE_bool(name, value, doc) DEFINE_VAR(bool, name, value, doc) 205#define DEFINE_string(name, value, doc) \ 206 DEFINE_VAR(string, name, value, doc) 207#define DEFINE_int32(name, value, doc) DEFINE_VAR(int32, name, value, doc) 208#define DEFINE_int64(name, value, doc) DEFINE_VAR(int64, name, value, doc) 209#define DEFINE_double(name, value, doc) DEFINE_VAR(double, name, value, doc) 210 211 212// Temporary directory 213DECLARE_string(tmpdir); 214 215void SetFlags(const char *usage, int *argc, char ***argv, bool remove_flags); 216 217// Deprecated - for backward compatibility 218inline void InitFst(const char *usage, int *argc, char ***argv, bool rmflags) { 219 return SetFlags(usage, argc, argv, rmflags); 220} 221 222void ShowUsage(); 223 224#endif // FST_LIB_FLAGS_H__ 225