libcxx

libcxx mirror with random patches
git clone https://git.neptards.moe/neptards/libcxx.git
Log | Files | Refs

refstring.h (3201B)


      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 
     34 inline _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 
     39 inline 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
     46 const 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*
     59 get_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
     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
     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
    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
    118 bool __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