• 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 <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 {
FlagDescriptionFlagDescription59   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:
GetRegister()71   static FlagRegister<T> *GetRegister() {
72     fst::FstOnceInit(&register_init_, &FlagRegister<T>::Init);
73     return register_;
74   }
75 
GetFlagDescription(const string & name)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   }
SetDescription(const string & name,const FlagDescription<T> & desc)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 
SetFlag(const string & val,bool * address)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   }
SetFlag(const string & val,string * address)100   bool SetFlag(const string &val, string *address) const {
101     *address = val;
102     return true;
103   }
SetFlag(const string & val,int32 * address)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   }
SetFlag(const string & val,int64 * address)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   }
SetFlag(const string & val,double * address)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 
SetFlag(const string & arg,const string & val)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 
ShowDefault(bool default_value)134   void ShowDefault(bool default_value) const {
135     std::cout << ", default = ";
136     std::cout << (default_value ? "true" : "false");
137   }
ShowDefault(const string & default_value)138   void ShowDefault(const string &default_value) const {
139     std::cout << ", default = ";
140     std::cout << "\"" << default_value << "\"";
141   }
ShowDefault(const V & default_value)142   template<typename V> void ShowDefault(const V& default_value) const {
143     std::cout << ", default = ";
144     std::cout << default_value;
145   }
ShowUsage()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:
Init()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:
FlagRegisterer(const string & name,const FlagDescription<T> & desc)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
InitFst(const char * usage,int * argc,char *** argv,bool rmflags)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