diff options
author | John Hodge <tpg@ucc.asn.au> | 2019-05-21 18:58:23 +0800 |
---|---|---|
committer | John Hodge <tpg@ucc.asn.au> | 2019-05-21 18:58:23 +0800 |
commit | 84a9e0b722ac2b56a958720330592bc9e5ed7633 (patch) | |
tree | d5ff8de91483237813490bd101983df6566b65ce | |
parent | b48167dec0c1c05b463991a8db5a8db70a5ae604 (diff) | |
download | mrust-84a9e0b722ac2b56a958720330592bc9e5ed7633.tar.gz |
rc_string - Use memcmp/strcmp (faster)
-rw-r--r-- | src/include/rc_string.hpp | 16 | ||||
-rw-r--r-- | src/rc_string.cpp | 71 |
2 files changed, 31 insertions, 56 deletions
diff --git a/src/include/rc_string.hpp b/src/include/rc_string.hpp index 94b6d9e7..2177e614 100644 --- a/src/include/rc_string.hpp +++ b/src/include/rc_string.hpp @@ -85,7 +85,12 @@ public: return *(c_str() + size() - 1); } - Ordering ord(const RcString& s) const; + Ordering ord(const char* s, size_t l) const; + Ordering ord(const RcString& s) const { + if( m_ptr == s.m_ptr ) + return OrdEqual; + return ord(s.c_str(), s.size()); + } bool operator==(const RcString& s) const { if(s.size() != this->size()) return false; @@ -99,13 +104,16 @@ public: bool operator<(const RcString& s) const { return this->ord(s) == OrdLess; } bool operator>(const RcString& s) const { return this->ord(s) == OrdGreater; } - Ordering ord(const std::string& s) const; + Ordering ord(const std::string& s) const { return ord(s.data(), s.size()); } bool operator==(const std::string& s) const { return this->ord(s) == OrdEqual; } bool operator!=(const std::string& s) const { return this->ord(s) != OrdEqual; } bool operator<(const std::string& s) const { return this->ord(s) == OrdLess; } bool operator>(const std::string& s) const { return this->ord(s) == OrdGreater; } - bool operator==(const char* s) const; - bool operator!=(const char* s) const { return !(*this == s); } + + Ordering ord(const char* s) const; + bool operator==(const char* s) const { return this->ord(s) == OrdEqual; } + bool operator!=(const char* s) const { return this->ord(s) != OrdEqual; } + friend ::std::ostream& operator<<(::std::ostream& os, const RcString& x); friend bool operator==(const char* a, const RcString& b) { diff --git a/src/rc_string.cpp b/src/rc_string.cpp index 0d7e253a..123b4254 100644 --- a/src/rc_string.cpp +++ b/src/rc_string.cpp @@ -37,70 +37,35 @@ RcString::~RcString() } } } -Ordering RcString::ord(const RcString& x) const +Ordering RcString::ord(const char* s, size_t len) const { - if( m_ptr == x.m_ptr ) - return OrdEqual; - // Both can't be empty/null if( m_ptr == nullptr ) - return OrdLess; - if( x.m_ptr == nullptr ) + return (len == 0 ? OrdEqual : OrdLess); + if( len == 0 ) return OrdGreater; - assert(x.size() > 0); assert(this->size() > 0); + assert(len > 0); - auto xp = x.c_str(); - auto tp = this->c_str(); - for(size_t i = 0; i < ::std::min(this->size(), x.size()); i ++) - { - if( *xp != *tp ) - return ::ord((unsigned)*xp, (unsigned)*tp); - xp ++; - tp ++; - } - return ::ord((unsigned)this->size(), (unsigned)x.size()); + int cmp = memcmp(this->c_str(), s, ::std::min(len, this->size())); + if(cmp == 0) + return ::ord(this->size(), len); + return ::ord(cmp, 0); } -Ordering RcString::ord(const std::string& x) const +Ordering RcString::ord(const char* s) const { - if( m_ptr == nullptr && x.size() == 0 ) - return OrdEqual; - // Both can't be empty/null if( m_ptr == nullptr ) - return OrdLess; - if( x.empty() ) - return OrdGreater; - - assert(x.size() > 0); - assert(this->size() > 0); + return (*s == '\0' ? OrdEqual : OrdLess); - auto xp = x.c_str(); - auto tp = this->c_str(); - for(size_t i = 0; i < ::std::min(this->size(), x.size()); i ++) - { - if( *xp != *tp ) - return ::ord((unsigned)*xp, (unsigned)*tp); - xp ++; - tp ++; - } - return ::ord((unsigned)this->size(), (unsigned)x.size()); -} -bool RcString::operator==(const char* s) const -{ - if( m_ptr == nullptr ) - return *s == '\0'; - const char* ts = this->c_str(); - const char* end = ts + this->size(); - // Loop while not at the end of either - while(s && ts != end) + int cmp = strncmp(this->c_str(), s, this->size()); + if( cmp == 0 ) { - if( *s != *ts ) - return false; - s ++; - ts ++; + if( s[this->size()] == '\0' ) + return OrdEqual; + else + return OrdLess; } - // Only equal if we're at the end of both strings - return *s == '\0' && ts == end; + return ::ord(cmp, 0); } ::std::ostream& operator<<(::std::ostream& os, const RcString& x) @@ -125,12 +90,14 @@ RcString RcString::new_interned(const ::std::string& s) } return *it; #else + // TODO: interning flag, so comparisons can just be a pointer comparison return *RcString_interned_strings.insert(RcString(s)).first; #endif } size_t std::hash<RcString>::operator()(const RcString& s) const noexcept { + // http://www.cse.yorku.ca/~oz/hash.html "djb2" size_t h = 5381; for(auto c : s) { h = h * 33 + (unsigned)c; |