Skip to content

Instantly share code, notes, and snippets.

@facontidavide
Last active November 18, 2021 03:33
Show Gist options
  • Save facontidavide/185ad92d1bd96f5a5a7dba293627b047 to your computer and use it in GitHub Desktop.
Save facontidavide/185ad92d1bd96f5a5a7dba293627b047 to your computer and use it in GitHub Desktop.
Unmutable, string reference with "small object optimization".
/**
* @brief Super simple, unmutable, string_view with
* small string optimization.
* If the string is 15 bytes or less, it is copied, otherwise,
* StringRef stores a not-owning reference.
*/
class StringRef
{
private:
static const uint64_t TYPE_BIT = uint64_t(1) << (sizeof(size_t)*8 -1 );
struct noSSO
{
const char* data;
size_t size;
};
static const uint8_t SSO_SIZE = sizeof(noSSO) - 1;
struct SSO
{
char data[sizeof(noSSO)];
};
union {
noSSO no_sso;
SSO sso;
} _storage;
public:
bool isSSO() const
{
return !(_storage.no_sso.size & TYPE_BIT);
}
StringRef()
: StringRef( nullptr, 0 )
{}
StringRef(const std::string& str)
: StringRef( str.data(), str.size() )
{}
StringRef(const char* str)
: StringRef( str, strlen(str) )
{}
explicit StringRef(const char* data_ptr, size_t length)
{
_storage.no_sso.data = nullptr;
_storage.no_sso.size = 0;
if( length <= SSO_SIZE )
{
memcpy( _storage.sso.data, data_ptr, length );
_storage.sso.data[SSO_SIZE] = SSO_SIZE - length;
}
else{
_storage.no_sso.data = data_ptr;
_storage.no_sso.size = length;
_storage.no_sso.size |= TYPE_BIT;
}
}
const char* data() const
{
return isSSO() ? _storage.sso.data :
_storage.no_sso.data;
}
size_t size() const
{
return isSSO() ? (SSO_SIZE - _storage.sso.data[SSO_SIZE]) :
_storage.no_sso.size & ~TYPE_BIT;
}
};
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment