Skip to content

Commit 8a2dd17

Browse files
committed
Define a search helper to reduce code duplication
There should be no meaningful performance degradation. If there is any impact at all, it will be positive, because calling `lower_bound` and then checking for equality gives us the search result directly, whereas calling `find` may require an comparison with the end iterator sometimes.
1 parent 1e1f689 commit 8a2dd17

2 files changed

Lines changed: 27 additions & 10 deletions

File tree

src/pysorteddict/sorted_dict_type.cc

Lines changed: 26 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -214,6 +214,24 @@ bool SortedDictType::is_nargs_good(char const* caller, Py_ssize_t nargs, int at_
214214
return true;
215215
}
216216

217+
/**
218+
* Find the lower bound of the given good key. To determine whether a good key
219+
* is present, check the second element of the result.
220+
*
221+
* @param key Good key.
222+
*
223+
* @return The lower bound and status (whether its key matches the given key).
224+
*/
225+
std::pair<FwdIterType, bool> SortedDictType::getitem_impl(PyObject* key)
226+
{
227+
// Using this method to just check whether a key is present has no
228+
// meaningful performance impact over calling the dedicated method provided
229+
// for that purpose, because it is implemented the same way (i.e.
230+
// by finding the lower bound first).
231+
auto it = this->map->lower_bound(key);
232+
return { it, it != this->map->end() && !this->map->key_comp()(key, it->first) };
233+
}
234+
217235
/**
218236
* Update the sorted dictionary with the keys and values from the given
219237
* mapping.
@@ -398,8 +416,8 @@ int SortedDictType::contains(PyObject* key, PyObject* value)
398416
{
399417
return -1;
400418
}
401-
auto it = this->map->find(key);
402-
if (it == this->map->end())
419+
auto [it, found] = this->getitem_impl(key);
420+
if (!found)
403421
{
404422
return 0;
405423
}
@@ -433,8 +451,8 @@ PyObject* SortedDictType::getitem(PyObject* key)
433451
{
434452
return nullptr;
435453
}
436-
auto it = this->map->find(key);
437-
if (it == this->map->end())
454+
auto [it, found] = this->getitem_impl(key);
455+
if (!found)
438456
{
439457
PyErr_SetObject(PyExc_KeyError, key);
440458
return nullptr;
@@ -460,8 +478,7 @@ int SortedDictType::setitem(PyObject* key, PyObject* value)
460478

461479
// Insertion will be faster if the approximate location is known. Hence,
462480
// look for the nearest match.
463-
auto it = this->map->lower_bound(key);
464-
bool found = it != this->map->end() && !this->map->key_comp()(key, it->first);
481+
auto [it, found] = this->getitem_impl(key);
465482

466483
if (value == nullptr)
467484
{
@@ -558,8 +575,8 @@ PyObject* SortedDictType::get(PyObject* const* args, Py_ssize_t nargs)
558575
{
559576
return nullptr;
560577
}
561-
auto it = this->map->find(key);
562-
if (it != this->map->end())
578+
auto [it, found] = this->getitem_impl(key);
579+
if (found)
563580
{
564581
return Py_NewRef(it->second.value); // 🆕
565582
}
@@ -588,8 +605,7 @@ PyObject* SortedDictType::setdefault(PyObject* const* args, Py_ssize_t nargs)
588605
{
589606
return nullptr;
590607
}
591-
auto it = this->map->lower_bound(key);
592-
bool found = it != this->map->end() && !this->map->key_comp()(key, it->first);
608+
auto [it, found] = this->getitem_impl(key);
593609
if (found)
594610
{
595611
return Py_NewRef(it->second.value); // 🆕

src/pysorteddict/sorted_dict_type.hh

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -63,6 +63,7 @@ private:
6363
bool is_deletion_allowed(void);
6464
static bool is_deletion_allowed(Py_ssize_t);
6565
static bool is_nargs_good(char const*, Py_ssize_t, int, int);
66+
std::pair<FwdIterType, bool> getitem_impl(PyObject*);
6667
bool update_from_mapping(PyObject*);
6768
bool update_from_sequence(PyObject*);
6869
bool update_from_object(PyObject*);

0 commit comments

Comments
 (0)