diff options
| -rw-r--r-- | layers/vk_layer_utils.h | 53 |
1 files changed, 53 insertions, 0 deletions
diff --git a/layers/vk_layer_utils.h b/layers/vk_layer_utils.h index 08574a5e..cfad81ce 100644 --- a/layers/vk_layer_utils.h +++ b/layers/vk_layer_utils.h @@ -21,6 +21,7 @@ #pragma once #include <stdbool.h> +#include <string> #include <vector> #include "vk_format_utils.h" #include "vk_layer_logging.h" @@ -32,6 +33,58 @@ #endif #ifdef __cplusplus +// Traits objects to allow string_join to operate on collections of const char * +template <typename String> +struct StringJoinSizeTrait { + static size_t size(const String &str) { return str.size(); } +}; + +template <> +struct StringJoinSizeTrait<const char *> { + static size_t size(const char *str) { + if (!str) return 0; + return strlen(str); + } +}; +// Similar to perl/python join +// * String must support size, reserve, append, and be default constructable +// * StringCollection must support size, const forward iteration, and store +// strings compatible with String::append +// * Accessor trait can be set if default accessors (compatible with string +// and const char *) don't support size(StringCollection::value_type &) +// +// Return type based on sep type +template <typename String = std::string, typename StringCollection = std::vector<String>, + typename Accessor = StringJoinSizeTrait<typename StringCollection::value_type>> +static inline String string_join(const String &sep, const StringCollection &strings) { + String joined; + const size_t count = strings.size(); + if (!count) return joined; + + // Prereserved storage, s.t. we will execute in linear time (avoids reallocation copies) + size_t reserve = (count - 1) * sep.size(); + for (const auto &str : strings) { + reserve += Accessor::size(str); // abstracted to allow const char * type in StringCollection + } + joined.reserve(reserve + 1); + + // Seps only occur *between* strings entries, so first is special + auto current = strings.cbegin(); + joined.append(*current); + ++current; + for (; current != strings.cend(); ++current) { + joined.append(sep); + joined.append(*current); + } + return joined; +} + +// Requires StringCollection::value_type has a const char * constructor and is compatible the string_join::String above +template <typename StringCollection = std::vector<std::string>, typename SepString = std::string> +static inline SepString string_join(const char *sep, const StringCollection &strings) { + return string_join<SepString, StringCollection>(SepString(sep), strings); +} + extern "C" { #endif |
