summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMaxime Coste <mawww@kakoune.org>2019-03-19 22:00:57 +1100
committerMaxime Coste <mawww@kakoune.org>2019-03-19 22:00:57 +1100
commit56611604b28b6c293b13e3637fbae65e6bea064c (patch)
tree710d7c264d81ac352292cba196b231aca832afda
parentc2be661785418be87e06d366979bdcd8ff3cf0b2 (diff)
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.
-rw-r--r--src/command_manager.cc4
-rw-r--r--src/string.cc11
-rw-r--r--src/string.hh5
3 files changed, 16 insertions, 4 deletions
diff --git a/src/command_manager.cc b/src/command_manager.cc
index 42e7f802..f777eeda 100644
--- a/src/command_manager.cc
+++ b/src/command_manager.cc
@@ -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)
diff --git a/src/string.cc b/src/string.cc
index 6ff89450..d44963ba 100644
--- a/src/string.cc
+++ b/src/string.cc
@@ -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);
}
diff --git a/src/string.hh b/src/string.hh
index ae41642c..e69be344 100644
--- a/src/string.hh
+++ b/src/string.hh
@@ -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