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