Simple HPHP Changes for HPHP with Clang
[hiphop-php.git] / hphp / util / base.h
blob555244d88b98e2765ec0974515c6d4cfbc78d79a
1 /*
2 +----------------------------------------------------------------------+
3 | HipHop for PHP |
4 +----------------------------------------------------------------------+
5 | Copyright (c) 2010-2013 Facebook, Inc. (http://www.facebook.com) |
6 +----------------------------------------------------------------------+
7 | This source file is subject to version 3.01 of the PHP license, |
8 | that is bundled with this package in the file LICENSE, and is |
9 | available through the world-wide-web at the following url: |
10 | http://www.php.net/license/3_01.txt |
11 | If you did not receive a copy of the PHP license and are unable to |
12 | obtain it through the world-wide-web, please send a note to |
13 | license@php.net so we can mail you a copy immediately. |
14 +----------------------------------------------------------------------+
17 #ifndef incl_HPHP_BASE_H_
18 #define incl_HPHP_BASE_H_
20 #include <stdio.h>
21 #include <stdlib.h>
22 #include <stdarg.h>
23 #include <cinttypes>
25 #include <errno.h>
26 #include <string.h>
27 #include "hphp/runtime/base/strings.h"
28 #include <unistd.h>
29 #include <poll.h>
30 #include "netinet/in.h"
31 #include "arpa/inet.h"
32 #include <netdb.h>
33 #include <signal.h>
34 #include <fcntl.h>
36 #include <sys/time.h>
37 #include <sys/stat.h>
38 #include <sys/types.h>
39 #include <sys/resource.h>
40 #include <sys/utsname.h>
41 #include <sys/socket.h>
42 #include <sys/wait.h>
43 #include <sys/poll.h>
45 #include <fstream>
46 #include <iostream>
47 #include <sstream>
48 #include <vector>
49 #include <stack>
50 #include <string>
51 #include <map>
52 #include <list>
53 #include <set>
54 #include <deque>
55 #include <exception>
56 #include <tr1/functional>
58 #include <boost/shared_ptr.hpp>
59 #include <boost/enable_shared_from_this.hpp>
60 #include <boost/lexical_cast.hpp>
61 #include <boost/interprocess/sync/interprocess_upgradable_mutex.hpp>
62 #include <boost/foreach.hpp>
63 #include <boost/tuple/tuple.hpp>
64 #include <boost/filesystem/operations.hpp>
65 #include <boost/type_traits.hpp>
66 #include <boost/numeric/conversion/cast.hpp>
68 #include "hphp/util/hash.h"
69 #include "hphp/util/assertions.h"
71 #ifdef __INTEL_COMPILER
72 #define va_copy __builtin_va_copy
73 #endif
75 #if (__GNUC__ > 4) || ((__GNUC__ == 4) && (__GNUC_MINOR__ >= 4)) || \
76 __INTEL_COMPILER || defined(__clang__)
78 #include <tr1/unordered_map>
79 #include <tr1/unordered_set>
81 #define hphp_hash std::tr1::hash
82 namespace std {
83 namespace tr1 {
84 template<>
85 struct hash<const char*> {
86 size_t operator()(const char *s) const {
87 return HPHP::hash_string_cs(s, strlen(s));
93 namespace HPHP {
94 template <class _T,class _U,
95 class _V = hphp_hash<_T>,class _W = std::equal_to<_T> >
96 struct hphp_hash_map : std::tr1::unordered_map<_T,_U,_V,_W> {
97 hphp_hash_map() : std::tr1::unordered_map<_T,_U,_V,_W>(0) {}
100 template <class _T,
101 class _V = hphp_hash<_T>,class _W = std::equal_to<_T> >
102 struct hphp_hash_set : std::tr1::unordered_set<_T,_V,_W> {
103 hphp_hash_set() : std::tr1::unordered_set<_T,_V,_W>(0) {}
107 #else
109 #include <ext/hash_map>
110 #include <ext/hash_set>
112 #define hphp_hash_map __gnu_cxx::hash_map
113 #define hphp_hash_set __gnu_cxx::hash_set
114 #define hphp_hash __gnu_cxx::hash
116 #endif
118 namespace HPHP {
119 ///////////////////////////////////////////////////////////////////////////////
120 // debugging
122 const bool debug =
123 #ifdef DEBUG
124 true
125 #else
126 false
127 #endif
130 const bool use_jemalloc =
131 #ifdef USE_JEMALLOC
132 true
133 #else
134 false
135 #endif
138 const bool packed_tv =
139 #ifdef PACKED_TV
140 true
141 #else
142 false
143 #endif
147 * Guard bug-for-bug hphpi compatibility code with this predicate.
149 const bool hphpiCompat = true;
151 ///////////////////////////////////////////////////////////////////////////////
152 // system includes
154 #if __WORDSIZE == 64
155 #define WORDSIZE_IS_64
156 #endif
158 typedef unsigned char uchar;
160 #ifndef ULLONG_MAX
161 #define ULLONG_MAX 0xffffffffffffffffULL
162 #endif
164 ///////////////////////////////////////////////////////////////////////////////
165 // stl classes
167 struct ltstr {
168 bool operator()(const char *s1, const char *s2) const {
169 return strcmp(s1, s2) < 0;
173 struct eqstr {
174 bool operator()(const char* s1, const char* s2) const {
175 return strcmp(s1, s2) == 0;
179 struct stdltstr {
180 bool operator()(const std::string &s1, const std::string &s2) const {
181 return strcmp(s1.c_str(), s2.c_str()) < 0;
185 struct stdltistr {
186 bool operator()(const std::string &s1, const std::string &s2) const {
187 return strcasecmp(s1.c_str(), s2.c_str()) < 0;
191 struct string_hash {
192 size_t operator()(const std::string &s) const {
193 return hash_string_cs(s.c_str(), s.size());
195 size_t hash(const std::string &s) const {
196 return operator()(s);
200 struct stringHashCompare {
201 bool equal(const std::string &s1, const std::string &s2) const {
202 return s1 == s2;
204 size_t hash(const std::string &s) const {
205 return hash_string(s.c_str(), s.size());
209 template<class type, class T> struct hphp_string_hash_map :
210 public hphp_hash_map<std::string, type, string_hash> {
213 struct int64_hash {
214 size_t operator() (const int64_t v) const {
215 return (size_t)hash_int64(v);
217 size_t hash(const int64_t v) const {
218 return operator()(v);
220 bool equal(const int64_t lhs, const int64_t rhs) const {
221 return lhs == rhs;
225 template<typename T>
226 struct pointer_hash {
227 size_t operator() (const T *const p) const {
228 return (size_t)hash_int64(intptr_t(p));
230 size_t hash(const T *const p) const {
231 return operator()(p);
233 bool equal(const T *const lhs,
234 const T *const rhs) const {
235 return lhs == rhs;
239 template<typename T>
240 struct smart_pointer_hash {
241 size_t operator() (const T &p) const {
242 return (size_t)hash_int64(intptr_t(p.get()));
244 size_t hash (const T &p) const {
245 return operator()(p);
247 bool equal(const T &lhs, const T &rhs) const {
248 return lhs.get() == rhs.get();
252 template <class T> class hphp_raw_ptr {
253 public:
254 hphp_raw_ptr() : px(0) {}
255 explicit hphp_raw_ptr(T *p) : px(p) {}
257 /* implicit */ hphp_raw_ptr(const boost::weak_ptr<T> &p)
258 : px(p.lock().get())
261 template <class S>
262 /* implicit */ hphp_raw_ptr(const boost::shared_ptr<S> &p) : px(p.get()) {}
263 template <class S>
264 /* implicit */ hphp_raw_ptr(const boost::weak_ptr<S> &p)
265 : px(p.lock().get())
267 template <class S>
268 /* implicit */ hphp_raw_ptr(const hphp_raw_ptr<S> &p) : px(p.get()) {}
270 boost::shared_ptr<T> lock() const {
271 return px ? boost::static_pointer_cast<T>(px->shared_from_this()) :
272 boost::shared_ptr<T>();
274 bool expired() const {
275 return !px;
278 template <class S>
279 /* implicit */ operator boost::shared_ptr<S>() const {
280 S *s = px; // just to verify the implicit conversion T->S
281 return s ? boost::static_pointer_cast<S>(px->shared_from_this()) :
282 boost::shared_ptr<S>();
285 T *operator->() const { assert(px); return px; }
286 T *get() const { return px; }
287 explicit operator bool() const { return !expired(); }
288 void reset() { px = 0; }
289 private:
290 T *px;
293 #define IMPLEMENT_PTR_OPERATORS(A, B) \
294 template <class T, class U> \
295 inline bool operator==(const A<T> &p1, const B<U> &p2) { \
296 return p1.get() == p2.get(); \
298 template <class T, class U> \
299 inline bool operator!=(const A<T> &p1, const B<U> &p2) { \
300 return p1.get() != p2.get(); \
302 template <class T, class U> \
303 inline bool operator<(const A<T> &p1, const B<U> &p2) { \
304 return intptr_t(p1.get()) < intptr_t(p2.get()); \
307 IMPLEMENT_PTR_OPERATORS(hphp_raw_ptr, hphp_raw_ptr);
308 IMPLEMENT_PTR_OPERATORS(hphp_raw_ptr, boost::shared_ptr);
309 IMPLEMENT_PTR_OPERATORS(boost::shared_ptr, hphp_raw_ptr);
311 template<typename T>
312 class hphp_const_char_map :
313 public hphp_hash_map<const char *, T, hphp_hash<const char *>, eqstr> {
316 template<typename T>
317 class hphp_string_map :
318 public hphp_hash_map<std::string, T, string_hash> {
321 typedef hphp_hash_set<std::string, string_hash> hphp_string_set;
322 typedef hphp_hash_set<const char *, hphp_hash<const char *>,
323 eqstr> hphp_const_char_set;
325 typedef hphp_hash_map<void*, void*, pointer_hash<void> > PointerMap;
326 typedef hphp_hash_map<void*, int, pointer_hash<void> > PointerCounterMap;
327 typedef hphp_hash_set<void*, pointer_hash<void> > PointerSet;
329 typedef std::vector<std::string> StringVec;
330 typedef boost::shared_ptr<std::vector<std::string> > StringVecPtr;
331 typedef std::pair<std::string, std::string> StringPair;
332 typedef std::set<std::pair<std::string, std::string> > StringPairSet;
333 typedef std::vector<StringPairSet> StringPairSetVec;
335 // Convenience functions to avoid boilerplate checks for set/map<>::end() after
336 // set/map<>::find().
338 template<typename Set>
339 bool
340 setContains(const Set& m,
341 const typename Set::key_type& k) {
342 return m.find(k) != m.end();
345 template<typename Map>
346 bool
347 mapContains(const Map& m,
348 const typename Map::key_type& k) {
349 return m.find(k) != m.end();
352 template<typename Map>
353 typename Map::mapped_type
354 mapGet(const Map& m,
355 const typename Map::key_type& k,
356 const typename Map::mapped_type& defaultVal =
357 typename Map::mapped_type()) {
358 typename Map::const_iterator i = m.find(k);
359 if (i == m.end()) return defaultVal;
360 return i->second;
363 template<typename Map>
364 bool
365 mapGet(const Map& m,
366 const typename Map::key_type& k,
367 typename Map::mapped_type* outResult) {
368 typename Map::const_iterator i = m.find(k);
369 if (i == m.end()) return false;
370 if (outResult) *outResult = i->second;
371 return true;
374 template<typename Map>
375 bool
376 mapGetPtr(Map& m,
377 const typename Map::key_type& k,
378 typename Map::mapped_type** outResult) {
379 typename Map::iterator i = m.find(k);
380 if (i == m.end()) return false;
381 if (outResult) *outResult = &i->second;
382 return true;
385 template<typename Map>
386 bool
387 mapGetKey(Map& m,
388 const typename Map::key_type& k,
389 typename Map::key_type* key_ptr) {
390 typename Map::iterator i = m.find(k);
391 if (i == m.end()) return false;
392 if (key_ptr) *key_ptr = i->first;
393 return true;
396 template<typename Map>
397 void
398 mapInsert(Map& m,
399 const typename Map::key_type& k,
400 const typename Map::mapped_type& d) {
401 m.insert(typename Map::value_type(k, d));
404 // Known-unique insertion.
405 template<typename Map>
406 void
407 mapInsertUnique(Map& m,
408 const typename Map::key_type& k,
409 const typename Map::mapped_type& d) {
410 assert(!mapContains(m, k));
411 mapInsert(m, k, d);
414 // Deep-copy a container of dynamically allocated pointers. Assumes copy
415 // constructors do the right thing.
416 template<typename Container>
417 void
418 cloneMembers(Container& c) {
419 for (typename Container::iterator i = c.begin();
420 i != c.end(); ++i) {
421 typedef typename Container::value_type Pointer;
422 typedef typename boost::remove_pointer<Pointer>::type Inner;
423 *i = new Inner(**i);
427 // invoke operator delete on the contents of a container.
428 template<typename Container>
429 void
430 destroyMembers(Container& c) {
431 for (typename Container::iterator i = c.begin();
432 i != c.end(); ++i) {
433 delete *i;
437 template<typename Container>
438 void
439 destroyMapValues(Container& c) {
440 for (typename Container::iterator i = c.begin();
441 i != c.end(); ++i) {
442 delete i->second;
447 ///////////////////////////////////////////////////////////////////////////////
448 // boost
450 // Let us always use hphp's definition of DECLARE_BOOST_TYPES, esp. when it is
451 // used as an external library.
452 #ifdef DECLARE_BOOST_TYPES
453 #undef DECLARE_BOOST_TYPES
454 #endif
456 #define DECLARE_BOOST_TYPES(classname) \
457 class classname; \
458 typedef boost::shared_ptr<classname> classname ## Ptr; \
459 typedef hphp_raw_ptr<classname> classname ## RawPtr; \
460 typedef boost::weak_ptr<classname> classname ## WeakPtr; \
461 typedef boost::shared_ptr<const classname> classname ## ConstPtr; \
462 typedef std::vector<classname ## Ptr> classname ## PtrVec; \
463 typedef std::set<classname ## Ptr> classname ## PtrSet; \
464 typedef std::list<classname ## Ptr> classname ## PtrList; \
465 typedef hphp_string_hash_map<classname ## Ptr, classname> \
466 StringTo ## classname ## PtrMap; \
467 typedef hphp_string_hash_map<classname ## PtrVec, classname> \
468 StringTo ## classname ## PtrVecMap; \
469 typedef hphp_string_hash_map<classname ## PtrSet, classname> \
470 StringTo ## classname ## PtrSetMap; \
472 typedef boost::shared_ptr<FILE> FilePtr;
474 struct null_deleter {
475 void operator()(void const *) const {
479 struct file_closer {
480 void operator()(FILE *f) const {
481 if (f) fclose(f);
485 ///////////////////////////////////////////////////////////////////////////////
488 * DEBUG-only wrapper around boost::numeric_cast that converts any
489 * thrown exceptions to a failed assertion.
491 template <typename To, typename From>
492 To safe_cast(From val) {
493 if (debug) {
494 try {
495 return boost::numeric_cast<To>(val);
496 } catch (std::bad_cast& bce) {
497 std::cerr << "conversion of " << val << " failed in "
498 << __PRETTY_FUNCTION__ << " : "
499 << bce.what() << std::endl;
500 not_reached();
502 } else {
503 return static_cast<To>(val);
507 template<class T, size_t Sz>
508 size_t array_size(T (&t)[Sz]) {
509 return Sz;
512 template<typename Out, typename In>
513 Out& readData(In*& it) {
514 Out& r = *(Out*)it;
515 (char*&)it += sizeof(Out);
516 return r;
518 } // namespace HPHP
520 namespace boost {
522 template <typename T, typename U>
523 HPHP::hphp_raw_ptr<T> dynamic_pointer_cast(HPHP::hphp_raw_ptr<U> p) {
524 return HPHP::hphp_raw_ptr<T>(dynamic_cast<T*>(p.get()));
527 template <typename T, typename U>
528 HPHP::hphp_raw_ptr<T> static_pointer_cast(HPHP::hphp_raw_ptr<U> p) {
529 return HPHP::hphp_raw_ptr<T>(static_cast<T*>(p.get()));
533 inline bool ptr_is_low_mem(void* ptr) {
534 static_assert(sizeof(void*) == 8, "Unexpected pointer size");
535 return !((uint64_t)ptr & 0xffffffff00000000ull);
538 namespace HPHP {
539 using std::string;
540 using std::vector;
541 using boost::lexical_cast;
542 using boost::dynamic_pointer_cast;
543 using boost::static_pointer_cast;
546 #endif