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