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 2 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 @@ -254,6 +254,60 @@ ScopedFloatFormatting::~ScopedFloatFormatting()
Value::setFloatPrecision(_precision);
}

StringVec parseStructValueString(const string& str)
jstone-lucasfilm marked this conversation as resolved.
Show resolved Hide resolved
{
const char SEPARATOR = ';';
jstone-lucasfilm marked this conversation as resolved.
Show resolved Hide resolved
const char OPEN_BRACE = '{';
const char CLOSE_BRACE = '}';

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

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

StringVec split;

// strip off the surrounding braces
string substring = str.substr(1, str.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 accumlated 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;
}

//
// Value registry class
//
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& str);

/// Forward declaration of specific template instantiations.
/// Base types
MX_CORE_EXTERN_TEMPLATE(TypedValue<int>);
Expand Down
8 changes: 8 additions & 0 deletions source/MaterialXTest/MaterialXCore/Value.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -78,6 +78,14 @@ 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);

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