summaryrefslogtreecommitdiff
path: root/src/rc_string.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/rc_string.cpp')
-rw-r--r--src/rc_string.cpp113
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());
}