2 +----------------------------------------------------------------------+
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_
27 #include "hphp/runtime/base/strings.h"
30 #include "netinet/in.h"
31 #include "arpa/inet.h"
38 #include <sys/types.h>
39 #include <sys/resource.h>
40 #include <sys/utsname.h>
41 #include <sys/socket.h>
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
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
85 struct hash
<const char*> {
86 size_t operator()(const char *s
) const {
87 return HPHP::hash_string_cs(s
, strlen(s
));
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) {}
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) {}
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
119 ///////////////////////////////////////////////////////////////////////////////
130 const bool use_jemalloc
=
138 const bool packed_tv
=
147 * Guard bug-for-bug hphpi compatibility code with this predicate.
149 const bool hphpiCompat
= true;
151 ///////////////////////////////////////////////////////////////////////////////
155 #define WORDSIZE_IS_64
158 typedef unsigned char uchar
;
161 #define ULLONG_MAX 0xffffffffffffffffULL
164 ///////////////////////////////////////////////////////////////////////////////
168 bool operator()(const char *s1
, const char *s2
) const {
169 return strcmp(s1
, s2
) < 0;
174 bool operator()(const char* s1
, const char* s2
) const {
175 return strcmp(s1
, s2
) == 0;
180 bool operator()(const std::string
&s1
, const std::string
&s2
) const {
181 return strcmp(s1
.c_str(), s2
.c_str()) < 0;
186 bool operator()(const std::string
&s1
, const std::string
&s2
) const {
187 return strcasecmp(s1
.c_str(), s2
.c_str()) < 0;
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 {
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
> {
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 {
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 {
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
{
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
)
262 /* implicit */ hphp_raw_ptr(const boost::shared_ptr
<S
> &p
) : px(p
.get()) {}
264 /* implicit */ hphp_raw_ptr(const boost::weak_ptr
<S
> &p
)
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 {
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; }
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
);
312 class hphp_const_char_map
:
313 public hphp_hash_map
<const char *, T
, hphp_hash
<const char *>, eqstr
> {
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
>
340 setContains(const Set
& m
,
341 const typename
Set::key_type
& k
) {
342 return m
.find(k
) != m
.end();
345 template<typename Map
>
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
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
;
363 template<typename Map
>
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
;
374 template<typename Map
>
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
;
385 template<typename Map
>
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
;
396 template<typename Map
>
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
>
407 mapInsertUnique(Map
& m
,
408 const typename
Map::key_type
& k
,
409 const typename
Map::mapped_type
& d
) {
410 assert(!mapContains(m
, k
));
414 // Deep-copy a container of dynamically allocated pointers. Assumes copy
415 // constructors do the right thing.
416 template<typename Container
>
418 cloneMembers(Container
& c
) {
419 for (typename
Container::iterator i
= c
.begin();
421 typedef typename
Container::value_type Pointer
;
422 typedef typename
boost::remove_pointer
<Pointer
>::type Inner
;
427 // invoke operator delete on the contents of a container.
428 template<typename Container
>
430 destroyMembers(Container
& c
) {
431 for (typename
Container::iterator i
= c
.begin();
437 template<typename Container
>
439 destroyMapValues(Container
& c
) {
440 for (typename
Container::iterator i
= c
.begin();
447 ///////////////////////////////////////////////////////////////////////////////
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
456 #define DECLARE_BOOST_TYPES(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 {
480 void operator()(FILE *f
) const {
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
) {
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
;
503 return static_cast<To
>(val
);
507 template<class T
, size_t Sz
>
508 size_t array_size(T (&t
)[Sz
]) {
512 template<typename Out
, typename In
>
513 Out
& readData(In
*& it
) {
515 (char*&)it
+= sizeof(Out
);
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
);
541 using boost::lexical_cast
;
542 using boost::dynamic_pointer_cast
;
543 using boost::static_pointer_cast
;