Skip to content

Commit 8715073

Browse files
committed
refactor loop
1 parent d05bc04 commit 8715073

File tree

3 files changed

+86
-78
lines changed

3 files changed

+86
-78
lines changed

include/boost/json/detail/object.hpp

+3
Original file line numberDiff line numberDiff line change
@@ -93,6 +93,9 @@ find_in_object<string_view>(
9393
object const&,
9494
string_view key) noexcept;
9595

96+
template< bool SmallTable, bool IgnoreDuplicates >
97+
void init_from_unchecked( object& obj, unchecked_object& uo );
98+
9699
} // detail
97100
BOOST_JSON_NS_END
98101

include/boost/json/impl/object.ipp

+78-78
Original file line numberDiff line numberDiff line change
@@ -70,6 +70,75 @@ find_in_object<string_view>(
7070
object const& obj,
7171
string_view key) noexcept;
7272

73+
template< bool SmallTable, bool IgnoreDuplicates >
74+
void init_from_unchecked( object& obj, unchecked_object& uo )
75+
{
76+
// insert all elements, keeping
77+
// the last of any duplicate keys, unless IgnoreDuplicates is false.
78+
auto const begin = obj.begin();
79+
auto dest = begin;
80+
for( ; uo.size(); uo.pop_front() )
81+
{
82+
auto src = uo.front();
83+
access::construct_key_value_pair(
84+
dest, pilfer(src[0]), pilfer(src[1]));
85+
86+
string_view const key = dest->key();
87+
key_value_pair* duplicate = nullptr;
88+
BOOST_IF_CONSTEXPR ( SmallTable )
89+
duplicate = find_in_object( obj, key ).first;
90+
else
91+
{
92+
auto& head = obj.t_->bucket( key );
93+
auto i = head;
94+
while( true )
95+
{
96+
if( i == object::null_index_ )
97+
{
98+
// end of bucket
99+
access::next(*dest) = head;
100+
head = static_cast<object::index_t>( dest - begin );
101+
break;
102+
}
103+
auto& v = begin[i];
104+
if( v.key() != key )
105+
{
106+
i = access::next(v);
107+
continue;
108+
}
109+
110+
// handle duplicate
111+
access::next(*dest) = access::next(v);
112+
duplicate = &v;
113+
break;
114+
}
115+
}
116+
117+
if( !duplicate )
118+
{
119+
++dest;
120+
++obj.t_->size;
121+
continue;
122+
}
123+
124+
// handle duplicate
125+
BOOST_IF_CONSTEXPR ( IgnoreDuplicates )
126+
{
127+
// don't bother to check if
128+
// storage deallocate is trivial
129+
duplicate->~key_value_pair();
130+
// trivial relocate
131+
std::memcpy(
132+
static_cast<void*>(duplicate), dest, sizeof(key_value_pair) );
133+
}
134+
else
135+
{
136+
dest->~key_value_pair();
137+
return;
138+
}
139+
}
140+
}
141+
73142
} // namespace detail
74143

75144
//----------------------------------------------------------
@@ -212,85 +281,16 @@ object(detail::unchecked_object& uo)
212281
uo.size(), 0, sp_);
213282
t_->size = 0;
214283

215-
// insert all elements, keeping
216-
// the last of any duplicate keys, unless uo.ignore_duplicates is false.
217-
auto dest = begin();
218284
if(t_->is_small())
219-
{
220-
for( ; uo.size(); uo.pop_front() )
221-
{
222-
auto src = uo.front();
223-
access::construct_key_value_pair(
224-
dest, pilfer(src[0]), pilfer(src[1]));
225-
auto result = detail::find_in_object(*this, dest->key());
226-
if(! result.first)
227-
{
228-
++dest;
229-
++t_->size;
230-
continue;
231-
}
232-
// handle duplicate
233-
if( !uo.ignore_duplicate_keys() )
234-
{
235-
dest->~key_value_pair();
236-
return;
237-
}
238-
auto& v = *result.first;
239-
// don't bother to check if
240-
// storage deallocate is trivial
241-
v.~key_value_pair();
242-
// trivial relocate
243-
std::memcpy(
244-
static_cast<void*>(&v),
245-
dest, sizeof(v));
246-
}
247-
return;
248-
}
249-
for( ; uo.size() ; uo.pop_front() )
250-
{
251-
auto src = uo.front();
252-
access::construct_key_value_pair(
253-
dest, pilfer(src[0]), pilfer(src[1]));
254-
auto& head = t_->bucket(dest->key());
255-
auto i = head;
256-
for(;;)
257-
{
258-
if(i == null_index_)
259-
{
260-
// end of bucket
261-
access::next(
262-
*dest) = head;
263-
head = static_cast<index_t>(
264-
dest - begin());
265-
++dest;
266-
++t_->size;
267-
break;
268-
}
269-
auto& v = (*t_)[i];
270-
if(v.key() != dest->key())
271-
{
272-
i = access::next(v);
273-
continue;
274-
}
275-
276-
// handle duplicate
277-
if( !uo.ignore_duplicate_keys() )
278-
{
279-
dest->~key_value_pair();
280-
return;
281-
}
282-
access::next(*dest) =
283-
access::next(v);
284-
// don't bother to check if
285-
// storage deallocate is trivial
286-
v.~key_value_pair();
287-
// trivial relocate
288-
std::memcpy(
289-
static_cast<void*>(&v),
290-
dest, sizeof(v));
291-
break;
292-
}
293-
}
285+
if( uo.ignore_duplicate_keys() )
286+
detail::init_from_unchecked< true, true >( *this, uo );
287+
else
288+
detail::init_from_unchecked< true, false >( *this, uo );
289+
else
290+
if( uo.ignore_duplicate_keys() )
291+
detail::init_from_unchecked< false, true >( *this, uo );
292+
else
293+
detail::init_from_unchecked< false, false >( *this, uo );
294294
}
295295

296296
object::

include/boost/json/object.hpp

+5
Original file line numberDiff line numberDiff line change
@@ -1646,6 +1646,11 @@ class object
16461646
reindex_relocate(
16471647
key_value_pair* src,
16481648
key_value_pair* dst) noexcept;
1649+
1650+
template< bool SmallTable, bool IgnoreDuplicates >
1651+
friend
1652+
void
1653+
detail::init_from_unchecked( object& obj, detail::unchecked_object& uo );
16491654
};
16501655

16511656
BOOST_JSON_NS_END

0 commit comments

Comments
 (0)