@@ -70,6 +70,126 @@ find_in_object<string_view>(
70
70
object const & obj,
71
71
string_view key) noexcept ;
72
72
73
+ // returns pointer to duplicate element
74
+ template < bool SmallTable >
75
+ key_value_pair*
76
+ add_to_bucket ( object& obj, key_value_pair* kv ) noexcept
77
+ {
78
+ return find_in_object ( obj, kv->key () ).first ;
79
+ }
80
+
81
+ template <>
82
+ key_value_pair*
83
+ add_to_bucket< false >( object& obj, key_value_pair* kv )
84
+ noexcept
85
+ {
86
+ auto & head = access ::bucket ( obj, kv->key () );
87
+ auto i = head;
88
+ while ( true )
89
+ {
90
+ if (i == access ::null_index (obj) )
91
+ {
92
+ // end of bucket
93
+ access ::next (*kv) = head;
94
+ head = static_cast < access ::index_t >( kv - obj.begin () );
95
+ return nullptr ;
96
+ }
97
+
98
+ auto & v = obj.begin ()[i];
99
+ if ( v.key () != kv->key () )
100
+ {
101
+ i = access ::next (v);
102
+ continue ;
103
+ }
104
+
105
+ access ::next (*kv) = access ::next (v);
106
+ return &v;
107
+ }
108
+ }
109
+
110
+ template < bool Ignore >
111
+ std::integral_constant<bool , Ignore>
112
+ handle_duplicate ( key_value_pair& new_kv, key_value_pair& old_kv ) noexcept
113
+ {
114
+ // don't bother to check if
115
+ // storage deallocate is trivial
116
+ old_kv.~key_value_pair ();
117
+ // trivial relocate
118
+ std::memcpy ( static_cast <void *>(&old_kv), &new_kv, sizeof (old_kv) );
119
+ return {};
120
+ }
121
+
122
+ template <>
123
+ std::integral_constant<bool , false >
124
+ handle_duplicate< false >( key_value_pair&, key_value_pair& ) noexcept
125
+ {
126
+ return {};
127
+ }
128
+
129
+ template < class SmallTable , class IgnoreDuplicates >
130
+ void
131
+ unchecked_init_impl (
132
+ object& obj, unchecked_object& uo, SmallTable, IgnoreDuplicates )
133
+ {
134
+ // insert all elements, either keeping the last of any duplicate keys, or
135
+ // aborting insertion, depending on whether uo.ignore_duplicates is false.
136
+ auto dest = obj.begin ();
137
+ for ( ; uo.size (); uo.pop_front () )
138
+ {
139
+ auto src = uo.front ();
140
+ access ::construct_key_value_pair (
141
+ dest, pilfer (src[0 ]), pilfer (src[1 ]));
142
+
143
+ auto const duplicate = add_to_bucket< SmallTable::value >( obj, dest );
144
+ if ( !duplicate )
145
+ {
146
+ ++dest;
147
+ access ::grow_size (obj);
148
+ continue ;
149
+ }
150
+ if ( !handle_duplicate< IgnoreDuplicates::value >(*dest, *duplicate) )
151
+ {
152
+ dest->~key_value_pair ();
153
+ return ;
154
+ }
155
+ }
156
+ }
157
+
158
+ template < class SmallTable >
159
+ struct unchecked_init_helper2
160
+ {
161
+ object& obj;
162
+ unchecked_object& uo;
163
+
164
+ template < class IgnoreDuplicates >
165
+ void operator ()(IgnoreDuplicates) const
166
+ {
167
+ unchecked_init_impl ( obj, uo, SmallTable (), IgnoreDuplicates () );
168
+ }
169
+ };
170
+
171
+ struct unchecked_init_helper1
172
+ {
173
+ object& obj;
174
+ unchecked_object& uo;
175
+
176
+ template < class SmallTable >
177
+ void operator ()(SmallTable) const
178
+ {
179
+ mp11::mp_with_index<2 >(
180
+ uo.ignore_duplicate_keys (),
181
+ unchecked_init_helper2< SmallTable >{obj, uo} );
182
+ }
183
+ };
184
+
185
+ void
186
+ initialize_from_unchecked (object& obj, unchecked_object& uo, bool small_table)
187
+ {
188
+ mp11::mp_with_index<2 >(
189
+ small_table,
190
+ unchecked_init_helper1{obj, uo});
191
+ }
192
+
73
193
} // namespace detail
74
194
75
195
// ----------------------------------------------------------
@@ -212,85 +332,7 @@ object(detail::unchecked_object& uo)
212
332
uo.size (), 0 , sp_);
213
333
t_->size = 0 ;
214
334
215
- // insert all elements, keeping
216
- // the last of any duplicate keys, unless uo.ignore_duplicates is false.
217
- auto dest = begin ();
218
- 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
- }
335
+ detail::initialize_from_unchecked ( *this , uo, t_->is_small () );
294
336
}
295
337
296
338
object::
0 commit comments