1*58b9f456SAndroid Build Coastguard Worker //===------------------------ __refstring ---------------------------------===// 2*58b9f456SAndroid Build Coastguard Worker // 3*58b9f456SAndroid Build Coastguard Worker // The LLVM Compiler Infrastructure 4*58b9f456SAndroid Build Coastguard Worker // 5*58b9f456SAndroid Build Coastguard Worker // This file is dual licensed under the MIT and the University of Illinois Open 6*58b9f456SAndroid Build Coastguard Worker // Source Licenses. See LICENSE.TXT for details. 7*58b9f456SAndroid Build Coastguard Worker // 8*58b9f456SAndroid Build Coastguard Worker //===----------------------------------------------------------------------===// 9*58b9f456SAndroid Build Coastguard Worker 10*58b9f456SAndroid Build Coastguard Worker #ifndef _LIBCPP_REFSTRING_H 11*58b9f456SAndroid Build Coastguard Worker #define _LIBCPP_REFSTRING_H 12*58b9f456SAndroid Build Coastguard Worker 13*58b9f456SAndroid Build Coastguard Worker #include <__config> 14*58b9f456SAndroid Build Coastguard Worker #include <stdexcept> 15*58b9f456SAndroid Build Coastguard Worker #include <cstddef> 16*58b9f456SAndroid Build Coastguard Worker #include <cstring> 17*58b9f456SAndroid Build Coastguard Worker #ifdef __APPLE__ 18*58b9f456SAndroid Build Coastguard Worker #include <dlfcn.h> 19*58b9f456SAndroid Build Coastguard Worker #include <mach-o/dyld.h> 20*58b9f456SAndroid Build Coastguard Worker #endif 21*58b9f456SAndroid Build Coastguard Worker #include "atomic_support.h" 22*58b9f456SAndroid Build Coastguard Worker 23*58b9f456SAndroid Build Coastguard Worker _LIBCPP_BEGIN_NAMESPACE_STD 24*58b9f456SAndroid Build Coastguard Worker 25*58b9f456SAndroid Build Coastguard Worker namespace __refstring_imp { namespace { 26*58b9f456SAndroid Build Coastguard Worker typedef int count_t; 27*58b9f456SAndroid Build Coastguard Worker 28*58b9f456SAndroid Build Coastguard Worker struct _Rep_base { 29*58b9f456SAndroid Build Coastguard Worker std::size_t len; 30*58b9f456SAndroid Build Coastguard Worker std::size_t cap; 31*58b9f456SAndroid Build Coastguard Worker count_t count; 32*58b9f456SAndroid Build Coastguard Worker }; 33*58b9f456SAndroid Build Coastguard Worker rep_from_data(const char * data_)34*58b9f456SAndroid Build Coastguard Workerinline _Rep_base* rep_from_data(const char *data_) noexcept { 35*58b9f456SAndroid Build Coastguard Worker char *data = const_cast<char *>(data_); 36*58b9f456SAndroid Build Coastguard Worker return reinterpret_cast<_Rep_base *>(data - sizeof(_Rep_base)); 37*58b9f456SAndroid Build Coastguard Worker } 38*58b9f456SAndroid Build Coastguard Worker data_from_rep(_Rep_base * rep)39*58b9f456SAndroid Build Coastguard Workerinline char * data_from_rep(_Rep_base *rep) noexcept { 40*58b9f456SAndroid Build Coastguard Worker char *data = reinterpret_cast<char *>(rep); 41*58b9f456SAndroid Build Coastguard Worker return data + sizeof(*rep); 42*58b9f456SAndroid Build Coastguard Worker } 43*58b9f456SAndroid Build Coastguard Worker 44*58b9f456SAndroid Build Coastguard Worker #if defined(__APPLE__) 45*58b9f456SAndroid Build Coastguard Worker inline compute_gcc_empty_string_storage()46*58b9f456SAndroid Build Coastguard Workerconst char* compute_gcc_empty_string_storage() _NOEXCEPT 47*58b9f456SAndroid Build Coastguard Worker { 48*58b9f456SAndroid Build Coastguard Worker void* handle = dlopen("/usr/lib/libstdc++.6.dylib", RTLD_NOLOAD); 49*58b9f456SAndroid Build Coastguard Worker if (handle == nullptr) 50*58b9f456SAndroid Build Coastguard Worker return nullptr; 51*58b9f456SAndroid Build Coastguard Worker void* sym = dlsym(handle, "_ZNSs4_Rep20_S_empty_rep_storageE"); 52*58b9f456SAndroid Build Coastguard Worker if (sym == nullptr) 53*58b9f456SAndroid Build Coastguard Worker return nullptr; 54*58b9f456SAndroid Build Coastguard Worker return data_from_rep(reinterpret_cast<_Rep_base *>(sym)); 55*58b9f456SAndroid Build Coastguard Worker } 56*58b9f456SAndroid Build Coastguard Worker 57*58b9f456SAndroid Build Coastguard Worker inline 58*58b9f456SAndroid Build Coastguard Worker const char* get_gcc_empty_string_storage()59*58b9f456SAndroid Build Coastguard Workerget_gcc_empty_string_storage() _NOEXCEPT 60*58b9f456SAndroid Build Coastguard Worker { 61*58b9f456SAndroid Build Coastguard Worker static const char* p = compute_gcc_empty_string_storage(); 62*58b9f456SAndroid Build Coastguard Worker return p; 63*58b9f456SAndroid Build Coastguard Worker } 64*58b9f456SAndroid Build Coastguard Worker #endif 65*58b9f456SAndroid Build Coastguard Worker 66*58b9f456SAndroid Build Coastguard Worker }} // namespace __refstring_imp 67*58b9f456SAndroid Build Coastguard Worker 68*58b9f456SAndroid Build Coastguard Worker using namespace __refstring_imp; 69*58b9f456SAndroid Build Coastguard Worker 70*58b9f456SAndroid Build Coastguard Worker inline __libcpp_refstring(const char * msg)71*58b9f456SAndroid Build Coastguard Worker__libcpp_refstring::__libcpp_refstring(const char* msg) { 72*58b9f456SAndroid Build Coastguard Worker std::size_t len = strlen(msg); 73*58b9f456SAndroid Build Coastguard Worker _Rep_base* rep = static_cast<_Rep_base *>(::operator new(sizeof(*rep) + len + 1)); 74*58b9f456SAndroid Build Coastguard Worker rep->len = len; 75*58b9f456SAndroid Build Coastguard Worker rep->cap = len; 76*58b9f456SAndroid Build Coastguard Worker rep->count = 0; 77*58b9f456SAndroid Build Coastguard Worker char *data = data_from_rep(rep); 78*58b9f456SAndroid Build Coastguard Worker std::memcpy(data, msg, len + 1); 79*58b9f456SAndroid Build Coastguard Worker __imp_ = data; 80*58b9f456SAndroid Build Coastguard Worker } 81*58b9f456SAndroid Build Coastguard Worker 82*58b9f456SAndroid Build Coastguard Worker inline __libcpp_refstring(const __libcpp_refstring & s)83*58b9f456SAndroid Build Coastguard Worker__libcpp_refstring::__libcpp_refstring(const __libcpp_refstring &s) _NOEXCEPT 84*58b9f456SAndroid Build Coastguard Worker : __imp_(s.__imp_) 85*58b9f456SAndroid Build Coastguard Worker { 86*58b9f456SAndroid Build Coastguard Worker if (__uses_refcount()) 87*58b9f456SAndroid Build Coastguard Worker __libcpp_atomic_add(&rep_from_data(__imp_)->count, 1); 88*58b9f456SAndroid Build Coastguard Worker } 89*58b9f456SAndroid Build Coastguard Worker 90*58b9f456SAndroid Build Coastguard Worker inline 91*58b9f456SAndroid Build Coastguard Worker __libcpp_refstring& __libcpp_refstring::operator=(__libcpp_refstring const& s) _NOEXCEPT { 92*58b9f456SAndroid Build Coastguard Worker bool adjust_old_count = __uses_refcount(); 93*58b9f456SAndroid Build Coastguard Worker struct _Rep_base *old_rep = rep_from_data(__imp_); 94*58b9f456SAndroid Build Coastguard Worker __imp_ = s.__imp_; 95*58b9f456SAndroid Build Coastguard Worker if (__uses_refcount()) 96*58b9f456SAndroid Build Coastguard Worker __libcpp_atomic_add(&rep_from_data(__imp_)->count, 1); 97*58b9f456SAndroid Build Coastguard Worker if (adjust_old_count) 98*58b9f456SAndroid Build Coastguard Worker { 99*58b9f456SAndroid Build Coastguard Worker if (__libcpp_atomic_add(&old_rep->count, count_t(-1)) < 0) 100*58b9f456SAndroid Build Coastguard Worker { 101*58b9f456SAndroid Build Coastguard Worker ::operator delete(old_rep); 102*58b9f456SAndroid Build Coastguard Worker } 103*58b9f456SAndroid Build Coastguard Worker } 104*58b9f456SAndroid Build Coastguard Worker return *this; 105*58b9f456SAndroid Build Coastguard Worker } 106*58b9f456SAndroid Build Coastguard Worker 107*58b9f456SAndroid Build Coastguard Worker inline ~__libcpp_refstring()108*58b9f456SAndroid Build Coastguard Worker__libcpp_refstring::~__libcpp_refstring() { 109*58b9f456SAndroid Build Coastguard Worker if (__uses_refcount()) { 110*58b9f456SAndroid Build Coastguard Worker _Rep_base* rep = rep_from_data(__imp_); 111*58b9f456SAndroid Build Coastguard Worker if (__libcpp_atomic_add(&rep->count, count_t(-1)) < 0) { 112*58b9f456SAndroid Build Coastguard Worker ::operator delete(rep); 113*58b9f456SAndroid Build Coastguard Worker } 114*58b9f456SAndroid Build Coastguard Worker } 115*58b9f456SAndroid Build Coastguard Worker } 116*58b9f456SAndroid Build Coastguard Worker 117*58b9f456SAndroid Build Coastguard Worker inline __uses_refcount()118*58b9f456SAndroid Build Coastguard Workerbool __libcpp_refstring::__uses_refcount() const { 119*58b9f456SAndroid Build Coastguard Worker #ifdef __APPLE__ 120*58b9f456SAndroid Build Coastguard Worker return __imp_ != get_gcc_empty_string_storage(); 121*58b9f456SAndroid Build Coastguard Worker #else 122*58b9f456SAndroid Build Coastguard Worker return true; 123*58b9f456SAndroid Build Coastguard Worker #endif 124*58b9f456SAndroid Build Coastguard Worker } 125*58b9f456SAndroid Build Coastguard Worker 126*58b9f456SAndroid Build Coastguard Worker _LIBCPP_END_NAMESPACE_STD 127*58b9f456SAndroid Build Coastguard Worker 128*58b9f456SAndroid Build Coastguard Worker #endif //_LIBCPP_REFSTRING_H 129