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_HPP
11 : #define BOOST_JSON_IMPL_STRING_HPP
12 :
13 : #include <utility>
14 :
15 : namespace boost {
16 : namespace json {
17 :
18 30296 : string::
19 : string(
20 : detail::key_t const&,
21 : string_view s,
22 30296 : storage_ptr sp)
23 30296 : : sp_(std::move(sp))
24 30296 : , impl_(detail::key_t{},
25 30296 : s, sp_)
26 : {
27 30296 : }
28 :
29 8060 : string::
30 : string(
31 : detail::key_t const&,
32 : string_view s1,
33 : string_view s2,
34 8060 : storage_ptr sp)
35 8060 : : sp_(std::move(sp))
36 8060 : , impl_(detail::key_t{},
37 8060 : s1, s2, sp_)
38 : {
39 8060 : }
40 :
41 : template<class InputIt, class>
42 31 : string::
43 : string(
44 : InputIt first,
45 : InputIt last,
46 : storage_ptr sp)
47 31 : : sp_(std::move(sp))
48 31 : , impl_(first, last, sp_,
49 21 : iter_cat<InputIt>{})
50 : {
51 31 : }
52 :
53 : template<class InputIt, class>
54 : string&
55 13 : string::
56 : assign(
57 : InputIt first,
58 : InputIt last)
59 : {
60 13 : assign(first, last,
61 : iter_cat<InputIt>{});
62 10 : return *this;
63 : }
64 :
65 : template<class InputIt, class>
66 : string&
67 6 : string::
68 : append(InputIt first, InputIt last)
69 : {
70 6 : append(first, last,
71 : iter_cat<InputIt>{});
72 4 : 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 6 : 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 6 : ~cleanup()
93 : {
94 6 : s.destroy(sp);
95 6 : }
96 : };
97 :
98 : // We use the default storage because
99 : // the allocation is immediately freed.
100 6 : storage_ptr dsp;
101 6 : detail::string_impl tmp(
102 : first, last, dsp,
103 : iter_cat<InputIt>{});
104 6 : cleanup c{tmp, dsp};
105 6 : std::memcpy(
106 6 : impl_.insert_unchecked(pos, tmp.size(), sp_),
107 6 : tmp.data(),
108 : tmp.size());
109 4 : return *this;
110 8 : }
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 6 : string::
159 : assign(
160 : InputIt first,
161 : InputIt last,
162 : std::random_access_iterator_tag)
163 : {
164 6 : auto dest = impl_.assign(static_cast<
165 6 : size_type>(last - first), sp_);
166 63 : while(first != last)
167 58 : *dest++ = *first++;
168 5 : }
169 :
170 : template<class InputIt>
171 : void
172 7 : string::
173 : assign(
174 : InputIt first,
175 : InputIt last,
176 : std::input_iterator_tag)
177 : {
178 7 : if(first == last)
179 : {
180 1 : impl_.term(0);
181 1 : return;
182 : }
183 6 : detail::string_impl tmp(
184 6 : first, last, sp_,
185 : std::input_iterator_tag{});
186 4 : impl_.destroy(sp_);
187 4 : impl_ = tmp;
188 : }
189 :
190 : template<class InputIt>
191 : void
192 3 : string::
193 : append(
194 : InputIt first,
195 : InputIt last,
196 : std::random_access_iterator_tag)
197 : {
198 :
199 3 : auto const n = static_cast<
200 3 : size_type>(last - first);
201 3 : char* out = impl_.append(n, sp_);
202 : #if defined(_MSC_VER) && _MSC_VER <= 1900
203 : while( first != last )
204 : *out++ = *first++;
205 : #else
206 2 : std::copy(first, last, out);
207 : #endif
208 2 : }
209 :
210 : template<class InputIt>
211 : void
212 3 : 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 3 : ~cleanup()
224 : {
225 3 : s.destroy(sp);
226 3 : }
227 : };
228 :
229 : // We use the default storage because
230 : // the allocation is immediately freed.
231 3 : storage_ptr dsp;
232 3 : detail::string_impl tmp(
233 : first, last, dsp,
234 : std::input_iterator_tag{});
235 3 : cleanup c{tmp, dsp};
236 3 : std::memcpy(
237 3 : impl_.append(tmp.size(), sp_),
238 3 : tmp.data(), tmp.size());
239 4 : }
240 :
241 : char&
242 15 : string::at(std::size_t pos, source_location const& loc)
243 : {
244 :
245 15 : auto const& self = *this;
246 15 : return const_cast< char& >( self.at(pos, loc) );
247 : }
248 :
249 : } // namespace json
250 : } // namespace boost
251 :
252 : #endif
|