From 5868db1d531080258b92e5cf846f5c3872b68fc6 Mon Sep 17 00:00:00 2001 From: blueloveTH Date: Thu, 28 Aug 2025 19:03:46 +0800 Subject: [PATCH] make `dict` with string keys noexcept --- include/pocketpy/common/smallmap.h | 5 ++--- src/public/py_dict.c | 29 ++++++++++++++++++++--------- 2 files changed, 22 insertions(+), 12 deletions(-) diff --git a/include/pocketpy/common/smallmap.h b/include/pocketpy/common/smallmap.h index 74556202..3a007268 100644 --- a/include/pocketpy/common/smallmap.h +++ b/include/pocketpy/common/smallmap.h @@ -22,12 +22,11 @@ #define K c11_sv #define V int #define NAME c11_smallmap_v2d -#define less(a, b) (c11_sv__cmp((a), (b)) < 0) -#define equal(a, b) (c11_sv__cmp((a), (b)) == 0) +#define less(a, b) (c11_sv__cmp((a), (b)) < 0) +#define equal(a, b) c11__sveq((a), (b)) #include "pocketpy/xmacros/smallmap.h" #undef SMALLMAP_T__HEADER - #define SMALLMAP_T__HEADER #define K void* #define V py_i64 diff --git a/src/public/py_dict.c b/src/public/py_dict.c index a3870cca..fee464db 100644 --- a/src/public/py_dict.c +++ b/src/public/py_dict.c @@ -136,16 +136,17 @@ static void Dict__set_index(Dict* self, uint32_t index, uint32_t value) { } } +// Dict__probe won't raise exception for string keys static bool Dict__probe(Dict* self, py_TValue* key, uint64_t* p_hash, uint32_t* p_idx, DictEntry** p_entry) { - py_i64 h_user; - if(!py_hash(key, &h_user)) return false; if(py_isstr(key)) { - *p_hash = (uint64_t)h_user; + *p_hash = c11_sv__hash(py_tosv(key)); } else { + py_i64 h_user; + if(!py_hash(key, &h_user)) return false; *p_hash = Dict__hash_2nd((uint64_t)h_user); } uint32_t mask = self->capacity - 1; @@ -155,13 +156,23 @@ static bool Dict__probe(Dict* self, if(idx2 == self->null_index_value) break; DictEntry* entry = c11__at(DictEntry, &self->entries, idx2); if(entry->hash == (*p_hash)) { - int res = py_equal(&entry->key, key); - if(res == 1) { - *p_idx = idx; - *p_entry = entry; - return true; + if(py_isstr(&entry->key) && py_isstr(key)) { + c11_sv lhs = py_tosv(&entry->key); + c11_sv rhs = py_tosv(key); + if(c11__sveq(lhs, rhs)) { + *p_idx = idx; + *p_entry = entry; + return true; + } + } else { + int res = py_equal(&entry->key, key); + if(res == 1) { + *p_idx = idx; + *p_entry = entry; + return true; + } + if(res == -1) return false; // error } - if(res == -1) return false; // error } // try next index idx = Dict__step(idx);