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 25namespace __refstring_imp { namespace { 26typedef int count_t; 27 28struct _Rep_base { 29 std::size_t len; 30 std::size_t cap; 31 count_t count; 32}; 33 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 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__) 45inline 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 57inline 58const char* 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 68using namespace __refstring_imp; 69 70inline 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 82inline 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 90inline 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 107inline 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 117inline 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