Home | History | Annotate | Download | only in fst
      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(&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 
    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