Add reader::spv::Namer::Sanitize

Bug: tint:3
Change-Id: I4d554755dacecac0f2dacf191d85f8e339e87923
Reviewed-on: https://dawn-review.googlesource.com/c/tint/+/17420
Reviewed-by: dan sinclair <dsinclair@google.com>
This commit is contained in:
David Neto 2020-03-23 16:42:21 +00:00 committed by dan sinclair
parent 7b7ff741c5
commit bd1d142134
3 changed files with 62 additions and 1 deletions

View File

@ -14,6 +14,8 @@
#include "src/reader/spirv/namer.h"
#include <algorithm>
namespace tint {
namespace reader {
namespace spirv {
@ -22,6 +24,30 @@ Namer::Namer(const FailStream& fail_stream) : fail_stream_(fail_stream) {}
Namer::~Namer() = default;
std::string Namer::Sanitize(const std::string& suggested_name) {
if (suggested_name.empty()) {
return "empty";
}
// Otherwise, replace invalid characters by '_'.
std::string result;
std::string invalid_as_first_char = "_0123456789";
std::string valid =
"abcdefghijklmnopqrstuvwxyz"
"ABCDEFGHIJKLMNOPQRSTUVWXYZ"
"_0123456789";
// If the first character is invalid for starting a WGSL identifier, then
// prefix the result with "x".
if ((std::string::npos != invalid_as_first_char.find(suggested_name[0])) ||
(std::string::npos == valid.find(suggested_name[0]))) {
result = "x";
}
std::transform(suggested_name.begin(), suggested_name.end(),
std::back_inserter(result), [&valid](const char c) {
return (std::string::npos == valid.find(c)) ? '_' : c;
});
return result;
}
bool Namer::SaveName(uint32_t id, const std::string& name) {
if (HasName(id)) {
return Fail() << "internal error: ID " << id

View File

@ -26,6 +26,12 @@ namespace reader {
namespace spirv {
/// A Namer maps SPIR-V IDs to strings.
///
/// Sanitization:
/// Some names are user-suggested, but "sanitized" in the sense that an
/// unusual character (e.g. invalid for use in WGSL identifiers) is remapped
/// to a safer character such as an underscore. Also, sanitized names
/// never start with an underscorre.
class Namer {
public:
/// Creates a new namer
@ -34,6 +40,13 @@ class Namer {
/// Destructor
~Namer();
/// Sanitizes the given string, to replace unusual characters with
/// obviously-valid idenfier characters. An empy string yields "empty".
/// A sanitized name never starts with an underscore.
/// @param suggested_name input string
/// @returns sanitized name, suitable for use as an identifier
static std::string Sanitize(const std::string& suggested_name);
/// Registers a failure.
/// @returns a fail stream to accumulate diagnostics.
FailStream& Fail() { return fail_stream_.Fail(); }

View File

@ -18,7 +18,7 @@
#include <sstream>
#include <string>
#include "gtest/gtest.h"
#include "gmock/gmock.h"
#include "src/reader/spirv/fail_stream.h"
namespace tint {
@ -26,6 +26,8 @@ namespace reader {
namespace spirv {
namespace {
using ::testing::Eq;
class SpvNamerTest : public testing::Test {
public:
SpvNamerTest() : fail_stream_(&success_, &errors_) {}
@ -39,6 +41,26 @@ class SpvNamerTest : public testing::Test {
FailStream fail_stream_;
};
TEST_F(SpvNamerTest, SanitizeEmpty) {
EXPECT_THAT(Namer::Sanitize(""), Eq("empty"));
}
TEST_F(SpvNamerTest, SanitizeLeadingUnderscore) {
EXPECT_THAT(Namer::Sanitize("_"), Eq("x_"));
}
TEST_F(SpvNamerTest, SanitizeLeadingDigit) {
EXPECT_THAT(Namer::Sanitize("7zip"), Eq("x7zip"));
}
TEST_F(SpvNamerTest, SanitizeOkChars) {
EXPECT_THAT(Namer::Sanitize("_abcdef12345"), Eq("x_abcdef12345"));
}
TEST_F(SpvNamerTest, SanitizeNonIdentifierChars) {
EXPECT_THAT(Namer::Sanitize("a:1.2'f\n"), "a_1_2_f_");
}
TEST_F(SpvNamerTest, NoFailureToStart) {
Namer namer(fail_stream_);
EXPECT_TRUE(success_);