aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--layers/vk_layer_utils.h53
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