Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
wine-mirror
GitHub Repository: wine-mirror/wine
Path: blob/master/libs/c++/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
#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
129
130