-
-
Save wheybags/3c06795d251f004e007d47b3a5d823a7 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#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