Remove building with NOCRYPTO option
[minix.git] / external / bsd / libc++ / dist / libcxx / include / __refstring
blob61ccc75122a5ae4553d2d61569301d6a9e2df1fa
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 //===----------------------------------------------------------------------===//
10 #ifndef _LIBCPP___REFSTRING
11 #define _LIBCPP___REFSTRING
13 #include <__config>
14 #include <cstddef>
15 #include <cstring>
16 #ifdef __APPLE__
17 #include <dlfcn.h>
18 #include <mach-o/dyld.h>
19 #endif
21 _LIBCPP_BEGIN_NAMESPACE_STD
23 class _LIBCPP_HIDDEN __libcpp_refstring
25 private:
26     const char* str_;
28     typedef int count_t;
30     struct _Rep_base
31     {
32         std::size_t len;
33         std::size_t cap;
34         count_t     count;
35     };
37     static
38     _Rep_base*
39     rep_from_data(const char *data_) _NOEXCEPT
40     {
41         char *data = const_cast<char *>(data_);
42         return reinterpret_cast<_Rep_base *>(data - sizeof(_Rep_base));
43     }
44     static
45     char *
46     data_from_rep(_Rep_base *rep) _NOEXCEPT
47     {
48         char *data = reinterpret_cast<char *>(rep);
49         return data + sizeof(*rep);
50     }
52 #ifdef __APPLE__
53     static
54     const char*
55     compute_gcc_empty_string_storage() _NOEXCEPT
56     {
57         void* handle = dlopen("/usr/lib/libstdc++.6.dylib", RTLD_NOLOAD);
58         if (handle == nullptr)
59             return nullptr;
60         void* sym = dlsym(handle, "_ZNSs4_Rep20_S_empty_rep_storageE");
61         if (sym == nullptr)
62             return nullptr;
63         return data_from_rep(reinterpret_cast<_Rep_base *>(sym));
64     }
66     static
67     const char*
68     get_gcc_empty_string_storage() _NOEXCEPT
69     {
70         static const char* p = compute_gcc_empty_string_storage();
71         return p;
72     }
74     bool
75     uses_refcount() const
76     {
77         return str_ != get_gcc_empty_string_storage();
78     }
79 #else
80     bool
81     uses_refcount() const
82     {
83         return true;
84     }
85 #endif
87 public:
88     explicit __libcpp_refstring(const char* msg) {
89         std::size_t len = strlen(msg);
90         _Rep_base* rep = static_cast<_Rep_base *>(::operator new(sizeof(*rep) + len + 1));
91         rep->len = len;
92         rep->cap = len;
93         rep->count = 0;
94         char *data = data_from_rep(rep);
95         std::memcpy(data, msg, len + 1);
96         str_ = data;
97     }
99     __libcpp_refstring(const __libcpp_refstring& s) _NOEXCEPT : str_(s.str_)
100     {
101         if (uses_refcount())
102             __sync_add_and_fetch(&rep_from_data(str_)->count, 1);
103     }
105     __libcpp_refstring& operator=(const __libcpp_refstring& s) _NOEXCEPT
106     {
107         bool adjust_old_count = uses_refcount();
108         struct _Rep_base *old_rep = rep_from_data(str_);
109         str_ = s.str_;
110         if (uses_refcount())
111             __sync_add_and_fetch(&rep_from_data(str_)->count, 1);
112         if (adjust_old_count)
113         {
114             if (__sync_add_and_fetch(&old_rep->count, count_t(-1)) < 0)
115             {
116                 ::operator delete(old_rep);
117             }
118         }
119         return *this;
120     }
122     ~__libcpp_refstring()
123     {
124         if (uses_refcount())
125         {
126             _Rep_base* rep = rep_from_data(str_);
127             if (__sync_add_and_fetch(&rep->count, count_t(-1)) < 0)
128             {
129                 ::operator delete(rep);
130             }
131         }
132     }
134     const char* c_str() const _NOEXCEPT {return str_;}
137 _LIBCPP_END_NAMESPACE_STD
139 #endif //_LIBCPP___REFSTRING