blob: 8622cdab4818cfcf93d918b54ec533e422cc8b8b [file] [log] [blame]
// Copyright 2023 The Khronos Group Inc.
// Copyright 2023 Valve Corporation
// Copyright 2023 LunarG, Inc.
//
// SPDX-License-Identifier: Apache-2.0
//
// Author(s):
// - Christophe Riccio <christophe@lunarg.com>
#include "layer_settings_util.hpp"
#include <sstream>
#include <regex>
#include <cstdlib>
#include <cassert>
#include <cstdint>
namespace vl {
std::vector<std::string> Split(const std::string &pValues, char delimiter) {
std::vector<std::string> 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<uint32_t>(std::strtoul(token.c_str(), nullptr, 16));
} else {
int_id = static_cast<uint32_t>(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<uint64_t>(std::strtoull(token.c_str(), nullptr, 16));
} else {
int_id = static_cast<uint64_t>(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<int32_t>(std::strtol(token.c_str(), nullptr, 16));
} else {
int_id = static_cast<int32_t>(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<uint64_t>(std::strtoll(token.c_str(), nullptr, 16));
} else {
int_id = static_cast<uint64_t>(std::strtoll(token.c_str(), nullptr, 10)); // Decimal format
}
return int_id;
}
VkFramesetEXT ToFrameSet(const std::string &s) {
assert(IsFrameSets(s));
VkFramesetEXT frameset{0, 1, 1};
const std::vector<std::string> &frameset_split = vl::Split(s, '-');
if (frameset_split.size() >= 1) {
frameset.first = static_cast<std::uint32_t>(std::atoll(frameset_split[0].c_str()));
}
if (frameset_split.size() >= 2) {
frameset.count = static_cast<std::uint32_t>(std::atoll(frameset_split[1].c_str()));
}
if (frameset_split.size() >= 3) {
frameset.step = static_cast<std::uint32_t>(std::atoll(frameset_split[2].c_str()));
}
return frameset;
}
std::vector<VkFramesetEXT> ToFrameSets(const std::string &s) {
std::vector<std::string> tokens = Split(s, FindDelimiter(s));
std::vector<VkFramesetEXT> 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 Format(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