1// compat.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//
16// \file
17// Google compatibility declarations and inline definitions.
18
19#ifndef FST_COMPAT_H__
20#define FST_COMPAT_H__
21
22// for STL
23#include <cassert>
24#include <cstdio>
25#include <iostream>
26#include <map>
27#include <string>
28#include <vector>
29
30#include <fcntl.h>
31#include <pthread.h>
32#include <stdlib.h>
33#include <sys/stat.h>
34#include <sys/types.h>
35#include <unistd.h>
36
37// exact size types
38typedef short int16;
39typedef int int32;
40typedef long long int64;
41
42typedef unsigned short uint16;
43typedef unsigned int uint32;
44typedef unsigned long long uint64;
45
46using namespace std;
47
48// make copy constructor and operator= private
49#define DISALLOW_EVIL_CONSTRUCTORS(type)    \
50  type(const type&);                        \
51  void operator=(const type&)
52
53// thread control
54class Mutex {
55 public:
56  Mutex();
57
58 private:
59  DISALLOW_EVIL_CONSTRUCTORS(Mutex);
60};
61
62class MutexLock {
63 public:
64  MutexLock(Mutex *);
65
66 private:
67  DISALLOW_EVIL_CONSTRUCTORS(MutexLock);
68};
69
70
71// flags
72#define DECLARE_bool(name) extern bool FLAGS_ ## name
73#define DECLARE_string(name) extern string FLAGS_ ## name
74#define DECLARE_int32(name) extern int32 FLAGS_ ## name
75#define DECLARE_int64(name) extern int64 FLAGS_ ## name
76#define DECLARE_double(name) extern double FLAGS_ ## name
77
78template <typename T>
79struct FlagDescription {
80  FlagDescription(T *addr, const char *doc, const char *type, const T val)
81      : address(addr), doc_string(doc), type_name(type), default_value(val) {}
82
83  T *address;
84  const char *doc_string;
85  const char *type_name;
86  const T default_value;
87};
88
89template <typename T>
90class FlagRegister {
91 public:
92  static FlagRegister<T> *GetRegister() {
93    pthread_once(&register_init_, &FlagRegister<T>::Init);
94    return register_;
95  }
96
97  const FlagDescription<T> &GetFlagDescription(const string &name) const {
98    MutexLock l(register_lock_);
99    typename map< string, FlagDescription<T> >::const_iterator it =
100      flag_table_.find(name);
101    return it != flag_table_.end() ? it->second : 0;
102  }
103  void SetDescription(const string &name, const FlagDescription<T> &desc) {
104    MutexLock l(register_lock_);
105    flag_table_.insert(make_pair(name, desc));
106  }
107
108  bool SetFlag(const string &val, bool *address) const {
109    if (val == "true" || val == "1" || val.empty()) {
110      *address = true;
111      return true;
112    } else if (val == "false" || val == "0") {
113      *address = false;
114      return true;
115    }
116    else {
117      return false;
118    }
119  }
120  bool SetFlag(const string &val, string *address) const {
121    *address = val;
122    return true;
123  }
124  bool SetFlag(const string &val, int32 *address) const {
125    char *p = 0;
126    *address = strtol(val.c_str(), &p, 0);
127    return !val.empty() && *p == '\0';
128  }
129  bool SetFlag(const string &val, int64 *address) const {
130    char *p = 0;
131    *address = strtoll(val.c_str(), &p, 0);
132    return !val.empty() && *p == '\0';
133  }
134  bool SetFlag(const string &val, double *address) const {
135    char *p = 0;
136    *address = strtod(val.c_str(), &p);
137    return !val.empty() && *p == '\0';
138  }
139
140  bool InitFlag(const string &arg, const string &val) const {
141    for (typename map< string, FlagDescription<T> >::const_iterator it =
142           flag_table_.begin();
143         it != flag_table_.end();
144         ++it) {
145      const string &name = it->first;
146      const FlagDescription<T> &desc = it->second;
147      if (arg == name)
148        return SetFlag(val, desc.address);
149    }
150    return false;
151  }
152
153  void ShowDefault(bool default_value) const {
154    std::cout << ", default = ";
155    std::cout << (default_value ? "true" : "false");
156  }
157  void ShowDefault(const string &default_value) const {
158    std::cout << ", default = ";
159    std::cout << "\"" << default_value << "\"";
160  }
161  template<typename V> void ShowDefault(const V& default_value) const {
162    std::cout << ", default = ";
163    std::cout << default_value;
164  }
165  void ShowUsage() const {
166    for (typename map< string, FlagDescription<T> >::const_iterator it =
167           flag_table_.begin();
168         it != flag_table_.end();
169         ++it) {
170      const string &name = it->first;
171      const FlagDescription<T> &desc = it->second;
172      std::cout << "    --" << name
173           << ": type = " << desc.type_name;
174      ShowDefault(desc.default_value);
175      std::cout << "\n      " << desc.doc_string  << "\n";
176    }
177  }
178
179 private:
180  static void Init() {
181    register_lock_ = new Mutex;
182    register_ = new FlagRegister<T>;
183  }
184  static pthread_once_t register_init_;   // ensures only called once
185  static Mutex* register_lock_;           // multithreading lock
186  static FlagRegister<T> *register_;
187
188  map< string, FlagDescription<T> > flag_table_;
189};
190
191template <class T>
192pthread_once_t FlagRegister<T>::register_init_ = PTHREAD_ONCE_INIT;
193
194template <class T>
195Mutex *FlagRegister<T>::register_lock_ = 0;
196
197template <class T>
198FlagRegister<T> *FlagRegister<T>::register_ = 0;
199
200
201template <typename T>
202class FlagRegisterer {
203 public:
204  FlagRegisterer(const string &name, const FlagDescription<T> &desc) {
205    FlagRegister<T> *registr = FlagRegister<T>::GetRegister();
206    registr->SetDescription(name, desc);
207  }
208
209 private:
210  DISALLOW_EVIL_CONSTRUCTORS(FlagRegisterer);
211};
212
213
214#define DEFINE_VAR(type, name, value, doc)                                \
215  type FLAGS_ ## name = value;                                            \
216  static FlagRegisterer<type>                                             \
217  name ## _flags_registerer(#name, FlagDescription<type>(&FLAGS_ ## name, \
218                                                         doc,             \
219                                                         #type,           \
220                                                         value))
221
222#define DEFINE_bool(name, value, doc) DEFINE_VAR(bool, name, value, doc)
223#define DEFINE_string(name, value, doc) DEFINE_VAR(string, name, value, doc)
224#define DEFINE_int32(name, value, doc) DEFINE_VAR(int32, name, value, doc)
225#define DEFINE_int64(name, value, doc) DEFINE_VAR(int64, name, value, doc)
226#define DEFINE_double(name, value, doc) DEFINE_VAR(double, name, value, doc)
227
228void InitFst(const char *usage, int *argc, char ***argv, bool remove_flags);
229
230void ShowUsage();
231
232
233// checking
234#define CHECK(x) assert(x)
235#define CHECK_EQ(x, y) assert((x) == (y))
236
237// logging
238DECLARE_int32(v);
239
240// tmp directory
241DECLARE_string(tmpdir);
242
243class LogMessage {
244 public:
245  LogMessage(const string &type) : fatal_(type == "FATAL") {
246    std::cerr << type << ": ";
247  }
248  ~LogMessage() {
249    std::cerr << endl;
250    if(fatal_)
251      exit(1);
252  }
253  ostream &stream() { return std::cerr; }
254
255 private:
256  bool fatal_;
257};
258
259#define LOG(type) LogMessage(#type).stream()
260#define VLOG(level) if ((level) <= FLAGS_v) LOG(INFO)
261
262
263// string utilities
264void SplitToVector(char *line, const char *delim,
265                   vector<char *> *vec, bool omit_empty_strings);
266
267// Downcasting
268template<typename To, typename From>
269inline To down_cast(From* f) {
270  return static_cast<To>(f);
271}
272
273// Bitcasting
274template <class Dest, class Source>
275inline Dest bit_cast(const Source& source) {
276  // Compile time assertion: sizeof(Dest) == sizeof(Source)
277  // A compile error here means your Dest and Source have different sizes.
278  typedef char VerifySizesAreEqual [sizeof(Dest) == sizeof(Source) ? 1 :
279                                    -1];
280  Dest dest;
281  memcpy(&dest, &source, sizeof(dest));
282  return dest;
283}
284
285// MD5 checksums
286class MD5 {
287 public:
288  MD5();
289  void Reset();
290  void Update(void const *data, int size);
291  string Digest();
292
293 private:
294  DISALLOW_EVIL_CONSTRUCTORS(MD5);
295};
296
297#endif  // FST_COMPAT_H__
298