1 /* Copyright (c) 2015-2017 The Khronos Group Inc. 2 * Copyright (c) 2015-2017 Valve Corporation 3 * Copyright (c) 2015-2017 LunarG, Inc. 4 * 5 * Licensed under the Apache License, Version 2.0 (the "License"); 6 * you may not use this file except in compliance with the License. 7 * You may obtain a copy of the License at 8 * 9 * http://www.apache.org/licenses/LICENSE-2.0 10 * 11 * Unless required by applicable law or agreed to in writing, software 12 * distributed under the License is distributed on an "AS IS" BASIS, 13 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 * See the License for the specific language governing permissions and 15 * limitations under the License. 16 * 17 * Author: Mark Lobodzinski <mark@lunarg.com> 18 * Author: Courtney Goeltzenleuchter <courtney@LunarG.com> 19 * Author: Dave Houlton <daveh@lunarg.com> 20 */ 21 22 #pragma once 23 #include <stdbool.h> 24 #include <string> 25 #include <vector> 26 #include <set> 27 #include "vk_format_utils.h" 28 #include "vk_layer_logging.h" 29 30 #ifndef WIN32 31 #include <strings.h> // For ffs() 32 #else 33 #include <intrin.h> // For __lzcnt() 34 #endif 35 36 #ifdef __cplusplus 37 // Traits objects to allow string_join to operate on collections of const char * 38 template <typename String> 39 struct StringJoinSizeTrait { sizeStringJoinSizeTrait40 static size_t size(const String &str) { return str.size(); } 41 }; 42 43 template <> 44 struct StringJoinSizeTrait<const char *> { 45 static size_t size(const char *str) { 46 if (!str) return 0; 47 return strlen(str); 48 } 49 }; 50 // Similar to perl/python join 51 // * String must support size, reserve, append, and be default constructable 52 // * StringCollection must support size, const forward iteration, and store 53 // strings compatible with String::append 54 // * Accessor trait can be set if default accessors (compatible with string 55 // and const char *) don't support size(StringCollection::value_type &) 56 // 57 // Return type based on sep type 58 template <typename String = std::string, typename StringCollection = std::vector<String>, 59 typename Accessor = StringJoinSizeTrait<typename StringCollection::value_type>> 60 static inline String string_join(const String &sep, const StringCollection &strings) { 61 String joined; 62 const size_t count = strings.size(); 63 if (!count) return joined; 64 65 // Prereserved storage, s.t. we will execute in linear time (avoids reallocation copies) 66 size_t reserve = (count - 1) * sep.size(); 67 for (const auto &str : strings) { 68 reserve += Accessor::size(str); // abstracted to allow const char * type in StringCollection 69 } 70 joined.reserve(reserve + 1); 71 72 // Seps only occur *between* strings entries, so first is special 73 auto current = strings.cbegin(); 74 joined.append(*current); 75 ++current; 76 for (; current != strings.cend(); ++current) { 77 joined.append(sep); 78 joined.append(*current); 79 } 80 return joined; 81 } 82 83 // Requires StringCollection::value_type has a const char * constructor and is compatible the string_join::String above 84 template <typename StringCollection = std::vector<std::string>, typename SepString = std::string> 85 static inline SepString string_join(const char *sep, const StringCollection &strings) { 86 return string_join<SepString, StringCollection>(SepString(sep), strings); 87 } 88 89 // Perl/Python style join operation for general types using stream semantics 90 // Note: won't be as fast as string_join above, but simpler to use (and code) 91 // Note: Modifiable reference doesn't match the google style but does match std style for stream handling and algorithms 92 template <typename Stream, typename String, typename ForwardIt> 93 Stream &stream_join(Stream &stream, const String &sep, ForwardIt first, ForwardIt last) { 94 if (first != last) { 95 stream << *first; 96 ++first; 97 while (first != last) { 98 stream << sep << *first; 99 ++first; 100 } 101 } 102 return stream; 103 } 104 105 // stream_join For whole collections with forward iterators 106 template <typename Stream, typename String, typename Collection> 107 Stream &stream_join(Stream &stream, const String &sep, const Collection &values) { 108 return stream_join(stream, sep, values.cbegin(), values.cend()); 109 } 110 111 typedef void *dispatch_key; 112 static inline dispatch_key get_dispatch_key(const void *object) { return (dispatch_key) * (VkLayerDispatchTable **)object; } 113 114 VK_LAYER_EXPORT VkLayerInstanceCreateInfo *get_chain_info(const VkInstanceCreateInfo *pCreateInfo, VkLayerFunction func); 115 VK_LAYER_EXPORT VkLayerDeviceCreateInfo *get_chain_info(const VkDeviceCreateInfo *pCreateInfo, VkLayerFunction func); 116 117 static inline bool IsPowerOfTwo(unsigned x) { return x && !(x & (x - 1)); } 118 119 extern "C" { 120 #endif 121 122 #define VK_LAYER_API_VERSION VK_MAKE_VERSION(1, 0, VK_HEADER_VERSION) 123 124 typedef enum VkStringErrorFlagBits { 125 VK_STRING_ERROR_NONE = 0x00000000, 126 VK_STRING_ERROR_LENGTH = 0x00000001, 127 VK_STRING_ERROR_BAD_DATA = 0x00000002, 128 } VkStringErrorFlagBits; 129 typedef VkFlags VkStringErrorFlags; 130 131 VK_LAYER_EXPORT void layer_debug_report_actions(debug_report_data *report_data, 132 std::vector<VkDebugReportCallbackEXT> &logging_callback, 133 const VkAllocationCallbacks *pAllocator, const char *layer_identifier); 134 135 VK_LAYER_EXPORT void layer_debug_messenger_actions(debug_report_data *report_data, 136 std::vector<VkDebugUtilsMessengerEXT> &logging_messenger, 137 const VkAllocationCallbacks *pAllocator, const char *layer_identifier); 138 139 VK_LAYER_EXPORT VkStringErrorFlags vk_string_validate(const int max_length, const char *char_array); 140 VK_LAYER_EXPORT bool white_list(const char *item, const std::set<std::string> &whitelist); 141 142 static inline int u_ffs(int val) { 143 #ifdef WIN32 144 unsigned long bit_pos = 0; 145 if (_BitScanForward(&bit_pos, val) != 0) { 146 bit_pos += 1; 147 } 148 return bit_pos; 149 #else 150 return ffs(val); 151 #endif 152 } 153 154 #ifdef __cplusplus 155 } 156 #endif 157