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 <set> 26 #include <sstream> 27 #include <string> 28 29 #include <fst/types.h> 30 #include <fst/lock.h> 31 32 using std::string; 33 34 // 35 // FLAGS USAGE: 36 // 37 // Definition example: 38 // 39 // DEFINE_int32(length, 0, "length"); 40 // 41 // This defines variable FLAGS_length, initialized to 0. 42 // 43 // Declaration example: 44 // 45 // DECLARE_int32(length); 46 // 47 // SET_FLAGS() can be used to set flags from the command line 48 // using, for example, '--length=2'. 49 // 50 // ShowUsage() can be used to print out command and flag usage. 51 // 52 53 #define DECLARE_bool(name) extern bool FLAGS_ ## name 54 #define DECLARE_string(name) extern string FLAGS_ ## name 55 #define DECLARE_int32(name) extern int32 FLAGS_ ## name 56 #define DECLARE_int64(name) extern int64 FLAGS_ ## name 57 #define DECLARE_double(name) extern double FLAGS_ ## name 58 59 template <typename T> 60 struct FlagDescription { 61 FlagDescription(T *addr, const char *doc, const char *type, 62 const char *file, const T val) 63 : address(addr), 64 doc_string(doc), 65 type_name(type), 66 file_name(file), 67 default_value(val) {} 68 69 T *address; 70 const char *doc_string; 71 const char *type_name; 72 const char *file_name; 73 const T default_value; 74 }; 75 76 template <typename T> 77 class FlagRegister { 78 public: 79 static FlagRegister<T> *GetRegister() { 80 fst::FstOnceInit(®ister_init_, &FlagRegister<T>::Init); 81 return register_; 82 } 83 84 const FlagDescription<T> &GetFlagDescription(const string &name) const { 85 fst::MutexLock l(register_lock_); 86 typename std::map< string, FlagDescription<T> >::const_iterator it = 87 flag_table_.find(name); 88 return it != flag_table_.end() ? it->second : 0; 89 } 90 void SetDescription(const string &name, 91 const FlagDescription<T> &desc) { 92 fst::MutexLock l(register_lock_); 93 flag_table_.insert(make_pair(name, desc)); 94 } 95 96 bool SetFlag(const string &val, bool *address) const { 97 if (val == "true" || val == "1" || val.empty()) { 98 *address = true; 99 return true; 100 } else if (val == "false" || val == "0") { 101 *address = false; 102 return true; 103 } 104 else { 105 return false; 106 } 107 } 108 bool SetFlag(const string &val, string *address) const { 109 *address = val; 110 return true; 111 } 112 bool SetFlag(const string &val, int32 *address) const { 113 char *p = 0; 114 *address = strtol(val.c_str(), &p, 0); 115 return !val.empty() && *p == '\0'; 116 } 117 bool SetFlag(const string &val, int64 *address) const { 118 char *p = 0; 119 *address = strtoll(val.c_str(), &p, 0); 120 return !val.empty() && *p == '\0'; 121 } 122 bool SetFlag(const string &val, double *address) const { 123 char *p = 0; 124 *address = strtod(val.c_str(), &p); 125 return !val.empty() && *p == '\0'; 126 } 127 128 bool SetFlag(const string &arg, const string &val) const { 129 for (typename std::map< string, FlagDescription<T> >::const_iterator it = 130 flag_table_.begin(); 131 it != flag_table_.end(); 132 ++it) { 133 const string &name = it->first; 134 const FlagDescription<T> &desc = it->second; 135 if (arg == name) 136 return SetFlag(val, desc.address); 137 } 138 return false; 139 } 140 141 void GetUsage(std::set< std::pair<string, string> > *usage_set) const { 142 for (typename std::map< string, 143 FlagDescription<T> >::const_iterator it = 144 flag_table_.begin(); 145 it != flag_table_.end(); 146 ++it) { 147 const string &name = it->first; 148 const FlagDescription<T> &desc = it->second; 149 string usage = " --" + name; 150 usage += ": type = "; 151 usage += desc.type_name; 152 usage += ", default = "; 153 usage += GetDefault(desc.default_value) + "\n "; 154 usage += desc.doc_string; 155 usage_set->insert(make_pair(desc.file_name, usage)); 156 } 157 } 158 159 private: 160 static void Init() { 161 register_lock_ = new fst::Mutex; 162 register_ = new FlagRegister<T>; 163 } 164 165 std::map< string, FlagDescription<T> > flag_table_; 166 167 string GetDefault(bool default_value) const { 168 return default_value ? "true" : "false"; 169 } 170 171 string GetDefault(const string &default_value) const { 172 return "\"" + default_value + "\""; 173 } 174 175 template<typename V> string GetDefault(const V& default_value) const { 176 std::ostringstream strm; 177 strm << default_value; 178 return strm.str(); 179 } 180 181 static fst::FstOnceType register_init_; // ensures only called once 182 static fst::Mutex* register_lock_; // multithreading lock 183 static FlagRegister<T> *register_; 184 }; 185 186 template <class T> 187 fst::FstOnceType FlagRegister<T>::register_init_ = fst::FST_ONCE_INIT; 188 189 template <class T> 190 fst::Mutex *FlagRegister<T>::register_lock_ = 0; 191 192 template <class T> 193 FlagRegister<T> *FlagRegister<T>::register_ = 0; 194 195 196 template <typename T> 197 class FlagRegisterer { 198 public: 199 FlagRegisterer(const string &name, const FlagDescription<T> &desc) { 200 FlagRegister<T> *registr = FlagRegister<T>::GetRegister(); 201 registr->SetDescription(name, desc); 202 } 203 204 private: 205 DISALLOW_COPY_AND_ASSIGN(FlagRegisterer); 206 }; 207 208 209 #define DEFINE_VAR(type, name, value, doc) \ 210 type FLAGS_ ## name = value; \ 211 static FlagRegisterer<type> \ 212 name ## _flags_registerer(#name, FlagDescription<type>(&FLAGS_ ## name, \ 213 doc, \ 214 #type, \ 215 __FILE__, \ 216 value)) 217 218 #define DEFINE_bool(name, value, doc) DEFINE_VAR(bool, name, value, doc) 219 #define DEFINE_string(name, value, doc) \ 220 DEFINE_VAR(string, name, value, doc) 221 #define DEFINE_int32(name, value, doc) DEFINE_VAR(int32, name, value, doc) 222 #define DEFINE_int64(name, value, doc) DEFINE_VAR(int64, name, value, doc) 223 #define DEFINE_double(name, value, doc) DEFINE_VAR(double, name, value, doc) 224 225 226 // Temporary directory 227 DECLARE_string(tmpdir); 228 229 void SetFlags(const char *usage, int *argc, char ***argv, bool remove_flags, 230 const char *src = ""); 231 232 #define SET_FLAGS(usage, argc, argv, rmflags) \ 233 SetFlags(usage, argc, argv, rmflags, __FILE__) 234 235 // Deprecated - for backward compatibility 236 inline void InitFst(const char *usage, int *argc, char ***argv, bool rmflags) { 237 return SetFlags(usage, argc, argv, rmflags); 238 } 239 240 void ShowUsage(bool long_usage = true); 241 242 #endif // FST_LIB_FLAGS_H__ 243