__refstring revision 278724
1213288Sdavidxu//===------------------------ __refstring ---------------------------------===// 2213288Sdavidxu// 3213288Sdavidxu// The LLVM Compiler Infrastructure 4213288Sdavidxu// 5213288Sdavidxu// This file is dual licensed under the MIT and the University of Illinois Open 6213288Sdavidxu// Source Licenses. See LICENSE.TXT for details. 7213288Sdavidxu// 8213288Sdavidxu//===----------------------------------------------------------------------===// 9213288Sdavidxu 10213288Sdavidxu#ifndef _LIBCPP___REFSTRING 11213288Sdavidxu#define _LIBCPP___REFSTRING 12213288Sdavidxu 13213288Sdavidxu#include <__config> 14213288Sdavidxu#include <cstddef> 15213288Sdavidxu#include <cstring> 16213288Sdavidxu#if __APPLE__ 17213288Sdavidxu#include <dlfcn.h> 18213288Sdavidxu#include <mach-o/dyld.h> 19213288Sdavidxu#endif 20213288Sdavidxu 21213288Sdavidxu_LIBCPP_BEGIN_NAMESPACE_STD 22213288Sdavidxu 23213288Sdavidxuclass _LIBCPP_HIDDEN __libcpp_refstring 24213288Sdavidxu{ 25213288Sdavidxuprivate: 26213288Sdavidxu const char* str_; 27213288Sdavidxu 28213288Sdavidxu typedef int count_t; 29213288Sdavidxu 30213288Sdavidxu struct _Rep_base 31213289Sdavidxu { 32213289Sdavidxu std::size_t len; 33213288Sdavidxu std::size_t cap; 34213288Sdavidxu count_t count; 35213288Sdavidxu }; 36213288Sdavidxu 37213288Sdavidxu static 38213288Sdavidxu _Rep_base* 39213288Sdavidxu rep_from_data(const char *data_) _NOEXCEPT 40213288Sdavidxu { 41213288Sdavidxu char *data = const_cast<char *>(data_); 42213288Sdavidxu return reinterpret_cast<_Rep_base *>(data - sizeof(_Rep_base)); 43213288Sdavidxu } 44213288Sdavidxu static 45213288Sdavidxu char * 46213288Sdavidxu data_from_rep(_Rep_base *rep) _NOEXCEPT 47213288Sdavidxu { 48213288Sdavidxu char *data = reinterpret_cast<char *>(rep); 49213288Sdavidxu return data + sizeof(*rep); 50213288Sdavidxu } 51213288Sdavidxu 52213288Sdavidxu#if __APPLE__ 53213288Sdavidxu static 54213288Sdavidxu const char* 55213288Sdavidxu compute_gcc_empty_string_storage() _NOEXCEPT 56213288Sdavidxu { 57213288Sdavidxu void* handle = dlopen("/usr/lib/libstdc++.6.dylib", RTLD_NOLOAD); 58213288Sdavidxu if (handle == nullptr) 59213288Sdavidxu return nullptr; 60213288Sdavidxu void* sym = dlsym(handle, "_ZNSs4_Rep20_S_empty_rep_storageE"); 61213288Sdavidxu if (sym == nullptr) 62213288Sdavidxu return nullptr; 63213288Sdavidxu return data_from_rep(reinterpret_cast<_Rep_base *>(sym)); 64213288Sdavidxu } 65213288Sdavidxu 66213288Sdavidxu static 67213288Sdavidxu const char* 68213288Sdavidxu get_gcc_empty_string_storage() _NOEXCEPT 69213290Sdavidxu { 70213288Sdavidxu static const char* p = compute_gcc_empty_string_storage(); 71213288Sdavidxu return p; 72213288Sdavidxu } 73213288Sdavidxu 74213288Sdavidxu bool 75213288Sdavidxu uses_refcount() const 76213288Sdavidxu { 77213288Sdavidxu return str_ != get_gcc_empty_string_storage(); 78213288Sdavidxu } 79213288Sdavidxu#else 80213288Sdavidxu bool 81213289Sdavidxu uses_refcount() const 82213288Sdavidxu { 83213288Sdavidxu return true; 84213288Sdavidxu } 85213288Sdavidxu#endif 86213288Sdavidxu 87213288Sdavidxupublic: 88213288Sdavidxu explicit __libcpp_refstring(const char* msg) { 89213288Sdavidxu std::size_t len = strlen(msg); 90213288Sdavidxu _Rep_base* rep = static_cast<_Rep_base *>(::operator new(sizeof(*rep) + len + 1)); 91213288Sdavidxu rep->len = len; 92213288Sdavidxu rep->cap = len; 93213288Sdavidxu rep->count = 0; 94213288Sdavidxu char *data = data_from_rep(rep); 95213288Sdavidxu std::memcpy(data, msg, len + 1); 96213288Sdavidxu str_ = data; 97213288Sdavidxu } 98213288Sdavidxu 99213288Sdavidxu __libcpp_refstring(const __libcpp_refstring& s) _NOEXCEPT : str_(s.str_) 100213289Sdavidxu { 101213288Sdavidxu if (uses_refcount()) 102213288Sdavidxu __sync_add_and_fetch(&rep_from_data(str_)->count, 1); 103213288Sdavidxu } 104213288Sdavidxu 105213288Sdavidxu __libcpp_refstring& operator=(const __libcpp_refstring& s) _NOEXCEPT 106213288Sdavidxu { 107213288Sdavidxu bool adjust_old_count = uses_refcount(); 108213288Sdavidxu struct _Rep_base *old_rep = rep_from_data(str_); 109213288Sdavidxu str_ = s.str_; 110213288Sdavidxu if (uses_refcount()) 111213288Sdavidxu __sync_add_and_fetch(&rep_from_data(str_)->count, 1); 112213288Sdavidxu if (adjust_old_count) 113213288Sdavidxu { 114213288Sdavidxu if (__sync_add_and_fetch(&old_rep->count, count_t(-1)) < 0) 115213288Sdavidxu { 116213288Sdavidxu ::operator delete(old_rep); 117213288Sdavidxu } 118213288Sdavidxu } 119213288Sdavidxu return *this; 120213288Sdavidxu } 121213288Sdavidxu 122213288Sdavidxu ~__libcpp_refstring() 123213288Sdavidxu { 124213288Sdavidxu if (uses_refcount()) 125213288Sdavidxu { 126213288Sdavidxu _Rep_base* rep = rep_from_data(str_); 127213288Sdavidxu if (__sync_add_and_fetch(&rep->count, count_t(-1)) < 0) 128213288Sdavidxu { 129213288Sdavidxu ::operator delete(rep); 130213288Sdavidxu } 131213288Sdavidxu } 132213288Sdavidxu } 133213288Sdavidxu 134213288Sdavidxu const char* c_str() const _NOEXCEPT {return str_;} 135213288Sdavidxu}; 136213288Sdavidxu 137213288Sdavidxu_LIBCPP_END_NAMESPACE_STD 138213288Sdavidxu 139213288Sdavidxu#endif //_LIBCPP___REFSTRING 140213288Sdavidxu