xref: /aosp_15_r20/external/libcxxabi/src/include/refstring.h (revision c05d8e5dc3e10f6ce4317e8bc22cc4a25f55fa94)
1*c05d8e5dSAndroid Build Coastguard Worker //===------------------------ __refstring ---------------------------------===//
2*c05d8e5dSAndroid Build Coastguard Worker //
3*c05d8e5dSAndroid Build Coastguard Worker //                     The LLVM Compiler Infrastructure
4*c05d8e5dSAndroid Build Coastguard Worker //
5*c05d8e5dSAndroid Build Coastguard Worker // This file is dual licensed under the MIT and the University of Illinois Open
6*c05d8e5dSAndroid Build Coastguard Worker // Source Licenses. See LICENSE.TXT for details.
7*c05d8e5dSAndroid Build Coastguard Worker //
8*c05d8e5dSAndroid Build Coastguard Worker //===----------------------------------------------------------------------===//
9*c05d8e5dSAndroid Build Coastguard Worker 
10*c05d8e5dSAndroid Build Coastguard Worker // FIXME: This file is copied from libcxx/src/include/refstring.h. Instead of
11*c05d8e5dSAndroid Build Coastguard Worker // duplicating the file in libc++abi we should require that the libc++ sources
12*c05d8e5dSAndroid Build Coastguard Worker // are available when building libc++abi.
13*c05d8e5dSAndroid Build Coastguard Worker 
14*c05d8e5dSAndroid Build Coastguard Worker #ifndef _LIBCPPABI_REFSTRING_H
15*c05d8e5dSAndroid Build Coastguard Worker #define _LIBCPPABI_REFSTRING_H
16*c05d8e5dSAndroid Build Coastguard Worker 
17*c05d8e5dSAndroid Build Coastguard Worker #include <__config>
18*c05d8e5dSAndroid Build Coastguard Worker #include <stdexcept>
19*c05d8e5dSAndroid Build Coastguard Worker #include <cstddef>
20*c05d8e5dSAndroid Build Coastguard Worker #include <cstring>
21*c05d8e5dSAndroid Build Coastguard Worker #ifdef __APPLE__
22*c05d8e5dSAndroid Build Coastguard Worker #include <dlfcn.h>
23*c05d8e5dSAndroid Build Coastguard Worker #include <mach-o/dyld.h>
24*c05d8e5dSAndroid Build Coastguard Worker #endif
25*c05d8e5dSAndroid Build Coastguard Worker #include "atomic_support.h"
26*c05d8e5dSAndroid Build Coastguard Worker 
27*c05d8e5dSAndroid Build Coastguard Worker _LIBCPP_BEGIN_NAMESPACE_STD
28*c05d8e5dSAndroid Build Coastguard Worker 
29*c05d8e5dSAndroid Build Coastguard Worker namespace __refstring_imp { namespace {
30*c05d8e5dSAndroid Build Coastguard Worker typedef int count_t;
31*c05d8e5dSAndroid Build Coastguard Worker 
32*c05d8e5dSAndroid Build Coastguard Worker struct _Rep_base {
33*c05d8e5dSAndroid Build Coastguard Worker     std::size_t len;
34*c05d8e5dSAndroid Build Coastguard Worker     std::size_t cap;
35*c05d8e5dSAndroid Build Coastguard Worker     count_t     count;
36*c05d8e5dSAndroid Build Coastguard Worker };
37*c05d8e5dSAndroid Build Coastguard Worker 
rep_from_data(const char * data_)38*c05d8e5dSAndroid Build Coastguard Worker inline _Rep_base* rep_from_data(const char *data_) noexcept {
39*c05d8e5dSAndroid Build Coastguard Worker     char *data = const_cast<char *>(data_);
40*c05d8e5dSAndroid Build Coastguard Worker     return reinterpret_cast<_Rep_base *>(data - sizeof(_Rep_base));
41*c05d8e5dSAndroid Build Coastguard Worker }
42*c05d8e5dSAndroid Build Coastguard Worker 
data_from_rep(_Rep_base * rep)43*c05d8e5dSAndroid Build Coastguard Worker inline char * data_from_rep(_Rep_base *rep) noexcept {
44*c05d8e5dSAndroid Build Coastguard Worker     char *data = reinterpret_cast<char *>(rep);
45*c05d8e5dSAndroid Build Coastguard Worker     return data + sizeof(*rep);
46*c05d8e5dSAndroid Build Coastguard Worker }
47*c05d8e5dSAndroid Build Coastguard Worker 
48*c05d8e5dSAndroid Build Coastguard Worker #if defined(__APPLE__)
49*c05d8e5dSAndroid Build Coastguard Worker inline
compute_gcc_empty_string_storage()50*c05d8e5dSAndroid Build Coastguard Worker const char* compute_gcc_empty_string_storage() _NOEXCEPT
51*c05d8e5dSAndroid Build Coastguard Worker {
52*c05d8e5dSAndroid Build Coastguard Worker     void* handle = dlopen("/usr/lib/libstdc++.6.dylib", RTLD_NOLOAD);
53*c05d8e5dSAndroid Build Coastguard Worker     if (handle == nullptr)
54*c05d8e5dSAndroid Build Coastguard Worker         return nullptr;
55*c05d8e5dSAndroid Build Coastguard Worker     void* sym = dlsym(handle, "_ZNSs4_Rep20_S_empty_rep_storageE");
56*c05d8e5dSAndroid Build Coastguard Worker     if (sym == nullptr)
57*c05d8e5dSAndroid Build Coastguard Worker         return nullptr;
58*c05d8e5dSAndroid Build Coastguard Worker     return data_from_rep(reinterpret_cast<_Rep_base *>(sym));
59*c05d8e5dSAndroid Build Coastguard Worker }
60*c05d8e5dSAndroid Build Coastguard Worker 
61*c05d8e5dSAndroid Build Coastguard Worker inline
62*c05d8e5dSAndroid Build Coastguard Worker const char*
get_gcc_empty_string_storage()63*c05d8e5dSAndroid Build Coastguard Worker get_gcc_empty_string_storage() _NOEXCEPT
64*c05d8e5dSAndroid Build Coastguard Worker {
65*c05d8e5dSAndroid Build Coastguard Worker     static const char* p = compute_gcc_empty_string_storage();
66*c05d8e5dSAndroid Build Coastguard Worker     return p;
67*c05d8e5dSAndroid Build Coastguard Worker }
68*c05d8e5dSAndroid Build Coastguard Worker #endif
69*c05d8e5dSAndroid Build Coastguard Worker 
70*c05d8e5dSAndroid Build Coastguard Worker }} // namespace __refstring_imp
71*c05d8e5dSAndroid Build Coastguard Worker 
72*c05d8e5dSAndroid Build Coastguard Worker using namespace __refstring_imp;
73*c05d8e5dSAndroid Build Coastguard Worker 
74*c05d8e5dSAndroid Build Coastguard Worker inline
__libcpp_refstring(const char * msg)75*c05d8e5dSAndroid Build Coastguard Worker __libcpp_refstring::__libcpp_refstring(const char* msg) {
76*c05d8e5dSAndroid Build Coastguard Worker     std::size_t len = strlen(msg);
77*c05d8e5dSAndroid Build Coastguard Worker     _Rep_base* rep = static_cast<_Rep_base *>(::operator new(sizeof(*rep) + len + 1));
78*c05d8e5dSAndroid Build Coastguard Worker     rep->len = len;
79*c05d8e5dSAndroid Build Coastguard Worker     rep->cap = len;
80*c05d8e5dSAndroid Build Coastguard Worker     rep->count = 0;
81*c05d8e5dSAndroid Build Coastguard Worker     char *data = data_from_rep(rep);
82*c05d8e5dSAndroid Build Coastguard Worker     std::memcpy(data, msg, len + 1);
83*c05d8e5dSAndroid Build Coastguard Worker     __imp_ = data;
84*c05d8e5dSAndroid Build Coastguard Worker }
85*c05d8e5dSAndroid Build Coastguard Worker 
86*c05d8e5dSAndroid Build Coastguard Worker inline
__libcpp_refstring(const __libcpp_refstring & s)87*c05d8e5dSAndroid Build Coastguard Worker __libcpp_refstring::__libcpp_refstring(const __libcpp_refstring &s) _NOEXCEPT
88*c05d8e5dSAndroid Build Coastguard Worker     : __imp_(s.__imp_)
89*c05d8e5dSAndroid Build Coastguard Worker {
90*c05d8e5dSAndroid Build Coastguard Worker     if (__uses_refcount())
91*c05d8e5dSAndroid Build Coastguard Worker         __libcpp_atomic_add(&rep_from_data(__imp_)->count, 1);
92*c05d8e5dSAndroid Build Coastguard Worker }
93*c05d8e5dSAndroid Build Coastguard Worker 
94*c05d8e5dSAndroid Build Coastguard Worker inline
95*c05d8e5dSAndroid Build Coastguard Worker __libcpp_refstring& __libcpp_refstring::operator=(__libcpp_refstring const& s) _NOEXCEPT {
96*c05d8e5dSAndroid Build Coastguard Worker     bool adjust_old_count = __uses_refcount();
97*c05d8e5dSAndroid Build Coastguard Worker     struct _Rep_base *old_rep = rep_from_data(__imp_);
98*c05d8e5dSAndroid Build Coastguard Worker     __imp_ = s.__imp_;
99*c05d8e5dSAndroid Build Coastguard Worker     if (__uses_refcount())
100*c05d8e5dSAndroid Build Coastguard Worker         __libcpp_atomic_add(&rep_from_data(__imp_)->count, 1);
101*c05d8e5dSAndroid Build Coastguard Worker     if (adjust_old_count)
102*c05d8e5dSAndroid Build Coastguard Worker     {
103*c05d8e5dSAndroid Build Coastguard Worker         if (__libcpp_atomic_add(&old_rep->count, count_t(-1)) < 0)
104*c05d8e5dSAndroid Build Coastguard Worker         {
105*c05d8e5dSAndroid Build Coastguard Worker             ::operator delete(old_rep);
106*c05d8e5dSAndroid Build Coastguard Worker         }
107*c05d8e5dSAndroid Build Coastguard Worker     }
108*c05d8e5dSAndroid Build Coastguard Worker     return *this;
109*c05d8e5dSAndroid Build Coastguard Worker }
110*c05d8e5dSAndroid Build Coastguard Worker 
111*c05d8e5dSAndroid Build Coastguard Worker inline
~__libcpp_refstring()112*c05d8e5dSAndroid Build Coastguard Worker __libcpp_refstring::~__libcpp_refstring() {
113*c05d8e5dSAndroid Build Coastguard Worker     if (__uses_refcount()) {
114*c05d8e5dSAndroid Build Coastguard Worker         _Rep_base* rep = rep_from_data(__imp_);
115*c05d8e5dSAndroid Build Coastguard Worker         if (__libcpp_atomic_add(&rep->count, count_t(-1)) < 0) {
116*c05d8e5dSAndroid Build Coastguard Worker             ::operator delete(rep);
117*c05d8e5dSAndroid Build Coastguard Worker         }
118*c05d8e5dSAndroid Build Coastguard Worker     }
119*c05d8e5dSAndroid Build Coastguard Worker }
120*c05d8e5dSAndroid Build Coastguard Worker 
121*c05d8e5dSAndroid Build Coastguard Worker inline
__uses_refcount()122*c05d8e5dSAndroid Build Coastguard Worker bool __libcpp_refstring::__uses_refcount() const {
123*c05d8e5dSAndroid Build Coastguard Worker #ifdef __APPLE__
124*c05d8e5dSAndroid Build Coastguard Worker     return __imp_ != get_gcc_empty_string_storage();
125*c05d8e5dSAndroid Build Coastguard Worker #else
126*c05d8e5dSAndroid Build Coastguard Worker     return true;
127*c05d8e5dSAndroid Build Coastguard Worker #endif
128*c05d8e5dSAndroid Build Coastguard Worker }
129*c05d8e5dSAndroid Build Coastguard Worker 
130*c05d8e5dSAndroid Build Coastguard Worker _LIBCPP_END_NAMESPACE_STD
131*c05d8e5dSAndroid Build Coastguard Worker 
132*c05d8e5dSAndroid Build Coastguard Worker #endif //_LIBCPPABI_REFSTRING_H
133