diff options
Diffstat (limited to 'src/libutil/types.hh')
-rw-r--r-- | src/libutil/types.hh | 82 |
1 files changed, 69 insertions, 13 deletions
diff --git a/src/libutil/types.hh b/src/libutil/types.hh index 9c85fef62..00ba567c6 100644 --- a/src/libutil/types.hh +++ b/src/libutil/types.hh @@ -6,26 +6,23 @@ #include <set> #include <string> #include <map> +#include <variant> #include <vector> namespace nix { -using std::list; -using std::set; -using std::vector; -using std::string; - -typedef list<string> Strings; -typedef set<string> StringSet; -typedef std::map<string, string> StringMap; +typedef std::list<std::string> Strings; +typedef std::set<std::string> StringSet; +typedef std::map<std::string, std::string> StringMap; +typedef std::map<std::string, std::string> StringPairs; /* Paths are just strings. */ +typedef std::string Path; +typedef std::string_view PathView; +typedef std::list<Path> Paths; +typedef std::set<Path> PathSet; -typedef string Path; -typedef list<Path> Paths; -typedef set<Path> PathSet; - -typedef vector<std::pair<string, string>> Headers; +typedef std::vector<std::pair<std::string, std::string>> Headers; /* Helper class to run code at startup. */ template<typename T> @@ -46,4 +43,63 @@ struct Explicit { } }; + +/* This wants to be a little bit like rust's Cow type. + Some parts of the evaluator benefit greatly from being able to reuse + existing allocations for strings, but have to be able to also use + newly allocated storage for values. + + We do not define implicit conversions, even with ref qualifiers, + since those can easily become ambiguous to the reader and can degrade + into copying behaviour we want to avoid. */ +class BackedStringView { +private: + std::variant<std::string, std::string_view> data; + + /* Needed to introduce a temporary since operator-> must return + a pointer. Without this we'd need to store the view object + even when we already own a string. */ + class Ptr { + private: + std::string_view view; + public: + Ptr(std::string_view view): view(view) {} + const std::string_view * operator->() const { return &view; } + }; + +public: + BackedStringView(std::string && s): data(std::move(s)) {} + BackedStringView(std::string_view sv): data(sv) {} + template<size_t N> + BackedStringView(const char (& lit)[N]): data(std::string_view(lit)) {} + + BackedStringView(const BackedStringView &) = delete; + BackedStringView & operator=(const BackedStringView &) = delete; + + /* We only want move operations defined since the sole purpose of + this type is to avoid copies. */ + BackedStringView(BackedStringView && other) = default; + BackedStringView & operator=(BackedStringView && other) = default; + + bool isOwned() const + { + return std::holds_alternative<std::string>(data); + } + + std::string toOwned() && + { + return isOwned() + ? std::move(std::get<std::string>(data)) + : std::string(std::get<std::string_view>(data)); + } + + std::string_view operator*() const + { + return isOwned() + ? std::get<std::string>(data) + : std::get<std::string_view>(data); + } + Ptr operator->() const { return Ptr(**this); } +}; + } |