summaryrefslogtreecommitdiffstats
path: root/tools/slang-test/render-api-util.cpp
diff options
context:
space:
mode:
authorjsmall-nvidia <jsmall@nvidia.com>2018-07-25 11:57:44 -0400
committerTim Foley <tfoleyNV@users.noreply.github.com>2018-07-25 08:57:44 -0700
commitdff216cc5ddb073e5bffdd4550eda208b7527676 (patch)
tree938d28c2659765ef1d6e28acf58b77e8318974f8 /tools/slang-test/render-api-util.cpp
parent990ed7383ef1d3311dfc1023785d2dc18cca5171 (diff)
Improved command line control for apis and synthesized tests (#616)
* Parsing of control of api parameters no longer needs comma separator. Parsing of API list now can take an initial state. Document the command line option. * * Proper handling of 'default' (or initialFlags) - by using if the first token is an operator. * Clarified parsing of api flags. * Now 'vk' will mean just use vk. +vk will mean the defaults plus vk, and -vk is the defaults -vk. * Improve README.md on api expressions. Improve error text for failure to parse api expressions.
Diffstat (limited to 'tools/slang-test/render-api-util.cpp')
-rw-r--r--tools/slang-test/render-api-util.cpp134
1 files changed, 105 insertions, 29 deletions
diff --git a/tools/slang-test/render-api-util.cpp b/tools/slang-test/render-api-util.cpp
index 5f47f3b49..06a915df8 100644
--- a/tools/slang-test/render-api-util.cpp
+++ b/tools/slang-test/render-api-util.cpp
@@ -59,66 +59,142 @@ static int _calcAvailableApis()
return RenderApiType::Unknown;
}
-/* static */int RenderApiUtil::findApiFlagsByName(const Slang::UnownedStringSlice& name)
+/* static */ Slang::Result RenderApiUtil::findApiFlagsByName(const Slang::UnownedStringSlice& name, RenderApiFlags* flagsOut)
{
// Special case 'all'
if (name == "all")
{
- return int(RenderApiFlag::AllOf);
+ *flagsOut = RenderApiFlags(RenderApiFlag::AllOf);
+ return SLANG_OK;
+ }
+ if (name == "none")
+ {
+ *flagsOut = RenderApiFlags(0);
+ return SLANG_OK;
}
RenderApiType type = findApiTypeByName(name);
- return (type == RenderApiType::Unknown) ? 0 : (1 << int(type));
+ if (type == RenderApiType::Unknown)
+ {
+ return SLANG_FAIL;
+ }
+ *flagsOut = RenderApiFlags(1) << int(type);
+ return SLANG_OK;
}
-/* static */Slang::Result RenderApiUtil::parseApiFlags(const Slang::UnownedStringSlice& text, int* apiBitsOut)
+static bool isNameStartChar(char c)
+{
+ return (c >= 'a' && c <='z') || (c >= 'A' && c <= 'Z') || (c == '_');
+}
+
+static bool isNameNextChar(char c)
+{
+ return (c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z') || (c == '_') || (c >= '0' && c <= '9');
+}
+
+namespace { // anonymous
+enum class Token
+{
+ eError,
+ eOp,
+ eId,
+ eEnd,
+};
+}
+
+static Token nextToken(Slang::UnownedStringSlice& textInOut, Slang::UnownedStringSlice& lexemeOut)
{
using namespace Slang;
+ if (textInOut.size() <= 0)
+ {
+ return Token::eEnd;
+ }
+ const char* start = textInOut.begin();
+ const char* end = textInOut.end();
+
+ const char firstChar = start[0];
+ if (firstChar == '-' || firstChar == '+')
+ {
+ lexemeOut = UnownedStringSlice(start, start + 1);
+ textInOut = UnownedStringSlice(start + 1, end);
+ return Token::eOp;
+ }
+
+ if (!isNameStartChar(firstChar))
+ {
+ lexemeOut = UnownedStringSlice(start, start + 1);
+ return Token::eError;
+ }
+ const char* cur = start + 1;
+ while (cur < end && isNameNextChar(*cur))
+ {
+ cur++;
+ }
- int apiBits = 0;
+ lexemeOut = UnownedStringSlice(start, cur);
+ textInOut = UnownedStringSlice(cur, end);
+ return Token::eId;
+}
- List<UnownedStringSlice> slices;
- StringUtil::split(text, ',', slices);
+/* static */Slang::Result RenderApiUtil::parseApiFlags(const Slang::UnownedStringSlice& textIn, RenderApiFlags initialFlags, RenderApiFlags* apiFlagsOut)
+{
+ using namespace Slang;
- for (int i = 0; i < int(slices.Count()); ++i)
+ UnownedStringSlice text(textIn);
+ UnownedStringSlice lexeme;
+
+ RenderApiFlags apiFlags = 0;
+
+ switch (nextToken(text, lexeme))
{
- UnownedStringSlice slice = slices[i];
- bool add = true;
- if (slice.size() <= 0)
+ case Token::eOp:
{
- return SLANG_FAIL;
+ // If we start with an op - we use the passed in values as the default
+ // Rewind back to the start
+ text = textIn;
+ apiFlags = initialFlags;
+ break;
}
- if (slice[0] == '+')
+ case Token::eId:
{
- // Drop the +
- slice = UnownedStringSlice(slice.begin() + 1, slice.end());
+ // If we start with an Id - we use that as the starting state
+ SLANG_RETURN_ON_FAIL(findApiFlagsByName(lexeme, &apiFlags));
+ break;
}
- else if (slice[0] == '-')
+ default: return SLANG_FAIL;
+ }
+
+ while (true)
+ {
+ // Must have an op followed by an id unless we are at the end
+ switch (nextToken(text, lexeme))
{
- add = false;
- // Drop the +
- slice = UnownedStringSlice(slice.begin() + 1, slice.end());
+ case Token::eEnd:
+ {
+ *apiFlagsOut = apiFlags;
+ return SLANG_OK;
+ }
+ case Token::eOp: break;
+ default: return SLANG_FAIL;
}
- // We need to find the bits...
- int bits = findApiFlagsByName(slice);
- // 0 means an error
- if (bits == 0)
+ const char op = lexeme[0];
+ if (nextToken(text, lexeme) != Token::eId)
{
return SLANG_FAIL;
}
- if (add)
+ RenderApiFlags flags;
+ SLANG_RETURN_ON_FAIL(findApiFlagsByName(lexeme, &flags));
+
+ if (op == '+')
{
- apiBits |= bits;
+ apiFlags |= flags;
}
else
{
- apiBits &= ~bits;
+ apiFlags &= ~flags;
}
}
-
- *apiBitsOut = apiBits;
- return SLANG_OK;
}
/* !!!!!!!!!!!!!!!!!!!!!!!!!!!! Platform specific stuff !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! */