blob: d04140bf7717daf895ec28394f5c0f629e8706c3 [file] [log] [blame]
{{- /* ------------------------------------------------------------------ */ -}}
{{- define "EnumCase" -}}
{{- /* Prints the 'Enum::kEntry' name for the provided sem.EnumEntry */ -}}
{{- /* argument. */ -}}
{{- /* ------------------------------------------------------------------ */ -}}
{{PascalCase $.Enum.Name}}::k{{PascalCase $.Name}}
{{- end -}}
{{- /* ------------------------------------------------------------------ */ -}}
{{- define "DeclareEnum" -}}
{{- /* Declares the 'enum class' for the provided sem.Enum argument. */ -}}
{{- /* ------------------------------------------------------------------ */ -}}
{{- $enum := PascalCase $.Name -}}
enum class {{$enum}} {
kUndefined,
{{- range $entry := $.Entries }}
k{{PascalCase $entry.Name}},{{if $entry.IsInternal}} // Tint-internal enum entry - not parsed{{end}}
{{- end }}
};
/// @param out the std::ostream to write to
/// @param value the {{$enum}}
/// @returns `out` so calls can be chained
std::ostream& operator<<(std::ostream& out, {{$enum}} value);
/// Parse{{$enum}} parses a {{$enum}} from a string.
/// @param str the string to parse
/// @returns the parsed enum, or {{$enum}}::kUndefined if the string could not be parsed.
{{$enum}} Parse{{$enum}}(std::string_view str);
constexpr const char* k{{$enum}}Strings[] = {
{{- range $entry := $.Entries }}
{{- if not $entry.IsInternal}}
"{{$entry.Name}}",
{{- end }}
{{- end }}
};
{{- end -}}
{{- /* ------------------------------------------------------------------ */ -}}
{{- define "ParseEnum" -}}
{{- /* Implements the 'ParseEnum' function for the provided sem.Enum */ -}}
{{- /* argument. */ -}}
{{- /* ------------------------------------------------------------------ */ -}}
{{- $enum := PascalCase $.Name -}}
/// Parse{{$enum}} parses a {{$enum}} from a string.
/// @param str the string to parse
/// @returns the parsed enum, or {{$enum}}::kUndefined if the string could not be parsed.
{{$enum}} Parse{{$enum}}(std::string_view str) {
{{- range $entry := $.PublicEntries }}
if (str == "{{$entry.Name}}") {
return {{template "EnumCase" $entry}};
}
{{- end }}
return {{$enum}}::kUndefined;
}
{{- end -}}
{{- /* ------------------------------------------------------------------ */ -}}
{{- define "EnumOStream" -}}
{{- /* Implements the std::ostream 'operator<<()' function to print the */ -}}
{{- /* provided sem.Enum. */ -}}
{{- /* ------------------------------------------------------------------ */ -}}
{{- $enum := PascalCase $.Name -}}
std::ostream& operator<<(std::ostream& out, {{$enum}} value) {
switch (value) {
case {{$enum}}::kUndefined:
return out << "undefined";
{{- range $entry := $.Entries }}
case {{template "EnumCase" $entry}}:
return out << "{{$entry.Name}}";
{{- end }}
}
return out << "<unknown>";
}
{{- end -}}
{{- /* ------------------------------------------------------------------ */ -}}
{{- define "TestParsePrintEnum" -}}
{{- /* Implements unit tests for parsing and printing the provided */ -}}
{{- /* sem.Enum argument. */ -}}
{{- /* ------------------------------------------------------------------ */ -}}
{{- $enum := PascalCase $.Name -}}
namespace parse_print_tests {
struct Case {
const char* string;
{{$enum}} value;
};
inline std::ostream& operator<<(std::ostream& out, Case c) {
return out << "'" << std::string(c.string) << "'";
}
static constexpr Case kValidCases[] = {
{{- range $entry := $.PublicEntries }}
{"{{$entry.Name}}", {{template "EnumCase" $entry}}},
{{- end }}
};
static constexpr Case kInvalidCases[] = {
{{- $exclude := $.NameSet -}}
{{- range $entry := $.PublicEntries }}
{"{{Scramble $entry.Name $exclude}}", {{$enum}}::kUndefined},
{"{{Scramble $entry.Name $exclude}}", {{$enum}}::kUndefined},
{"{{Scramble $entry.Name $exclude}}", {{$enum}}::kUndefined},
{{- end }}
};
using {{$enum}}ParseTest = testing::TestWithParam<Case>;
TEST_P({{$enum}}ParseTest, Parse) {
const char* string = GetParam().string;
{{$enum}} expect = GetParam().value;
EXPECT_EQ(expect, Parse{{$enum}}(string));
}
INSTANTIATE_TEST_SUITE_P(ValidCases, {{$enum}}ParseTest, testing::ValuesIn(kValidCases));
INSTANTIATE_TEST_SUITE_P(InvalidCases, {{$enum}}ParseTest, testing::ValuesIn(kInvalidCases));
using {{$enum}}PrintTest = testing::TestWithParam<Case>;
TEST_P({{$enum}}PrintTest, Print) {
{{$enum}} value = GetParam().value;
const char* expect = GetParam().string;
EXPECT_EQ(expect, utils::ToString(value));
}
INSTANTIATE_TEST_SUITE_P(ValidCases, {{$enum}}PrintTest, testing::ValuesIn(kValidCases));
} // namespace parse_print_tests
{{- end -}}
{{- /* ------------------------------------------------------------------ */ -}}
{{- define "BenchmarkParseEnum" -}}
{{- /* Implements a micro-benchmark for parsing the provided sem.Enum */ -}}
{{- /* argument. */ -}}
{{- /* ------------------------------------------------------------------ */ -}}
{{- $enum := PascalCase $.Name -}}
void {{$enum}}Parser(::benchmark::State& state) {
std::array kStrings{
{{- $exclude := $.NameSet -}}
{{- range $entry := $.PublicEntries }}
"{{Scramble $entry.Name $exclude}}",
"{{Scramble $entry.Name $exclude}}",
"{{Scramble $entry.Name $exclude}}",
"{{$entry.Name}}",
"{{Scramble $entry.Name $exclude}}",
"{{Scramble $entry.Name $exclude}}",
"{{Scramble $entry.Name $exclude}}",
{{- end }}
};
for (auto _ : state) {
for (auto& str : kStrings) {
auto result = Parse{{$enum}}(str);
benchmark::DoNotOptimize(result);
}
}
}
BENCHMARK({{$enum}}Parser);
{{- end -}}