Skip to content

Instantly share code, notes, and snippets.

@wheybags
Created December 23, 2020 00:12
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save wheybags/3c06795d251f004e007d47b3a5d823a7 to your computer and use it in GitHub Desktop.
Save wheybags/3c06795d251f004e007d47b3a5d823a7 to your computer and use it in GitHub Desktop.
#include <string>
#include <unistd.h>
#include <sys/fcntl.h>
#include <cassert>
template <typename CharT>
class basic_string_view_with_null
{
static constexpr bool holds_null_termination_info = sizeof(size_t) >= 4;
public:
basic_string_view_with_null(const std::basic_string<CharT>& string)
: basic_string_view_with_null(string.data(), string.length(), true)
{}
basic_string_view_with_null(const basic_string_view_with_null&) = default;
basic_string_view_with_null(const CharT* ptr, size_t len, bool is_null_terminated = false)
: m_ptr(ptr)
, m_len(len)
{
if constexpr (holds_null_termination_info)
{
size_t mask = size_t(is_null_terminated) << (sizeof(size_t) * 8 - 1);
m_len |= mask;
}
}
bool null_terminated()
{
if constexpr (holds_null_termination_info)
return (m_len & (size_t(1) << (sizeof(size_t) * 8 - 1))) != 0;
return false;
}
size_t size() const
{
size_t size = m_len;
if constexpr (holds_null_termination_info)
{
size_t mask = ~(size_t(1) << (sizeof(size_t) * 8 - 1));
size &= mask;
}
return size;
}
const char* data() const
{
return m_ptr;
}
explicit operator std::basic_string<CharT>()
{
return std::basic_string<CharT>(m_ptr, size());
}
private:
const char* m_ptr = nullptr;
size_t m_len = 0;
};
using string_view_with_null = basic_string_view_with_null<char>;
int foo(string_view_with_null path)
{
if (path.null_terminated())
return open(path.data(), O_RDONLY);
else
return open(std::string(path).c_str(), O_RDONLY);
}
int main(int argc, char** argv)
{
std::string path("/etc/passwd");
string_view_with_null path_view(path);
assert(path.size() == path_view.size());
int a = foo(path_view);
assert(a > 0);
std::string copied(path_view);
assert(copied == path);
return 0;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment