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(&register_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