// Copyright 2023 The Khronos Group Inc. // Copyright 2023 Valve Corporation // Copyright 2023 LunarG, Inc. // // SPDX-License-Identifier: Apache-2.0 // // Author(s): // - Christophe Riccio #include "layer_settings_util.hpp" #include #include #include #include #include namespace vl { std::vector Split(const std::string &pValues, char delimiter) { std::vector result; std::string parse = pValues; std::size_t start = 0; std::size_t end = parse.find(delimiter); while (end != std::string::npos) { result.push_back(parse.substr(start, end - start)); start = end + 1; end = parse.find(delimiter, start); } const std::string last = parse.substr(start, end); if (!last.empty()) { result.push_back(last); } return result; } std::string GetFileSettingName(const char *pLayerName, const char *pSettingName) { assert(pLayerName != nullptr); assert(pSettingName != nullptr); std::stringstream settingName; settingName << vl::ToLower(TrimPrefix(pLayerName)) << "." << pSettingName; return settingName.str(); } std::string GetEnvSettingName(const char *layer_key, const char *setting_key, TrimMode trim_mode) { std::stringstream result; #if defined(__ANDROID__) switch (trim_mode) { default: case TRIM_NONE: { result << "debug.vulkan." << GetFileSettingName(layer_key, setting_key); break; } case TRIM_VENDOR: { result << "debug.vulkan." << GetFileSettingName(TrimVendor(layer_key).c_str(), setting_key); break; } case TRIM_NAMESPACE: { result << "debug.vulkan." << setting_key; break; } } #else switch (trim_mode) { default: case TRIM_NONE: { result << "VK_" << vl::ToUpper(TrimPrefix(layer_key)) << "_" << vl::ToUpper(setting_key); break; } case TRIM_VENDOR: { result << "VK_" << vl::ToUpper(TrimVendor(layer_key)) << "_" << vl::ToUpper(setting_key); break; } case TRIM_NAMESPACE: { result << "VK_" << vl::ToUpper(setting_key); break; } } #endif return result.str(); } char GetEnvDelimiter() { #ifdef WIN32 // a define is necessary because ':' is used for disk drives on Windows path return ';'; #else return ':'; #endif } char FindDelimiter(const std::string& s) { if (s.find(',') != std::string::npos) { return ','; } else if (s.find(GetEnvDelimiter()) != std::string::npos) { return GetEnvDelimiter(); } else { return ','; } } std::string TrimWhitespace(const std::string &s) { const char *whitespace = " \t\f\v\n\r"; const auto trimmed_beg = s.find_first_not_of(whitespace); if (trimmed_beg == std::string::npos) return ""; const auto trimmed_end = s.find_last_not_of(whitespace); assert(trimmed_end != std::string::npos && trimmed_beg <= trimmed_end); return s.substr(trimmed_beg, trimmed_end - trimmed_beg + 1); } std::string TrimPrefix(const std::string &layer_key) { std::string key{}; if (layer_key.find("VK_LAYER_") == 0) { std::size_t prefix = std::strlen("VK_LAYER_"); key = layer_key.substr(prefix, layer_key.size() - prefix); } else { key = layer_key; } return key; } std::string TrimVendor(const std::string &layer_key) { static const char *separator = "_"; const std::string &namespace_key = TrimPrefix(layer_key); const auto trimmed_beg = namespace_key.find_first_of(separator); if (trimmed_beg == std::string::npos) return namespace_key; assert(namespace_key.find_last_not_of(separator) != std::string::npos && trimmed_beg <= namespace_key.find_last_not_of(separator)); return namespace_key.substr(trimmed_beg + 1, namespace_key.size()); } std::string ToLower(const std::string &s) { std::string result = s; for (auto &c : result) { c = (char)std::tolower(c); } return result; } std::string ToUpper(const std::string &s) { std::string result = s; for (auto &c : result) { c = (char)std::toupper(c); } return result; } uint32_t ToUint32(const std::string &token) { uint32_t int_id = 0; if ((token.find("0x") == 0) || token.find("0X") == 0) { // Handle hex format int_id = static_cast(std::strtoul(token.c_str(), nullptr, 16)); } else { int_id = static_cast(std::strtoul(token.c_str(), nullptr, 10)); // Decimal format } return int_id; } uint64_t ToUint64(const std::string &token) { uint64_t int_id = 0; if ((token.find("0x") == 0) || token.find("0X") == 0) { // Handle hex format int_id = static_cast(std::strtoull(token.c_str(), nullptr, 16)); } else { int_id = static_cast(std::strtoull(token.c_str(), nullptr, 10)); // Decimal format } return int_id; } int32_t ToInt32(const std::string &token) { int32_t int_id = 0; if (token.find("0x") == 0 || token.find("0X") == 0 || token.find("-0x") == 0 || token.find("-0X") == 0) { // Handle hex format int_id = static_cast(std::strtol(token.c_str(), nullptr, 16)); } else { int_id = static_cast(std::strtol(token.c_str(), nullptr, 10)); // Decimal format } return int_id; } int64_t ToInt64(const std::string &token) { int64_t int_id = 0; if (token.find("0x") == 0 || token.find("0X") == 0 || token.find("-0x") == 0 || token.find("-0X") == 0) { // Handle hex format int_id = static_cast(std::strtoll(token.c_str(), nullptr, 16)); } else { int_id = static_cast(std::strtoll(token.c_str(), nullptr, 10)); // Decimal format } return int_id; } VlFrameset ToFrameSet(const std::string &s) { assert(IsFrameSets(s)); VlFrameset frameset{0, 1, 1}; const std::vector &frameset_split = vl::Split(s, '-'); if (frameset_split.size() >= 1) { frameset.first = static_cast(std::atoll(frameset_split[0].c_str())); } if (frameset_split.size() >= 2) { frameset.count = static_cast(std::atoll(frameset_split[1].c_str())); } if (frameset_split.size() >= 3) { frameset.step = static_cast(std::atoll(frameset_split[2].c_str())); } return frameset; } std::vector ToFrameSets(const std::string &s) { std::vector tokens = Split(s, FindDelimiter(s)); std::vector results; results.resize(tokens.size()); for (std::size_t i = 0, n = tokens.size(); i < n; ++i) { results[i] = ToFrameSet(tokens[i]); } return results; } bool IsFrameSets(const std::string &s) { static const std::regex FRAME_REGEX("^([0-9]+([-][0-9]+){0,2})(,([0-9]+([-][0-9]+){0,2}))*$"); return std::regex_search(s, FRAME_REGEX); } bool IsInteger(const std::string &s) { static const std::regex FRAME_REGEX("^-?([0-9]*|0x[0-9|a-z|A-Z]*)$"); return std::regex_search(s, FRAME_REGEX); } bool IsFloat(const std::string &s) { static const std::regex FRAME_REGEX("^-?[0-9]*([.][0-9]*f?)?$"); return std::regex_search(s, FRAME_REGEX); } std::string FormatString(const char *message, ...) { std::size_t const STRING_BUFFER(4096); assert(message != nullptr); assert(strlen(message) >= 1 && strlen(message) < STRING_BUFFER); char buffer[STRING_BUFFER]; va_list list; va_start(list, message); vsnprintf(buffer, STRING_BUFFER, message, list); va_end(list); return buffer; } } // namespace vl