From: Remi Gacogne Date: Thu, 12 May 2022 09:37:20 +0000 (+0200) Subject: SuffixMatchTree: Avoid cloning labels during lookups X-Git-Tag: auth-4.8.0-alpha0~71^2~2 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=43075548735773013666b83dc29c8fb6d3c9159c;p=thirdparty%2Fpdns.git SuffixMatchTree: Avoid cloning labels during lookups --- diff --git a/pdns/dnsname.hh b/pdns/dnsname.hh index 3c3ed3330a..d0bc010d2e 100644 --- a/pdns/dnsname.hh +++ b/pdns/dnsname.hh @@ -318,14 +318,46 @@ struct SuffixMatchTree } std::string d_name; - mutable std::set children; + mutable std::set> children; mutable bool endNode; mutable T d_value; bool operator<(const SuffixMatchTree& rhs) const { return strcasecmp(d_name.c_str(), rhs.d_name.c_str()) < 0; } - typedef SuffixMatchTree value_type; + + /* this structure is used to do a lookup without allocating and + copying a string, using C++14's heterogeneous lookups in ordered + containers */ + struct LightKey + { + std::string_view d_name; + bool operator<(const SuffixMatchTree& smt) const + { + auto compareUpTo = std::min(this->d_name.size(), smt.d_name.size()); + auto ret = strncasecmp(this->d_name.data(), smt.d_name.data(), compareUpTo); + if (ret != 0) { + return ret < 0; + } + if (this->d_name.size() == smt.d_name.size()) { + return ret < 0; + } + return this->d_name.size() < smt.d_name.size(); + } + }; + + bool operator<(const LightKey& lk) const + { + auto compareUpTo = std::min(this->d_name.size(), lk.d_name.size()); + auto ret = strncasecmp(this->d_name.data(), lk.d_name.data(), compareUpTo); + if (ret != 0) { + return ret < 0; + } + if (this->d_name.size() == lk.d_name.size()) { + return ret < 0; + } + return this->d_name.size() < lk.d_name.size(); + } template void visit(const V& v) const { @@ -437,8 +469,8 @@ struct SuffixMatchTree return nullptr; } - SuffixMatchTree smn(std::string(visitor.back())); - auto child = children.find(smn); + const LightKey lk{visitor.back()}; + auto child = children.find(lk); if (child == children.end()) { if(endNode) { return &d_value;