diff options
Diffstat (limited to 'src/rc_string.cpp')
-rw-r--r-- | src/rc_string.cpp | 113 |
1 files changed, 89 insertions, 24 deletions
diff --git a/src/rc_string.cpp b/src/rc_string.cpp index 4025d8c8..b56f2e62 100644 --- a/src/rc_string.cpp +++ b/src/rc_string.cpp @@ -7,17 +7,19 @@ */ #include <rc_string.hpp> #include <cstring> +#include <string> #include <iostream> +#include <algorithm> // std::max RcString::RcString(const char* s, unsigned int len): - m_ptr(nullptr), - m_len(len) + m_ptr(nullptr) { if( len > 0 ) { - m_ptr = new unsigned int[1 + (len+1 + sizeof(unsigned int)-1) / sizeof(unsigned int)]; - *m_ptr = 1; - char* data_mut = reinterpret_cast<char*>(m_ptr + 1); + m_ptr = new unsigned int[2 + (len+1 + sizeof(unsigned int)-1) / sizeof(unsigned int)]; + m_ptr[0] = 1; + m_ptr[1] = len; + char* data_mut = reinterpret_cast<char*>(m_ptr + 2); for(unsigned int j = 0; j < len; j ++ ) data_mut[j] = s[j]; data_mut[len] = '\0'; @@ -25,16 +27,6 @@ RcString::RcString(const char* s, unsigned int len): //::std::cout << "RcString(" << m_ptr << " \"" << *this << "\") - " << *m_ptr << " (creation)" << ::std::endl; } } -RcString::RcString(const RcString& x): - m_ptr(x.m_ptr), - m_len(x.m_len) -{ - if( m_ptr ) - { - *m_ptr += 1; - //::std::cout << "RcString(" << m_ptr << " \"" << *this << "\") - " << *m_ptr << " refs present (copy)" << ::std::endl; - } -} RcString::~RcString() { if(m_ptr) @@ -48,14 +40,87 @@ RcString::~RcString() } } } -bool RcString::operator==(const char* s) const +Ordering RcString::ord(const char* s, size_t len) const +{ + if( m_ptr == nullptr ) + return (len == 0 ? OrdEqual : OrdLess); + if( len == 0 ) + return OrdGreater; + + assert(this->size() > 0); + assert(len > 0); + + 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 char* s) const +{ + if( m_ptr == nullptr ) + return (*s == '\0' ? OrdEqual : OrdLess); + + int cmp = strncmp(this->c_str(), s, this->size()); + if( cmp == 0 ) + { + if( s[this->size()] == '\0' ) + return OrdEqual; + else + return OrdLess; + } + return ::ord(cmp, 0); +} + +::std::ostream& operator<<(::std::ostream& os, const RcString& x) { - if( m_len == 0 ) - return *s == '\0'; - auto m = this->c_str(); - do { - if( *m != *s ) - return false; - } while( *m++ != '\0' && *s++ != '\0' ); - return true; + for(size_t i = 0; i < x.size(); i ++) + { + os << x.c_str()[i]; + } + return os; +} + + +::std::set<RcString> RcString_interned_strings; + +RcString RcString::new_interned(const ::std::string& s) +{ +#if 0 + auto it = RcString_interned_strings.find(s); + if( it == RcString_interned_strings.end() ) + { + it = RcString_interned_strings.insert(RcString(s)).first; + } + return *it; +#else + // TODO: interning flag, so comparisons can just be a pointer comparison + // - Only want to set this flag on the cached instance + return *RcString_interned_strings.insert(RcString(s)).first; +#endif +} +RcString RcString::new_interned(const char* s) +{ +#if 0 + auto it = RcString_interned_strings.find(s); + if( it == RcString_interned_strings.end() ) + { + it = RcString_interned_strings.insert(RcString(s)).first; + } + return *it; +#else + // TODO: interning flag, so comparisons can just be a pointer comparison + // - Only want to set this flag on the cached instance + 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; + } + return h; + //return hash<std::string_view>(s.c_str(), s.size()); } |