44
55namespace json
66{
7+ namespace _array_impl_detail
8+ {
9+ inline void append_array (array::raw_array& dst, const array& src)
10+ {
11+ dst.reserve (dst.size () + src.size ());
12+ dst.insert (dst.end (), src.begin (), src.end ());
13+ }
14+
15+ inline void append_array_move (array::raw_array& dst, array& src)
16+ {
17+ dst.reserve (dst.size () + src.size ());
18+ dst.insert (dst.end (), std::make_move_iterator (src.begin ()), std::make_move_iterator (src.end ()));
19+ }
20+ } // namespace _array_impl_detail
21+
722inline array::array () = default;
823inline array::array (const array& rhs) = default;
924inline array::array (array&& rhs) noexcept = default;
@@ -56,7 +71,11 @@ inline bool array::erase(size_t pos)
5671
5772inline bool array::erase (iterator iter)
5873{
59- return _array_data.erase (iter) != _array_data.end ();
74+ if (iter == _array_data.end ()) {
75+ return false ;
76+ }
77+ _array_data.erase (iter);
78+ return true ;
6079}
6180
6281template <typename ... args_t >
@@ -79,32 +98,44 @@ inline const value& array::at(size_t pos) const
7998
8099inline std::string array::to_string () const
81100{
82- std::string str { ' [' };
101+ std::string str;
102+ dump_to (str);
103+ return str;
104+ }
105+
106+ inline void array::dump_to (std::string& out) const
107+ {
108+ out.push_back (' [' );
83109 for (auto iter = _array_data.cbegin (); iter != _array_data.cend ();) {
84- str += iter->to_string ( );
110+ iter->dump_to (out );
85111 if (++iter != _array_data.cend ()) {
86- str += ' ,' ;
112+ out. push_back ( ' ,' ) ;
87113 }
88114 }
89- str += ' ]' ;
90- return str;
115+ out.push_back (' ]' );
91116}
92117
93118inline std::string array::format (size_t indent, size_t indent_times) const
94119{
95- const std::string tail_indent (indent * indent_times, ' ' );
96- const std::string body_indent (indent * (indent_times + 1 ), ' ' );
120+ std::string str;
121+ format_to (str, indent, indent_times);
122+ return str;
123+ }
97124
98- std::string str { ' [' , ' \n ' };
125+ inline void array::format_to (std::string& out, size_t indent, size_t indent_times) const
126+ {
127+ out.push_back (' [' );
128+ out.push_back (' \n ' );
99129 for (auto iter = _array_data.cbegin (); iter != _array_data.cend ();) {
100- str += body_indent + iter->format (indent, indent_times + 1 );
130+ out.append (indent * (indent_times + 1 ), ' ' );
131+ iter->format_to (out, indent, indent_times + 1 );
101132 if (++iter != _array_data.cend ()) {
102- str += ' ,' ;
133+ out. push_back ( ' ,' ) ;
103134 }
104- str += ' \n ' ;
135+ out. push_back ( ' \n ' ) ;
105136 }
106- str += tail_indent + ' ] ' ;
107- return str ;
137+ out. append (indent * indent_times, ' ' ) ;
138+ out. push_back ( ' ] ' ) ;
108139}
109140
110141inline std::string array::dumps (std::optional<size_t > indent) const
@@ -144,63 +175,36 @@ inline auto array::get(std::tuple<key_then_default_value_t...> keys_then_default
144175template <typename value_t , typename ... rest_keys_t >
145176inline auto array::get_helper (const value_t & default_value, size_t pos, rest_keys_t &&... rest) const
146177{
147- constexpr bool is_json = std::is_same_v<value, value_t > || std::is_same_v<array, value_t > || std::is_same_v<object, value_t >;
148- constexpr bool is_string = std::is_constructible_v<std::string, value_t > && !is_json;
149-
150178 if (!contains (pos)) {
151- if constexpr (is_string) {
152- return std::string (default_value);
153- }
154- else {
155- return value_t (default_value);
156- }
179+ return _utils::default_or_string (default_value);
157180 }
158181
159- return at ( pos) .get_helper (default_value, std::forward<rest_keys_t >(rest)...);
182+ return _array_data[ pos] .get_helper (default_value, std::forward<rest_keys_t >(rest)...);
160183}
161184
162185template <typename value_t >
163186inline auto array::get_helper (const value_t & default_value, size_t pos) const
164187{
165- constexpr bool is_json = std::is_same_v<value, value_t > || std::is_same_v<array, value_t > || std::is_same_v<object, value_t >;
166- constexpr bool is_string = std::is_constructible_v<std::string, value_t > && !is_json;
167-
168188 if (!contains (pos)) {
169- if constexpr (is_string) {
170- return std::string (default_value);
171- }
172- else {
173- return value_t (default_value);
174- }
189+ return _utils::default_or_string (default_value);
175190 }
176191
177- auto val = _array_data[pos];
178- if (val.template is <value_t >()) {
179- if constexpr (is_string) {
180- return val.template as <std::string>();
181- }
182- else {
183- return val.template as <value_t >();
184- }
185- }
186- else {
187- if constexpr (is_string) {
188- return std::string (default_value);
189- }
190- else {
191- return value_t (default_value);
192- }
193- }
192+ return _utils::json_value_or_default (_array_data[pos], default_value);
194193}
195194
196195template <typename value_t >
197196inline std::optional<value_t > array::find (size_t pos) const
198197{
199- if (!contains (pos)) {
198+ const auto * val = find_value (pos);
199+ if (!val) {
200200 return std::nullopt ;
201201 }
202- const auto & val = _array_data.at (pos);
203- return val.template is <value_t >() ? std::optional<value_t >(val.template as <value_t >()) : std::nullopt ;
202+ return val->template is <value_t >() ? std::optional<value_t >(val->template as <value_t >()) : std::nullopt ;
203+ }
204+
205+ inline const value* array::find_value (size_t pos) const
206+ {
207+ return contains (pos) ? &_array_data[pos] : nullptr ;
204208}
205209
206210inline typename array::iterator array::begin () noexcept
@@ -276,38 +280,38 @@ inline const value& array::operator[](size_t pos) const
276280inline array array::operator +(const array& rhs) const &
277281{
278282 array temp = *this ;
279- temp. _array_data . insert (temp._array_data . end () , rhs. begin (), rhs. end () );
283+ _array_impl_detail::append_array (temp._array_data , rhs);
280284 return temp;
281285}
282286
283287inline array array::operator +(array&& rhs) const &
284288{
285289 array temp = *this ;
286- temp. _array_data . insert (temp._array_data . end (), std::make_move_iterator ( rhs. begin ()), std::make_move_iterator (rhs. end ()) );
290+ _array_impl_detail::append_array_move (temp._array_data , rhs);
287291 return temp;
288292}
289293
290294inline array array::operator +(const array& rhs) &&
291295{
292- _array_data. insert (_array_data. end () , rhs. begin (), rhs. end () );
296+ _array_impl_detail::append_array (_array_data, rhs);
293297 return std::move (*this );
294298}
295299
296300inline array array::operator +(array&& rhs) &&
297301{
298- _array_data. insert (_array_data. end (), std::make_move_iterator (rhs. begin ()), std::make_move_iterator ( rhs. end ()) );
302+ _array_impl_detail::append_array_move (_array_data, rhs);
299303 return std::move (*this );
300304}
301305
302306inline array& array::operator +=(const array& rhs)
303307{
304- _array_data. insert (_array_data. end () , rhs. begin (), rhs. end () );
308+ _array_impl_detail::append_array (_array_data, rhs);
305309 return *this ;
306310}
307311
308312inline array& array::operator +=(array&& rhs)
309313{
310- _array_data. insert (_array_data. end (), std::make_move_iterator (rhs. begin ()), std::make_move_iterator ( rhs. end ()) );
314+ _array_impl_detail::append_array_move (_array_data, rhs);
311315 return *this ;
312316}
313317
@@ -344,6 +348,9 @@ inline T array::as() const&
344348 }
345349 else if constexpr (_utils::is_collection<T>) {
346350 T result;
351+ if constexpr (_utils::has_reserve<T>::value) {
352+ result.reserve (_array_data.size ());
353+ }
347354 for (const auto & val : _array_data) {
348355 if constexpr (_utils::has_emplace_back<T>::value) {
349356 result.emplace_back (val.as <typename T::value_type>());
@@ -387,6 +394,9 @@ inline T array::as() &&
387394 }
388395 else if constexpr (_utils::is_collection<T>) {
389396 T result;
397+ if constexpr (_utils::has_reserve<T>::value) {
398+ result.reserve (_array_data.size ());
399+ }
390400 for (auto & val : _array_data) {
391401 if constexpr (_utils::has_emplace_back<T>::value) {
392402 result.emplace_back (std::move (val).as <typename T::value_type>());
@@ -427,4 +437,4 @@ inline void array::move_as_tuple_helper(tuple_t& result, std::index_sequence<Is.
427437 using std::get;
428438 ((get<Is>(result) = std::move (_array_data[Is]).template as <std::tuple_element_t <Is, tuple_t >>()), ...);
429439}
430- } // namespace json
440+ } // namespace json
0 commit comments