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