• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 <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 {
FlagDescriptionFlagDescription61   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:
GetRegister()79   static FlagRegister<T> *GetRegister() {
80     fst::FstOnceInit(&register_init_, &FlagRegister<T>::Init);
81     return register_;
82   }
83 
GetFlagDescription(const string & name)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   }
SetDescription(const string & name,const FlagDescription<T> & desc)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 
SetFlag(const string & val,bool * address)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   }
SetFlag(const string & val,string * address)108   bool SetFlag(const string &val, string *address) const {
109     *address = val;
110     return true;
111   }
SetFlag(const string & val,int32 * address)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   }
SetFlag(const string & val,int64 * address)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   }
SetFlag(const string & val,double * address)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 
SetFlag(const string & arg,const string & val)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 
GetUsage(std::set<std::pair<string,string>> * usage_set)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:
Init()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 
GetDefault(bool default_value)167   string GetDefault(bool default_value) const {
168     return default_value ? "true" : "false";
169   }
170 
GetDefault(const string & default_value)171   string GetDefault(const string &default_value) const {
172     return "\"" + default_value + "\"";
173   }
174 
GetDefault(const V & default_value)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:
FlagRegisterer(const string & name,const FlagDescription<T> & desc)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
InitFst(const char * usage,int * argc,char *** argv,bool rmflags)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