Make String able to reference external data without copying

Sometimes we really need to have a String instead of a StringView,
but some of those strings might not need to own their data. Make
it possible to explicitely construct a String that does not own
the underlying buffer.

Use it when parsing balanced strings.
This commit is contained in:
Maxime Coste 2019-03-19 22:00:57 +11:00
parent c2be661785
commit 56611604b2
3 changed files with 16 additions and 4 deletions

View File

@ -121,11 +121,11 @@ QuotedResult parse_quoted_balanced(Reader& reader, char opening_delimiter,
{
auto content = reader.substr_from(start);
++reader.pos;
return {content.str(), true};
return {String{String::NoCopy{}, content}, true};
}
++reader.pos;
}
return {reader.substr_from(start).str(), false};
return {String{String::NoCopy{}, reader.substr_from(start)}, false};
}
String parse_unquoted(Reader& reader)

View File

@ -6,6 +6,13 @@
namespace Kakoune
{
String::Data::Data(String::NoCopy, const char* data, size_t size)
{
l.ptr = const_cast<char*>(data);
l.size = size;
l.capacity = 0;
}
String::Data::Data(const char* data, size_t size, size_t capacity)
{
if (capacity > Short::capacity)
@ -71,7 +78,7 @@ String::Data& String::Data::operator=(Data&& other) noexcept
template<bool copy>
void String::Data::reserve(size_t new_capacity)
{
if (new_capacity <= capacity())
if (capacity() != 0 and new_capacity <= capacity())
return;
if (is_long())
@ -123,7 +130,7 @@ void String::Data::clear()
void String::Data::release()
{
if (is_long())
if (is_long() and l.capacity != 0)
Alloc{}.deallocate(l.ptr, l.capacity+1);
}

View File

@ -121,6 +121,9 @@ public:
explicit String(StringView str);
struct NoCopy{};
String(NoCopy, StringView str);
[[gnu::always_inline]]
char* data() { return m_data.data(); }
@ -175,6 +178,7 @@ public:
} s;
Data() { set_empty(); }
Data(NoCopy, const char* data, size_t size);
Data(const char* data, size_t size, size_t capacity);
Data(const char* data, size_t size) : Data(data, size, size) {}
Data(const Data& other) : Data{other.data(), other.size()} {}
@ -257,6 +261,7 @@ template<> struct HashCompatible<String, StringView> : std::true_type {};
template<> struct HashCompatible<StringView, String> : std::true_type {};
inline String::String(StringView str) : String{str.begin(), str.length()} {}
inline String::String(NoCopy, StringView str) : m_data{NoCopy{}, str.begin(), (size_t)str.length()} {}
template<typename Type, typename CharType>
inline StringView StringOps<Type, CharType>::substr(ByteCount from, ByteCount length) const