@@ -199,30 +199,29 @@ bool CLASS::get(const Link& link, Element& element) const NOEXCEPT
199199// static
200200TEMPLATE
201201template <typename Element, if_equal<Element::size, Size>>
202- bool CLASS::get (const iterator& it, Element& element) NOEXCEPT
202+ bool CLASS::get (const memory_ptr& ptr, const Link& link,
203+ Element& element) NOEXCEPT
203204{
204- // This override avoids deadlock when holding iterator to the same table.
205- return read (it.get (), it.self (), element);
205+ return read (ptr, link, element);
206206}
207207
208208// static
209209TEMPLATE
210210template <typename Element, if_equal<Element::size, Size>>
211- bool CLASS::get (const iterator& it, const Link& link,
212- Element& element) NOEXCEPT
211+ bool CLASS::get (const iterator& it, Element& element) NOEXCEPT
213212{
214213 // This override avoids deadlock when holding iterator to the same table.
215- return read (it.get (), link , element);
214+ return read (it.get (), it. self () , element);
216215}
217216
218217// static
219218TEMPLATE
220219template <typename Element, if_equal<Element::size, Size>>
221- bool CLASS::get (const memory_ptr& ptr , const Link& link,
220+ bool CLASS::get (const iterator& it , const Link& link,
222221 Element& element) NOEXCEPT
223222{
224223 // This override avoids deadlock when holding iterator to the same table.
225- return read (ptr , link, element);
224+ return read (it. get () , link, element);
226225}
227226
228227TEMPLATE
@@ -307,24 +306,16 @@ template <typename Element, if_equal<Element::size, Size>>
307306bool CLASS::put (const Link& link, const Key& key,
308307 const Element& element) NOEXCEPT
309308{
310- using namespace system ;
311- const auto ptr = body_.get (link);
312- if (!ptr)
313- return false ;
314-
315- // iostream.flush is a nop (direct copy).
316- iostream stream{ *ptr };
317- finalizer sink{ stream };
318- sink.skip_bytes (Link::size);
319- sink.write_bytes (key);
320-
321- if constexpr (!is_slab)
322- {
323- BC_DEBUG_ONLY (sink.set_limit (Size * element.count ());)
324- }
309+ // This override is the normal form.
310+ return write (get_memory (), link, key, element);
311+ }
325312
326- auto & next = unsafe_array_cast<uint8_t , Link::size>(ptr->begin ());
327- return element.to_data (sink) && head_.push (link, next, head_.index (key));
313+ TEMPLATE
314+ template <typename Element, if_equal<Element::size, Size>>
315+ bool CLASS::put (const memory_ptr& ptr, const Link& link, const Key& key,
316+ const Element& element) NOEXCEPT
317+ {
318+ return write (ptr, link, key, element);
328319}
329320
330321TEMPLATE
@@ -355,6 +346,31 @@ Link CLASS::commit_link(const Link& link, const Key& key) NOEXCEPT
355346// protected/static
356347// ----------------------------------------------------------------------------
357348
349+ TEMPLATE
350+ Link CLASS::first (const memory_ptr& ptr, Link link, const Key& key) NOEXCEPT
351+ {
352+ if (!ptr)
353+ return {};
354+
355+ while (!link.is_terminal ())
356+ {
357+ // get element offset (fault)
358+ const auto offset = ptr->offset (body::link_to_position (link));
359+ if (is_null (offset))
360+ return {};
361+
362+ // element key matches (found)
363+ if (is_zero (std::memcmp (key.data (), std::next (offset, Link::size),
364+ array_count<Key>)))
365+ return link;
366+
367+ // set next element link (loop)
368+ link = system::unsafe_array_cast<uint8_t , Link::size>(offset);
369+ }
370+
371+ return link;
372+ }
373+
358374TEMPLATE
359375template <typename Element, if_equal<Element::size, Size>>
360376bool CLASS::read (const memory_ptr& ptr, const Link& link,
@@ -387,28 +403,40 @@ bool CLASS::read(const memory_ptr& ptr, const Link& link,
387403}
388404
389405TEMPLATE
390- Link CLASS::first (const memory_ptr& ptr, Link link, const Key& key) NOEXCEPT
406+ template <typename Element, if_equal<Element::size, Size>>
407+ bool CLASS::write (const memory_ptr& ptr, const Link& link, const Key& key,
408+ const Element& element) NOEXCEPT
391409{
392- if (!ptr)
393- return {} ;
410+ if (!ptr || link. is_terminal () )
411+ return false ;
394412
395- while (!link.is_terminal ())
396- {
397- // get element offset (fault)
398- const auto offset = ptr->offset (body::link_to_position (link));
399- if (is_null (offset))
400- return {};
413+ using namespace system ;
414+ const auto start = body::link_to_position (link);
415+ if (is_limited<ptrdiff_t >(start))
416+ return false ;
401417
402- // element key matches (found)
403- if ( is_zero ( std::memcmp (key. data (), std::next (offset, Link::size),
404- array_count<Key>)) )
405- return link ;
418+ const auto size = ptr-> size ();
419+ const auto position = possible_narrow_and_sign_cast< ptrdiff_t >(start);
420+ if (position > size )
421+ return false ;
406422
407- // set next element link (loop)
408- link = system::unsafe_array_cast<uint8_t , Link::size>(offset);
423+ const auto offset = ptr->offset (position);
424+ if (is_null (offset))
425+ return false ;
426+
427+ // iostream.flush is a nop (direct copy).
428+ iostream stream{ offset, size - position };
429+ finalizer sink{ stream };
430+ sink.skip_bytes (Link::size);
431+ sink.write_bytes (key);
432+
433+ if constexpr (!is_slab)
434+ {
435+ BC_DEBUG_ONLY (sink.set_limit (Size * element.count ());)
409436 }
410437
411- return link;
438+ auto & next = unsafe_array_cast<uint8_t , Link::size>(ptr->begin ());
439+ return element.to_data (sink) && head_.push (link, next, head_.index (key));
412440}
413441
414442} // namespace database
0 commit comments