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 <ext/hash_map>
31 #include <fcntl.h>
32 #include <pthread.h>
33 #include <sys/stat.h>
34 #include <sys/types.h>
35 #include <unistd.h>
36
37 // exact size types
38 typedef short int16;
39 typedef int int32;
40 typedef long long int64;
41
42 typedef unsigned short uint16;
43 typedef unsigned int uint32;
44 typedef unsigned long long uint64;
45
46 using 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
54 class Mutex {
55 public:
56 Mutex();
57
58 private:
59 DISALLOW_EVIL_CONSTRUCTORS(Mutex);
60 };
61
62 class 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
78 template <typename T>
79 struct FlagDescription {
FlagDescriptionFlagDescription80 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
89 template <typename T>
90 class FlagRegister {
91 public:
GetRegister()92 static FlagRegister<T> *GetRegister() {
93 pthread_once(®ister_init_, &FlagRegister<T>::Init);
94 return register_;
95 }
96
GetFlagDescription(const string & name)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 }
SetDescription(const string & name,const FlagDescription<T> & desc)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
SetFlag(const string & val,bool * address)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 }
SetFlag(const string & val,string * address)120 bool SetFlag(const string &val, string *address) const {
121 *address = val;
122 return true;
123 }
SetFlag(const string & val,int32 * address)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 }
SetFlag(const string & val,int64 * address)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 }
SetFlag(const string & val,double * address)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
InitFlag(const string & arg,const string & val)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
ShowDefault(bool default_value)153 void ShowDefault(bool default_value) const {
154 std::cout << ", default = ";
155 std::cout << (default_value ? "true" : "false");
156 }
ShowDefault(const string & default_value)157 void ShowDefault(const string &default_value) const {
158 std::cout << ", default = ";
159 std::cout << "\"" << default_value << "\"";
160 }
ShowDefault(const V & default_value)161 template<typename V> void ShowDefault(const V& default_value) const {
162 std::cout << ", default = ";
163 std::cout << default_value;
164 }
ShowUsage()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:
Init()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
191 template <class T>
192 pthread_once_t FlagRegister<T>::register_init_ = PTHREAD_ONCE_INIT;
193
194 template <class T>
195 Mutex *FlagRegister<T>::register_lock_ = 0;
196
197 template <class T>
198 FlagRegister<T> *FlagRegister<T>::register_ = 0;
199
200
201 template <typename T>
202 class FlagRegisterer {
203 public:
FlagRegisterer(const string & name,const FlagDescription<T> & desc)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
228 void InitFst(const char *usage, int *argc, char ***argv, bool remove_flags);
229
230 void ShowUsage();
231
232
233 // checking
234 #define CHECK(x) assert(x)
235 #define CHECK_EQ(x, y) assert((x) == (y))
236
237 // logging
238 DECLARE_int32(v);
239
240 // tmp directory
241 DECLARE_string(tmpdir);
242
243 class LogMessage {
244 public:
LogMessage(const string & type)245 LogMessage(const string &type) : fatal_(type == "FATAL") {
246 std::cerr << type << ": ";
247 }
~LogMessage()248 ~LogMessage() {
249 std::cerr << endl;
250 if(fatal_)
251 exit(1);
252 }
stream()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
264 void SplitToVector(char *line, const char *delim,
265 vector<char *> *vec, bool omit_empty_strings);
266
267 // Downcasting
268 template<typename To, typename From>
down_cast(From * f)269 inline To down_cast(From* f) {
270 return static_cast<To>(f);
271 }
272
273 // Bitcasting
274 template <class Dest, class Source>
bit_cast(const Source & source)275 inline 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
286 class 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 // Hashing functions
298 namespace __gnu_cxx {
299
300 template<> struct hash<int64> {
301 size_t operator()(int64 x) const {
302 return x;
303 }
304 };
305
306 template<> struct hash<string> {
307 size_t operator()(const string &s) const {
308 return __stl_hash_string(s.c_str());
309 }
310 };
311
312 } // namespace __gnu_cxx
313
314 #endif // FST_COMPAT_H__
315