TLA Line data Source code
1 : //
2 : // Copyright (c) 2019 Vinnie Falco (vinnie.falco@gmail.com)
3 : //
4 : // Distributed under the Boost Software License, Version 1.0. (See accompanying
5 : // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
6 : //
7 : // Official repository: https://github.com/boostorg/json
8 : //
9 :
10 : #ifndef BOOST_JSON_IMPL_STRING_IPP
11 : #define BOOST_JSON_IMPL_STRING_IPP
12 :
13 : #include <boost/json/detail/except.hpp>
14 : #include <algorithm>
15 : #include <new>
16 : #include <ostream>
17 : #include <stdexcept>
18 : #include <string>
19 : #include <utility>
20 :
21 : namespace boost {
22 : namespace json {
23 :
24 : //----------------------------------------------------------
25 : //
26 : // Construction
27 : //
28 : //----------------------------------------------------------
29 :
30 HIT 78 : string::
31 : string(
32 : std::size_t count,
33 : char ch,
34 78 : storage_ptr sp)
35 78 : : sp_(std::move(sp))
36 : {
37 78 : assign(count, ch);
38 78 : }
39 :
40 175 : string::
41 : string(
42 : char const* s,
43 175 : storage_ptr sp)
44 175 : : sp_(std::move(sp))
45 : {
46 175 : assign(s);
47 175 : }
48 :
49 4 : string::
50 : string(
51 : char const* s,
52 : std::size_t count,
53 4 : storage_ptr sp)
54 4 : : sp_(std::move(sp))
55 : {
56 4 : assign(s, count);
57 4 : }
58 :
59 8 : string::
60 8 : string(string const& other)
61 8 : : sp_(other.sp_)
62 : {
63 8 : assign(other);
64 8 : }
65 :
66 145 : string::
67 : string(
68 : string const& other,
69 145 : storage_ptr sp)
70 145 : : sp_(std::move(sp))
71 : {
72 145 : assign(other);
73 145 : }
74 :
75 351 : string::
76 : string(
77 : string&& other,
78 351 : storage_ptr sp)
79 351 : : sp_(std::move(sp))
80 : {
81 351 : assign(std::move(other));
82 351 : }
83 :
84 17890 : string::
85 : string(
86 : string_view s,
87 17890 : storage_ptr sp)
88 17890 : : sp_(std::move(sp))
89 : {
90 17890 : assign(s);
91 17890 : }
92 :
93 : //----------------------------------------------------------
94 : //
95 : // Assignment
96 : //
97 : //----------------------------------------------------------
98 :
99 : string&
100 6 : string::
101 : operator=(string const& other)
102 : {
103 6 : return assign(other);
104 : }
105 :
106 : string&
107 10 : string::
108 : operator=(string&& other)
109 : {
110 10 : return assign(std::move(other));
111 : }
112 :
113 : string&
114 9 : string::
115 : operator=(char const* s)
116 : {
117 9 : return assign(s);
118 : }
119 :
120 : string&
121 8 : string::
122 : operator=(string_view s)
123 : {
124 8 : return assign(s);
125 : }
126 :
127 :
128 :
129 : string&
130 83 : string::
131 : assign(
132 : size_type count,
133 : char ch)
134 : {
135 64 : std::char_traits<char>::assign(
136 83 : impl_.assign(count, sp_),
137 : count,
138 : ch);
139 64 : return *this;
140 : }
141 :
142 : string&
143 193 : string::
144 : assign(
145 : string const& other)
146 : {
147 193 : if(this == &other)
148 1 : return *this;
149 192 : return assign(
150 : other.data(),
151 165 : other.size());
152 : }
153 :
154 : string&
155 375 : string::
156 : assign(string&& other)
157 : {
158 375 : if( &other == this )
159 1 : return *this;
160 :
161 374 : if(*sp_ == *other.sp_)
162 : {
163 340 : impl_.destroy(sp_);
164 340 : impl_ = other.impl_;
165 340 : ::new(&other.impl_) detail::string_impl();
166 340 : return *this;
167 : }
168 :
169 : // copy
170 34 : return assign(other);
171 : }
172 :
173 : string&
174 18367 : string::
175 : assign(
176 : char const* s,
177 : size_type count)
178 : {
179 18244 : std::char_traits<char>::copy(
180 18367 : impl_.assign(count, sp_),
181 : s, count);
182 18244 : return *this;
183 : }
184 :
185 : string&
186 189 : string::
187 : assign(
188 : char const* s)
189 : {
190 189 : return assign(s, std::char_traits<
191 186 : char>::length(s));
192 : }
193 :
194 : //----------------------------------------------------------
195 : //
196 : // Capacity
197 : //
198 : //----------------------------------------------------------
199 :
200 : void
201 7 : string::
202 : shrink_to_fit()
203 : {
204 7 : impl_.shrink_to_fit(sp_);
205 7 : }
206 :
207 : //----------------------------------------------------------
208 : //
209 : // Access
210 : //
211 : //----------------------------------------------------------
212 :
213 : system::result<char&>
214 12 : string::try_at(std::size_t pos) noexcept
215 : {
216 12 : if( pos < size() )
217 10 : return impl_.data()[pos];
218 :
219 2 : system::error_code ec;
220 2 : BOOST_JSON_FAIL(ec, error::out_of_range);
221 2 : return ec;
222 : }
223 :
224 : system::result<char const&>
225 20 : string::try_at(std::size_t pos) const noexcept
226 : {
227 20 : if( pos < size() )
228 18 : return impl_.data()[pos];
229 :
230 2 : system::error_code ec;
231 2 : BOOST_JSON_FAIL(ec, error::out_of_range);
232 2 : return ec;
233 : }
234 :
235 : char const&
236 18 : string::at(std::size_t pos, source_location const& loc) const
237 : {
238 18 : return try_at(pos).value(loc);
239 : }
240 :
241 : //----------------------------------------------------------
242 : //
243 : // Operations
244 : //
245 : //----------------------------------------------------------
246 :
247 : void
248 2 : string::
249 : clear() noexcept
250 : {
251 2 : impl_.term(0);
252 2 : }
253 :
254 : //----------------------------------------------------------
255 :
256 : void
257 148 : string::
258 : push_back(char ch)
259 : {
260 148 : *impl_.append(1, sp_) = ch;
261 146 : }
262 :
263 : void
264 29 : string::
265 : pop_back()
266 : {
267 29 : back() = 0;
268 29 : impl_.size(impl_.size() - 1);
269 29 : }
270 :
271 : //----------------------------------------------------------
272 :
273 : string&
274 4 : string::
275 : append(size_type count, char ch)
276 : {
277 2 : std::char_traits<char>::assign(
278 4 : impl_.append(count, sp_),
279 : count, ch);
280 2 : return *this;
281 : }
282 :
283 : string&
284 55 : string::
285 : append(string_view sv)
286 : {
287 55 : auto const p = impl_.data();
288 55 : if(detail::ptr_in_range(p, p + impl_.size(), sv.data()))
289 : {
290 : // sv aliases our own storage; appending may reallocate and free the
291 : // buffer sv points into, so copy from the relocated offset afterwards
292 10 : auto const offset = sv.data() - p;
293 10 : auto const dest = impl_.append(sv.size(), sp_);
294 8 : std::char_traits<char>::copy(
295 8 : dest, impl_.data() + offset, sv.size());
296 : }
297 : else
298 : {
299 90 : std::char_traits<char>::copy(
300 45 : impl_.append(sv.size(), sp_),
301 : sv.data(), sv.size());
302 : }
303 40 : return *this;
304 : }
305 :
306 : //----------------------------------------------------------
307 :
308 : string&
309 27 : string::
310 : insert(
311 : size_type pos,
312 : string_view sv)
313 : {
314 27 : impl_.insert(pos, sv.data(), sv.size(), sp_);
315 17 : return *this;
316 : }
317 :
318 : string&
319 11 : string::
320 : insert(
321 : std::size_t pos,
322 : std::size_t count,
323 : char ch)
324 : {
325 6 : std::char_traits<char>::assign(
326 11 : impl_.insert_unchecked(pos, count, sp_),
327 : count, ch);
328 6 : return *this;
329 : }
330 :
331 : //----------------------------------------------------------
332 :
333 : string&
334 19 : string::
335 : replace(
336 : std::size_t pos,
337 : std::size_t count,
338 : string_view sv)
339 : {
340 19 : impl_.replace(pos, count, sv.data(), sv.size(), sp_);
341 15 : return *this;
342 : }
343 :
344 : string&
345 11 : string::
346 : replace(
347 : std::size_t pos,
348 : std::size_t count,
349 : std::size_t count2,
350 : char ch)
351 : {
352 7 : std::char_traits<char>::assign(
353 11 : impl_.replace_unchecked(pos, count, count2, sp_),
354 : count2, ch);
355 7 : return *this;
356 : }
357 :
358 : //----------------------------------------------------------
359 :
360 : string&
361 10 : string::
362 : erase(
363 : size_type pos,
364 : size_type count)
365 : {
366 10 : if(pos > impl_.size())
367 : {
368 : BOOST_STATIC_CONSTEXPR source_location loc = BOOST_CURRENT_LOCATION;
369 1 : detail::throw_system_error( error::out_of_range, &loc );
370 : }
371 9 : if( count > impl_.size() - pos)
372 4 : count = impl_.size() - pos;
373 9 : std::char_traits<char>::move(
374 9 : impl_.data() + pos,
375 9 : impl_.data() + pos + count,
376 9 : impl_.size() - pos - count + 1);
377 9 : impl_.term(impl_.size() - count);
378 9 : return *this;
379 : }
380 :
381 : auto
382 2 : string::
383 : erase(const_iterator pos) ->
384 : iterator
385 : {
386 2 : return erase(pos, pos+1);
387 : }
388 :
389 : auto
390 3 : string::
391 : erase(
392 : const_iterator first,
393 : const_iterator last) ->
394 : iterator
395 : {
396 3 : auto const pos = first - begin();
397 3 : auto const count = last - first;
398 3 : erase(pos, count);
399 3 : return data() + pos;
400 : }
401 :
402 : //----------------------------------------------------------
403 :
404 : void
405 66 : string::
406 : resize(size_type count, char ch)
407 : {
408 66 : if(count <= impl_.size())
409 : {
410 25 : impl_.term(count);
411 25 : return;
412 : }
413 :
414 41 : reserve(count);
415 35 : std::char_traits<char>::assign(
416 : impl_.end(),
417 35 : count - impl_.size(),
418 : ch);
419 35 : grow(count - size());
420 : }
421 :
422 : //----------------------------------------------------------
423 :
424 : void
425 4 : string::
426 : swap(string& other)
427 : {
428 4 : if(*sp_ == *other.sp_)
429 : {
430 3 : std::swap(impl_, other.impl_);
431 3 : return;
432 : }
433 : string temp1(
434 1 : std::move(*this), other.sp_);
435 : string temp2(
436 1 : std::move(other), sp_);
437 1 : this->~string();
438 1 : ::new(this) string(pilfer(temp2));
439 1 : other.~string();
440 1 : ::new(&other) string(pilfer(temp1));
441 1 : }
442 :
443 : //----------------------------------------------------------
444 :
445 : void
446 9686 : string::
447 : reserve_impl(size_type new_cap)
448 : {
449 9686 : BOOST_ASSERT(
450 : new_cap >= impl_.capacity());
451 9686 : if(new_cap > impl_.capacity())
452 : {
453 : // grow
454 9686 : new_cap = detail::string_impl::growth(
455 : new_cap, impl_.capacity());
456 9685 : detail::string_impl tmp(new_cap, sp_);
457 9675 : std::char_traits<char>::copy(tmp.data(),
458 9675 : impl_.data(), impl_.size() + 1);
459 9675 : tmp.size(impl_.size());
460 9675 : impl_.destroy(sp_);
461 9675 : impl_ = tmp;
462 9675 : return;
463 : }
464 : }
465 :
466 : } // namespace json
467 : } // namespace boost
468 :
469 : //----------------------------------------------------------
470 :
471 : std::size_t
472 3 : std::hash< ::boost::json::string >::operator()(
473 : ::boost::json::string const& js ) const noexcept
474 : {
475 3 : return ::boost::hash< ::boost::json::string >()( js );
476 : }
477 :
478 : #endif
|