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 178 : string::
41 : string(
42 : char const* s,
43 178 : storage_ptr sp)
44 178 : : sp_(std::move(sp))
45 : {
46 178 : assign(s);
47 178 : }
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 158 : string::
67 : string(
68 : string const& other,
69 158 : storage_ptr sp)
70 158 : : sp_(std::move(sp))
71 : {
72 158 : assign(other);
73 158 : }
74 :
75 355 : string::
76 : string(
77 : string&& other,
78 355 : storage_ptr sp)
79 355 : : sp_(std::move(sp))
80 : {
81 355 : assign(std::move(other));
82 355 : }
83 :
84 17893 : string::
85 : string(
86 : string_view s,
87 17893 : storage_ptr sp)
88 17893 : : sp_(std::move(sp))
89 : {
90 17893 : assign(s);
91 17893 : }
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 210 : string::
144 : assign(
145 : string const& other)
146 : {
147 210 : if(this == &other)
148 1 : return *this;
149 209 : return assign(
150 : other.data(),
151 179 : other.size());
152 : }
153 :
154 : string&
155 379 : string::
156 : assign(string&& other)
157 : {
158 379 : if( &other == this )
159 1 : return *this;
160 :
161 378 : 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 38 : return assign(other);
171 : }
172 :
173 : string&
174 18393 : string::
175 : assign(
176 : char const* s,
177 : size_type count)
178 : {
179 18393 : auto const p = impl_.data();
180 18393 : if(detail::ptr_in_range(p, p + impl_.size(), s))
181 : {
182 3 : std::char_traits<char>::move(p, s, count);
183 3 : impl_.term(count);
184 : }
185 : else
186 : {
187 18264 : std::char_traits<char>::copy(
188 18390 : impl_.assign(count, sp_),
189 : s, count);
190 : }
191 18267 : return *this;
192 : }
193 :
194 : string&
195 192 : string::
196 : assign(
197 : char const* s)
198 : {
199 192 : return assign(s, std::char_traits<
200 189 : char>::length(s));
201 : }
202 :
203 : //----------------------------------------------------------
204 : //
205 : // Capacity
206 : //
207 : //----------------------------------------------------------
208 :
209 : void
210 7 : string::
211 : shrink_to_fit()
212 : {
213 7 : impl_.shrink_to_fit(sp_);
214 7 : }
215 :
216 : //----------------------------------------------------------
217 : //
218 : // Access
219 : //
220 : //----------------------------------------------------------
221 :
222 : system::result<char&>
223 12 : string::try_at(std::size_t pos) noexcept
224 : {
225 12 : if( pos < size() )
226 10 : return impl_.data()[pos];
227 :
228 2 : system::error_code ec;
229 2 : BOOST_JSON_FAIL(ec, error::out_of_range);
230 2 : return ec;
231 : }
232 :
233 : system::result<char const&>
234 20 : string::try_at(std::size_t pos) const noexcept
235 : {
236 20 : if( pos < size() )
237 18 : return impl_.data()[pos];
238 :
239 2 : system::error_code ec;
240 2 : BOOST_JSON_FAIL(ec, error::out_of_range);
241 2 : return ec;
242 : }
243 :
244 : char const&
245 18 : string::at(std::size_t pos, source_location const& loc) const
246 : {
247 18 : return try_at(pos).value(loc);
248 : }
249 :
250 : //----------------------------------------------------------
251 : //
252 : // Operations
253 : //
254 : //----------------------------------------------------------
255 :
256 : void
257 2 : string::
258 : clear() noexcept
259 : {
260 2 : impl_.term(0);
261 2 : }
262 :
263 : //----------------------------------------------------------
264 :
265 : void
266 148 : string::
267 : push_back(char ch)
268 : {
269 148 : *impl_.append(1, sp_) = ch;
270 146 : }
271 :
272 : void
273 29 : string::
274 : pop_back()
275 : {
276 29 : back() = 0;
277 29 : impl_.size(impl_.size() - 1);
278 29 : }
279 :
280 : //----------------------------------------------------------
281 :
282 : string&
283 4 : string::
284 : append(size_type count, char ch)
285 : {
286 2 : std::char_traits<char>::assign(
287 4 : impl_.append(count, sp_),
288 : count, ch);
289 2 : return *this;
290 : }
291 :
292 : string&
293 55 : string::
294 : append(string_view sv)
295 : {
296 55 : auto const p = impl_.data();
297 55 : if(detail::ptr_in_range(p, p + impl_.size(), sv.data()))
298 : {
299 : // sv aliases our own storage; appending may reallocate and free the
300 : // buffer sv points into, so copy from the relocated offset afterwards
301 10 : auto const offset = sv.data() - p;
302 10 : auto const dest = impl_.append(sv.size(), sp_);
303 8 : std::char_traits<char>::copy(
304 8 : dest, impl_.data() + offset, sv.size());
305 : }
306 : else
307 : {
308 90 : std::char_traits<char>::copy(
309 45 : impl_.append(sv.size(), sp_),
310 : sv.data(), sv.size());
311 : }
312 40 : return *this;
313 : }
314 :
315 : //----------------------------------------------------------
316 :
317 : string&
318 27 : string::
319 : insert(
320 : size_type pos,
321 : string_view sv)
322 : {
323 27 : impl_.insert(pos, sv.data(), sv.size(), sp_);
324 17 : return *this;
325 : }
326 :
327 : string&
328 11 : string::
329 : insert(
330 : std::size_t pos,
331 : std::size_t count,
332 : char ch)
333 : {
334 6 : std::char_traits<char>::assign(
335 11 : impl_.insert_unchecked(pos, count, sp_),
336 : count, ch);
337 6 : return *this;
338 : }
339 :
340 : //----------------------------------------------------------
341 :
342 : string&
343 19 : string::
344 : replace(
345 : std::size_t pos,
346 : std::size_t count,
347 : string_view sv)
348 : {
349 19 : impl_.replace(pos, count, sv.data(), sv.size(), sp_);
350 15 : return *this;
351 : }
352 :
353 : string&
354 11 : string::
355 : replace(
356 : std::size_t pos,
357 : std::size_t count,
358 : std::size_t count2,
359 : char ch)
360 : {
361 7 : std::char_traits<char>::assign(
362 11 : impl_.replace_unchecked(pos, count, count2, sp_),
363 : count2, ch);
364 7 : return *this;
365 : }
366 :
367 : //----------------------------------------------------------
368 :
369 : string&
370 10 : string::
371 : erase(
372 : size_type pos,
373 : size_type count)
374 : {
375 10 : if(pos > impl_.size())
376 : {
377 : BOOST_STATIC_CONSTEXPR source_location loc = BOOST_CURRENT_LOCATION;
378 1 : detail::throw_system_error( error::out_of_range, &loc );
379 : }
380 9 : if( count > impl_.size() - pos)
381 4 : count = impl_.size() - pos;
382 9 : std::char_traits<char>::move(
383 9 : impl_.data() + pos,
384 9 : impl_.data() + pos + count,
385 9 : impl_.size() - pos - count + 1);
386 9 : impl_.term(impl_.size() - count);
387 9 : return *this;
388 : }
389 :
390 : auto
391 2 : string::
392 : erase(const_iterator pos) ->
393 : iterator
394 : {
395 2 : return erase(pos, pos+1);
396 : }
397 :
398 : auto
399 3 : string::
400 : erase(
401 : const_iterator first,
402 : const_iterator last) ->
403 : iterator
404 : {
405 3 : auto const pos = first - begin();
406 3 : auto const count = last - first;
407 3 : erase(pos, count);
408 3 : return data() + pos;
409 : }
410 :
411 : //----------------------------------------------------------
412 :
413 : void
414 66 : string::
415 : resize(size_type count, char ch)
416 : {
417 66 : if(count <= impl_.size())
418 : {
419 25 : impl_.term(count);
420 25 : return;
421 : }
422 :
423 41 : reserve(count);
424 35 : std::char_traits<char>::assign(
425 : impl_.end(),
426 35 : count - impl_.size(),
427 : ch);
428 35 : grow(count - size());
429 : }
430 :
431 : //----------------------------------------------------------
432 :
433 : void
434 4 : string::
435 : swap(string& other)
436 : {
437 4 : if(*sp_ == *other.sp_)
438 : {
439 3 : std::swap(impl_, other.impl_);
440 3 : return;
441 : }
442 : string temp1(
443 1 : std::move(*this), other.sp_);
444 : string temp2(
445 1 : std::move(other), sp_);
446 1 : this->~string();
447 1 : ::new(this) string(pilfer(temp2));
448 1 : other.~string();
449 1 : ::new(&other) string(pilfer(temp1));
450 1 : }
451 :
452 : //----------------------------------------------------------
453 :
454 : void
455 9686 : string::
456 : reserve_impl(size_type new_cap)
457 : {
458 9686 : BOOST_ASSERT(
459 : new_cap >= impl_.capacity());
460 9686 : if(new_cap > impl_.capacity())
461 : {
462 : // grow
463 9686 : new_cap = detail::string_impl::growth(
464 : new_cap, impl_.capacity());
465 9685 : detail::string_impl tmp(new_cap, sp_);
466 9675 : std::char_traits<char>::copy(tmp.data(),
467 9675 : impl_.data(), impl_.size() + 1);
468 9675 : tmp.size(impl_.size());
469 9675 : impl_.destroy(sp_);
470 9675 : impl_ = tmp;
471 9675 : return;
472 : }
473 : }
474 :
475 : } // namespace json
476 : } // namespace boost
477 :
478 : //----------------------------------------------------------
479 :
480 : std::size_t
481 3 : std::hash< ::boost::json::string >::operator()(
482 : ::boost::json::string const& js ) const noexcept
483 : {
484 3 : return ::boost::hash< ::boost::json::string >()( js );
485 : }
486 :
487 : #endif
|