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 (at) 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 30 using 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 57 template <typename T> 58 struct 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 68 template <typename T> 69 class 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 173 template <class T> 174 fst::FstOnceType FlagRegister<T>::register_init_ = fst::FST_ONCE_INIT; 175 176 template <class T> 177 fst::Mutex *FlagRegister<T>::register_lock_ = 0; 178 179 template <class T> 180 FlagRegister<T> *FlagRegister<T>::register_ = 0; 181 182 183 template <typename T> 184 class 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 213 DECLARE_string(tmpdir); 214 215 void SetFlags(const char *usage, int *argc, char ***argv, bool remove_flags); 216 217 // Deprecated - for backward compatibility 218 inline void InitFst(const char *usage, int *argc, char ***argv, bool rmflags) { 219 return SetFlags(usage, argc, argv, rmflags); 220 } 221 222 void ShowUsage(); 223 224 #endif // FST_LIB_FLAGS_H__ 225