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 26 _LIBCPP_BEGIN_NAMESPACE_STD 27 28 namespace __refstring_imp { namespace { 29 typedef int count_t; 30 31 struct _Rep_base { 32 std::size_t len; 33 std::size_t cap; 34 count_t count; 35 }; 36 37 inline _Rep_base* rep_from_data(const char *data_) noexcept { 38 char *data = const_cast<char *>(data_); 39 return reinterpret_cast<_Rep_base *>(data - sizeof(_Rep_base)); 40 } 41 42 inline char * data_from_rep(_Rep_base *rep) noexcept { 43 char *data = reinterpret_cast<char *>(rep); 44 return data + sizeof(*rep); 45 } 46 47 #if defined(__APPLE__) 48 inline 49 const char* compute_gcc_empty_string_storage() _NOEXCEPT 50 { 51 void* handle = dlopen("/usr/lib/libstdc++.6.dylib", RTLD_NOLOAD); 52 if (handle == nullptr) 53 return nullptr; 54 void* sym = dlsym(handle, "_ZNSs4_Rep20_S_empty_rep_storageE"); 55 if (sym == nullptr) 56 return nullptr; 57 return data_from_rep(reinterpret_cast<_Rep_base *>(sym)); 58 } 59 60 inline 61 const char* 62 get_gcc_empty_string_storage() _NOEXCEPT 63 { 64 static const char* p = compute_gcc_empty_string_storage(); 65 return p; 66 } 67 #endif 68 69 }} // namespace __refstring_imp 70 71 using namespace __refstring_imp; 72 73 inline 74 __libcpp_refstring::__libcpp_refstring(const char* msg) { 75 std::size_t len = strlen(msg); 76 _Rep_base* rep = static_cast<_Rep_base *>(::operator new(sizeof(*rep) + len + 1)); 77 rep->len = len; 78 rep->cap = len; 79 rep->count = 0; 80 char *data = data_from_rep(rep); 81 std::memcpy(data, msg, len + 1); 82 __imp_ = data; 83 } 84 85 inline 86 __libcpp_refstring::__libcpp_refstring(const __libcpp_refstring &s) _NOEXCEPT 87 : __imp_(s.__imp_) 88 { 89 if (__uses_refcount()) 90 __sync_add_and_fetch(&rep_from_data(__imp_)->count, 1); 91 } 92 93 inline 94 __libcpp_refstring& __libcpp_refstring::operator=(__libcpp_refstring const& s) _NOEXCEPT { 95 bool adjust_old_count = __uses_refcount(); 96 struct _Rep_base *old_rep = rep_from_data(__imp_); 97 __imp_ = s.__imp_; 98 if (__uses_refcount()) 99 __sync_add_and_fetch(&rep_from_data(__imp_)->count, 1); 100 if (adjust_old_count) 101 { 102 if (__sync_add_and_fetch(&old_rep->count, count_t(-1)) < 0) 103 { 104 ::operator delete(old_rep); 105 } 106 } 107 return *this; 108 } 109 110 inline 111 __libcpp_refstring::~__libcpp_refstring() { 112 if (__uses_refcount()) { 113 _Rep_base* rep = rep_from_data(__imp_); 114 if (__sync_add_and_fetch(&rep->count, count_t(-1)) < 0) { 115 ::operator delete(rep); 116 } 117 } 118 } 119 120 inline 121 bool __libcpp_refstring::__uses_refcount() const { 122 #ifdef __APPLE__ 123 return __imp_ != get_gcc_empty_string_storage(); 124 #else 125 return true; 126 #endif 127 } 128 129 _LIBCPP_END_NAMESPACE_STD 130 131 #endif //_LIBCPPABI_REFSTRING_H 132