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