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