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