xref: /minix3/external/bsd/libc++/dist/libcxx/include/__refstring (revision 0a6a1f1d05b60e214de2f05a7310ddd1f0e590e7)
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