GPU: Shader Preprocess: Add utility to search for references
This utility will only match `&` character inside a reference declaration. This is needed for speeding up the regex matches.
This commit is contained in:
@@ -1097,6 +1097,44 @@ class Preprocessor {
|
||||
{
|
||||
return char_count(str, '\n');
|
||||
}
|
||||
|
||||
/* Match any reference definition (e.g. `int &a = b`).
|
||||
* Call the callback function for each `&` character that matches a reference definition.
|
||||
* Expects the input `str` to be formatted with balanced parenthesis and curly brackets. */
|
||||
static void reference_search(std::string &str, std::function<void(int, int, char &)> callback)
|
||||
{
|
||||
size_t pos = 0;
|
||||
int parenthesis_depth = 0;
|
||||
int bracket_depth = 0;
|
||||
for (char &c : str) {
|
||||
if (c == '&') {
|
||||
if (pos > 0 && pos <= str.length() - 2) {
|
||||
/* This is made safe by the previous check and by starting at pos = 1. */
|
||||
char prev_char = str[pos - 1];
|
||||
char next_char = str[pos + 1];
|
||||
/* Validate it is not an operator (`&`, `&&`, `&=`). */
|
||||
if (prev_char == ' ' || prev_char == '(') {
|
||||
if (next_char != ' ' && next_char != '&' && next_char != '=') {
|
||||
callback(parenthesis_depth, bracket_depth, c);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (c == '(') {
|
||||
parenthesis_depth++;
|
||||
}
|
||||
else if (c == ')') {
|
||||
parenthesis_depth--;
|
||||
}
|
||||
else if (c == '{') {
|
||||
bracket_depth++;
|
||||
}
|
||||
else if (c == '}') {
|
||||
bracket_depth--;
|
||||
}
|
||||
pos++;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
} // namespace blender::gpu::shader
|
||||
|
||||
@@ -12,7 +12,7 @@ static void test_preprocess_utilities()
|
||||
{
|
||||
using namespace shader;
|
||||
using namespace std;
|
||||
/* get_content_between_balanced_pair */
|
||||
|
||||
string input = "test (u, u(s,(s,s)), u) {t{{}},t,{};(,)} {u{}} end";
|
||||
EXPECT_EQ(Preprocessor::get_content_between_balanced_pair(input, '{', '}'), "t{{}},t,{};(,)");
|
||||
EXPECT_EQ(Preprocessor::get_content_between_balanced_pair(input, '{', '}', true), "u{}");
|
||||
@@ -29,6 +29,24 @@ static void test_preprocess_utilities()
|
||||
vector<string> split_result2 = Preprocessor::split_string_not_between_balanced_pair(
|
||||
input2, ',', '(', ')');
|
||||
EXPECT_EQ_VECTOR(split_expect2, split_result2);
|
||||
|
||||
string input_reference = "void func(int &a, int (&c)[2]) {{ int &b = a; }} int &b = a;";
|
||||
int fn_ref_count = 0, arg_ref_count = 0, global_ref_count = 0;
|
||||
Preprocessor::reference_search(
|
||||
input_reference, [&](int parenthesis_depth, int bracket_depth, char & /*c*/) {
|
||||
if ((parenthesis_depth == 1 || parenthesis_depth == 2) && bracket_depth == 0) {
|
||||
arg_ref_count += 1;
|
||||
}
|
||||
else if (bracket_depth > 0) {
|
||||
fn_ref_count += 1;
|
||||
}
|
||||
else if (bracket_depth == 0 && parenthesis_depth == 0) {
|
||||
global_ref_count += 1;
|
||||
}
|
||||
});
|
||||
EXPECT_EQ(arg_ref_count, 2);
|
||||
EXPECT_EQ(fn_ref_count, 1);
|
||||
EXPECT_EQ(global_ref_count, 1);
|
||||
}
|
||||
GPU_TEST(preprocess_utilities);
|
||||
|
||||
|
||||
Reference in New Issue
Block a user