1 | #include <climits> |
2 | #include <memory> |
3 | #include <type_traits> |
4 | |
5 | #if REVISION == 0 |
6 | // Pre-c3d0205ee771 layout. |
7 | #define SUBCLASS_PADDING |
8 | #endif |
9 | #if REVISION <= 1 |
10 | // Pre-D123580 layout. |
11 | #define BITMASKS |
12 | #endif |
13 | #if REVISION <= 2 |
14 | // Pre-D125496 layout. |
15 | #define SHORT_UNION |
16 | #endif |
17 | #if REVISION == 3 |
18 | // Pre-D128285 layout. |
19 | #define PACKED_ANON_STRUCT |
20 | #endif |
21 | // REVISION == 4: current layout |
22 | |
23 | #ifdef PACKED_ANON_STRUCT |
24 | #define BEGIN_PACKED_ANON_STRUCT struct __attribute__((packed)) { |
25 | #define END_PACKED_ANON_STRUCT }; |
26 | #else |
27 | #define BEGIN_PACKED_ANON_STRUCT |
28 | #define END_PACKED_ANON_STRUCT |
29 | #endif |
30 | |
31 | |
32 | namespace std { |
33 | namespace __lldb { |
34 | |
35 | template <class _Tp, int _Idx, |
36 | bool _CanBeEmptyBase = |
37 | std::is_empty<_Tp>::value && !std::is_final<_Tp>::value> |
38 | struct __compressed_pair_elem { |
39 | explicit __compressed_pair_elem(_Tp __t) : __value_(__t) {} |
40 | |
41 | _Tp &__get() { return __value_; } |
42 | |
43 | private: |
44 | _Tp __value_; |
45 | }; |
46 | |
47 | template <class _Tp, int _Idx> |
48 | struct __compressed_pair_elem<_Tp, _Idx, true> : private _Tp { |
49 | explicit __compressed_pair_elem(_Tp __t) : _Tp(__t) {} |
50 | |
51 | _Tp &__get() { return *this; } |
52 | }; |
53 | |
54 | template <class _T1, class _T2> |
55 | class __compressed_pair : private __compressed_pair_elem<_T1, 0>, |
56 | private __compressed_pair_elem<_T2, 1> { |
57 | public: |
58 | using _Base1 = __compressed_pair_elem<_T1, 0>; |
59 | using _Base2 = __compressed_pair_elem<_T2, 1>; |
60 | |
61 | explicit __compressed_pair(_T1 __t1, _T2 __t2) : _Base1(__t1), _Base2(__t2) {} |
62 | |
63 | _T1 &first() { return static_cast<_Base1 &>(*this).__get(); } |
64 | }; |
65 | |
66 | #if defined(ALTERNATE_LAYOUT) && defined(SUBCLASS_PADDING) |
67 | template <class _CharT, size_t = sizeof(_CharT)> struct __padding { |
68 | unsigned char __xx[sizeof(_CharT) - 1]; |
69 | }; |
70 | |
71 | template <class _CharT> struct __padding<_CharT, 1> {}; |
72 | #endif |
73 | |
74 | template <class _CharT, class _Traits, class _Allocator> class basic_string { |
75 | public: |
76 | typedef _CharT value_type; |
77 | typedef _Allocator allocator_type; |
78 | typedef allocator_traits<allocator_type> __alloc_traits; |
79 | typedef typename __alloc_traits::size_type size_type; |
80 | typedef typename __alloc_traits::pointer pointer; |
81 | |
82 | #ifdef ALTERNATE_LAYOUT |
83 | |
84 | struct __long { |
85 | pointer __data_; |
86 | size_type __size_; |
87 | #ifdef BITMASKS |
88 | size_type __cap_; |
89 | #else |
90 | size_type __cap_ : sizeof(size_type) * CHAR_BIT - 1; |
91 | size_type __is_long_ : 1; |
92 | #endif |
93 | }; |
94 | |
95 | enum { |
96 | __min_cap = (sizeof(__long) - 1) / sizeof(value_type) > 2 |
97 | ? (sizeof(__long) - 1) / sizeof(value_type) |
98 | : 2 |
99 | }; |
100 | |
101 | struct __short { |
102 | value_type __data_[__min_cap]; |
103 | #ifdef BITMASKS |
104 | #ifdef SUBCLASS_PADDING |
105 | struct : __padding<value_type> { |
106 | unsigned char __size_; |
107 | }; |
108 | #else |
109 | unsigned char __padding[sizeof(value_type) - 1]; |
110 | unsigned char __size_; |
111 | #endif |
112 | #else // !BITMASKS |
113 | unsigned char __size_ : 7; |
114 | unsigned char __is_long_ : 1; |
115 | #endif |
116 | }; |
117 | |
118 | #ifdef BITMASKS |
119 | #if __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__ |
120 | static const size_type __short_shift = 1; |
121 | static const size_type __long_mask = 0x1ul; |
122 | #else |
123 | static const size_type __short_shift = 0; |
124 | static const size_type __long_mask = ~(size_type(~0) >> 1); |
125 | #endif |
126 | #else // !BITMASKS |
127 | #if __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__ |
128 | static const size_type __endian_factor = 2; |
129 | #else |
130 | static const size_type __endian_factor = 1; |
131 | #endif |
132 | #endif // BITMASKS |
133 | |
134 | #else // !ALTERNATE_LAYOUT |
135 | |
136 | struct __long { |
137 | #ifdef BITMASKS |
138 | size_type __cap_; |
139 | #else |
140 | BEGIN_PACKED_ANON_STRUCT |
141 | size_type __is_long_ : 1; |
142 | size_type __cap_ : sizeof(size_type) * CHAR_BIT - 1; |
143 | END_PACKED_ANON_STRUCT |
144 | #endif |
145 | size_type __size_; |
146 | pointer __data_; |
147 | }; |
148 | |
149 | enum { |
150 | __min_cap = (sizeof(__long) - 1) / sizeof(value_type) > 2 |
151 | ? (sizeof(__long) - 1) / sizeof(value_type) |
152 | : 2 |
153 | }; |
154 | |
155 | struct __short { |
156 | #ifdef SHORT_UNION |
157 | union { |
158 | #ifdef BITMASKS |
159 | unsigned char __size_; |
160 | #else |
161 | struct { |
162 | unsigned char __is_long_ : 1; |
163 | unsigned char __size_ : 7; |
164 | }; |
165 | #endif |
166 | value_type __lx; |
167 | }; |
168 | #else |
169 | BEGIN_PACKED_ANON_STRUCT |
170 | unsigned char __is_long_ : 1; |
171 | unsigned char __size_ : 7; |
172 | END_PACKED_ANON_STRUCT |
173 | char __padding_[sizeof(value_type) - 1]; |
174 | #endif |
175 | value_type __data_[__min_cap]; |
176 | }; |
177 | |
178 | #ifdef BITMASKS |
179 | #if __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__ |
180 | static const size_type __short_shift = 0; |
181 | static const size_type __long_mask = ~(size_type(~0) >> 1); |
182 | #else |
183 | static const size_type __short_shift = 1; |
184 | static const size_type __long_mask = 0x1ul; |
185 | #endif |
186 | #else // !BITMASKS |
187 | #if __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__ |
188 | static const size_type __endian_factor = 1; |
189 | #else |
190 | static const size_type __endian_factor = 2; |
191 | #endif |
192 | #endif |
193 | |
194 | #endif // ALTERNATE_LAYOUT |
195 | |
196 | union __ulx { |
197 | __long __lx; |
198 | __short __lxx; |
199 | }; |
200 | |
201 | enum { __n_words = sizeof(__ulx) / sizeof(size_type) }; |
202 | |
203 | struct __raw { |
204 | size_type __words[__n_words]; |
205 | }; |
206 | |
207 | struct __rep { |
208 | union { |
209 | __long __l; |
210 | __short __s; |
211 | __raw __r; |
212 | }; |
213 | }; |
214 | |
215 | __compressed_pair<__rep, allocator_type> __r_; |
216 | |
217 | public: |
218 | template <size_t __N> |
219 | basic_string(unsigned char __size, const value_type (&__data)[__N]) |
220 | : __r_({}, {}) { |
221 | static_assert(__N < __min_cap, "" ); |
222 | #ifdef BITMASKS |
223 | __r_.first().__s.__size_ = __size << __short_shift; |
224 | #else |
225 | __r_.first().__s.__size_ = __size; |
226 | __r_.first().__s.__is_long_ = false; |
227 | #endif |
228 | for (size_t __i = 0; __i < __N; ++__i) |
229 | __r_.first().__s.__data_[__i] = __data[__i]; |
230 | } |
231 | basic_string(size_t __cap, size_type __size, pointer __data) : __r_({}, {}) { |
232 | #ifdef BITMASKS |
233 | __r_.first().__l.__cap_ = __cap | __long_mask; |
234 | #else |
235 | __r_.first().__l.__cap_ = __cap / __endian_factor; |
236 | __r_.first().__l.__is_long_ = true; |
237 | #endif |
238 | __r_.first().__l.__size_ = __size; |
239 | __r_.first().__l.__data_ = __data; |
240 | } |
241 | }; |
242 | |
243 | using string = basic_string<char, std::char_traits<char>, std::allocator<char>>; |
244 | |
245 | } // namespace __lldb |
246 | } // namespace std |
247 | |
248 | int main() { |
249 | char longdata[] = "I am a very long string" ; |
250 | std::__lldb::string longstring(sizeof(longdata), sizeof(longdata) - 1, |
251 | longdata); |
252 | std::__lldb::string shortstring(5, "short" ); |
253 | return 0; // Break here |
254 | } |
255 | |