@@ -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
296296object::
0 commit comments