Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add parseStructValueString function #2019

Merged
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
54 changes: 54 additions & 0 deletions source/MaterialXCore/Value.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -193,6 +193,60 @@ template <class T> T fromValueString(const string& value)
return data;
}

StringVec parseStructValueString(const string& value)
{
static const char SEPARATOR = ';';
static const char OPEN_BRACE = '{';
static const char CLOSE_BRACE = '}';

if (value.empty())
return StringVec();

// Validate the string is correctly formatted - must be at least 2 characters long and start and end with braces
if (value.size() < 2 || (value[0] != OPEN_BRACE || value[value.size()-1] != CLOSE_BRACE))
{
return StringVec();
}

StringVec split;

// Strip off the surrounding braces
string substring = value.substr(1, value.size()-2);

// Sequentially examine each character to parse the list initializer.
string part = "";
int braceDepth = 0;
for (const char c : substring)
{
if (c == OPEN_BRACE)
{
// We've already trimmed the starting brace, so any additional braces indicate members that are themselves list initializers.
// We will just return this as a string of the list initializer.
braceDepth += 1;
}
if (braceDepth > 0 && c == CLOSE_BRACE)
{
braceDepth -= 1;
}

if (braceDepth == 0 && c == SEPARATOR)
{
// When we hit a separator we store the currently accumulated part, and clear to start collecting the next.
split.emplace_back(part);
part = "";
}
else
{
part += c;
}
}

if (!part.empty())
split.emplace_back(part);

return split;
}

//
// TypedValue methods
//
Expand Down
5 changes: 5 additions & 0 deletions source/MaterialXCore/Value.h
Original file line number Diff line number Diff line change
Expand Up @@ -216,6 +216,11 @@ template <class T> MX_CORE_API string toValueString(const T& data);
/// @throws ExceptionTypeError if the conversion cannot be performed.
template <class T> MX_CORE_API T fromValueString(const string& value);

/// Tokenize the string representation of a struct value i.e, "{1;2;3}" into a
/// vector of substrings.
/// Note: "{1;2;{3;4;5}}" will be split in to ["1", "2", "{3;4;5}"]
MX_CORE_API StringVec parseStructValueString(const string& value);

/// Forward declaration of specific template instantiations.
/// Base types
MX_CORE_EXTERN_TEMPLATE(TypedValue<int>);
Expand Down
9 changes: 9 additions & 0 deletions source/MaterialXTest/MaterialXCore/Value.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -78,6 +78,15 @@ TEST_CASE("Value strings", "[value]")
REQUIRE_THROWS_AS(mx::fromValueString<float>("text"), mx::ExceptionTypeError);
REQUIRE_THROWS_AS(mx::fromValueString<bool>("1"), mx::ExceptionTypeError);
REQUIRE_THROWS_AS(mx::fromValueString<mx::Color3>("1"), mx::ExceptionTypeError);

// Parse value strings using structure syntax features.
REQUIRE(mx::parseStructValueString("{{1;2;3};4}") == (std::vector<std::string>{"{1;2;3}","4"}));
REQUIRE(mx::parseStructValueString("{1;2;3;4}") == (std::vector<std::string>{"1","2","3","4"}));
REQUIRE(mx::parseStructValueString("{1;{2;3};4}") == (std::vector<std::string>{"1","{2;3}","4"}));
REQUIRE(mx::parseStructValueString("{1;{2;3;4}}") == (std::vector<std::string>{"1","{2;3;4}"}));
REQUIRE(mx::parseStructValueString("{1;{2;{3;4}}}") == (std::vector<std::string>{"1","{2;{3;4}}"}));
REQUIRE(mx::parseStructValueString("{1;2;{3};4}") == (std::vector<std::string>{"1","2","{3}","4"}));
REQUIRE(mx::parseStructValueString("{1;2;{3};4}") == (std::vector<std::string>{"1","2","{3}","4"}));
}

TEST_CASE("Typed values", "[value]")
Expand Down