impl/string.hpp

100.0% Lines (66/66) 89.5% Functions (17/19)
Line TLA Hits 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_HPP
11 #define BOOST_JSON_IMPL_STRING_HPP
12
13 #include <utility>
14
15 namespace boost {
16 namespace json {
17
18 30296x string::
19 string(
20 detail::key_t const&,
21 string_view s,
22 30296x storage_ptr sp)
23 30296x : sp_(std::move(sp))
24 30296x , impl_(detail::key_t{},
25 30296x s, sp_)
26 {
27 30296x }
28
29 8060x string::
30 string(
31 detail::key_t const&,
32 string_view s1,
33 string_view s2,
34 8060x storage_ptr sp)
35 8060x : sp_(std::move(sp))
36 8060x , impl_(detail::key_t{},
37 8060x s1, s2, sp_)
38 {
39 8060x }
40
41 template<class InputIt, class>
42 31x string::
43 string(
44 InputIt first,
45 InputIt last,
46 storage_ptr sp)
47 31x : sp_(std::move(sp))
48 31x , impl_(first, last, sp_,
49 21x iter_cat<InputIt>{})
50 {
51 31x }
52
53 template<class InputIt, class>
54 string&
55 13x string::
56 assign(
57 InputIt first,
58 InputIt last)
59 {
60 13x assign(first, last,
61 iter_cat<InputIt>{});
62 10x return *this;
63 }
64
65 template<class InputIt, class>
66 string&
67 6x string::
68 append(InputIt first, InputIt last)
69 {
70 6x append(first, last,
71 iter_cat<InputIt>{});
72 4x return *this;
73 }
74
75 // KRYSTIAN TODO: this can be done without copies when
76 // reallocation is not needed, when the iterator is a
77 // FowardIterator or better, as we can use std::distance
78 template<class InputIt, class>
79 auto
80 6x string::
81 insert(
82 size_type pos,
83 InputIt first,
84 InputIt last) ->
85 string&
86 {
87 struct cleanup
88 {
89 detail::string_impl& s;
90 storage_ptr const& sp;
91
92 ~cleanup()
93 {
94 s.destroy(sp);
95 }
96 };
97
98 // We use the default storage because
99 // the allocation is immediately freed.
100 6x storage_ptr dsp;
101 6x detail::string_impl tmp(
102 first, last, dsp,
103 iter_cat<InputIt>{});
104 6x cleanup c{tmp, dsp};
105 6x std::memcpy(
106 6x impl_.insert_unchecked(pos, tmp.size(), sp_),
107 6x tmp.data(),
108 tmp.size());
109 4x return *this;
110 8x }
111
112 // KRYSTIAN TODO: this can be done without copies when
113 // reallocation is not needed, when the iterator is a
114 // FowardIterator or better, as we can use std::distance
115 template<class InputIt, class>
116 auto
117 string::
118 replace(
119 const_iterator first,
120 const_iterator last,
121 InputIt first2,
122 InputIt last2) ->
123 string&
124 {
125 struct cleanup
126 {
127 detail::string_impl& s;
128 storage_ptr const& sp;
129
130 ~cleanup()
131 {
132 s.destroy(sp);
133 }
134 };
135
136 // We use the default storage because
137 // the allocation is immediately freed.
138 storage_ptr dsp;
139 detail::string_impl tmp(
140 first2, last2, dsp,
141 iter_cat<InputIt>{});
142 cleanup c{tmp, dsp};
143 std::memcpy(
144 impl_.replace_unchecked(
145 first - begin(),
146 last - first,
147 tmp.size(),
148 sp_),
149 tmp.data(),
150 tmp.size());
151 return *this;
152 }
153
154 //----------------------------------------------------------
155
156 template<class InputIt>
157 void
158 6x string::
159 assign(
160 InputIt first,
161 InputIt last,
162 std::random_access_iterator_tag)
163 {
164 6x auto dest = impl_.assign(static_cast<
165 6x size_type>(last - first), sp_);
166 63x while(first != last)
167 58x *dest++ = *first++;
168 5x }
169
170 template<class InputIt>
171 void
172 7x string::
173 assign(
174 InputIt first,
175 InputIt last,
176 std::input_iterator_tag)
177 {
178 7x if(first == last)
179 {
180 1x impl_.term(0);
181 1x return;
182 }
183 6x detail::string_impl tmp(
184 6x first, last, sp_,
185 std::input_iterator_tag{});
186 4x impl_.destroy(sp_);
187 4x impl_ = tmp;
188 }
189
190 template<class InputIt>
191 void
192 3x string::
193 append(
194 InputIt first,
195 InputIt last,
196 std::random_access_iterator_tag)
197 {
198
199 3x auto const n = static_cast<
200 3x size_type>(last - first);
201 3x char* out = impl_.append(n, sp_);
202 #if defined(_MSC_VER) && _MSC_VER <= 1900
203 while( first != last )
204 *out++ = *first++;
205 #else
206 2x std::copy(first, last, out);
207 #endif
208 2x }
209
210 template<class InputIt>
211 void
212 3x string::
213 append(
214 InputIt first,
215 InputIt last,
216 std::input_iterator_tag)
217 {
218 struct cleanup
219 {
220 detail::string_impl& s;
221 storage_ptr const& sp;
222
223 3x ~cleanup()
224 {
225 3x s.destroy(sp);
226 3x }
227 };
228
229 // We use the default storage because
230 // the allocation is immediately freed.
231 3x storage_ptr dsp;
232 3x detail::string_impl tmp(
233 first, last, dsp,
234 std::input_iterator_tag{});
235 3x cleanup c{tmp, dsp};
236 3x std::memcpy(
237 3x impl_.append(tmp.size(), sp_),
238 3x tmp.data(), tmp.size());
239 4x }
240
241 char&
242 15x string::at(std::size_t pos, source_location const& loc)
243 {
244
245 15x auto const& self = *this;
246 15x return const_cast< char& >( self.at(pos, loc) );
247 }
248
249 } // namespace json
250 } // namespace boost
251
252 #endif
253