#14648 Reduce the risk of changed behaviour for text values in lists

A quote or an opening bracket is only given special meaning when it is the first character of a value. Brackets and parentheses are treated as ordinary characters for text based values, as nested containers are not possible for these types. Text values are then parsed as before, also when they contain unbalanced brackets, parentheses or quotes.

Items in a tuple are not quoted by the Python client, as the tuple parser does not support quoted strings.

Add unit tests for text values containing separator characters, white space, file paths, numbers, nested containers and 3D vectors.
This commit is contained in:
Kristian Bendiksen committed 2026-09-09 11:19:44 +02:00
1 parent 5ed45b8f19
commit f38332b2e6
3 files changed
+240 -38

No files matched your search

@@ -201,6 +201,8 @@ constexpr bool isCamelCase( std::string_view str )
namespace caf
{
class FilePath;
template <typename DataType>
struct PdmFieldScriptingCapabilityIOHandler
{
@@ -489,8 +491,14 @@ struct PdmFieldScriptingCapabilityIOHandler<std::vector<T>>
QChar chr = errorMessageContainer->readCharWithLineNumberCount( inputStream );
if ( chr == QChar( '[' ) )
{
// Split on commas, but ignore commas inside quoted strings and inside nested
// brackets/parentheses. A quoted string can contain escaped characters.
// Split on commas, but ignore commas inside quoted strings and inside nested brackets or
// parentheses. A quote or an opening bracket is only given special meaning when it is the
// first character of an item, as text values are allowed to contain any character.
//
// Nested containers are not possible for text based values, and brackets and parentheses are
// treated as ordinary characters for these types.
const bool nestedContainersAreSupported = !std::is_same<T, QString>::value && !std::is_same<T, FilePath>::value;
std::vector<QString> allValues;
QString currentValue;
bool isInsideQuotes = false;
@@ -501,6 +509,8 @@ struct PdmFieldScriptingCapabilityIOHandler<std::vector<T>>
{
QChar currentChar = errorMessageContainer->readCharWithLineNumberCount( inputStream );
const bool isStartOfValue = currentValue.isEmpty();
if ( escapeNextChar )
{
currentValue += currentChar;
@@ -512,32 +522,34 @@ struct PdmFieldScriptingCapabilityIOHandler<std::vector<T>>
if ( currentChar == QChar( '"' ) ) isInsideQuotes = false;
currentValue += currentChar;
}
else if ( currentChar == QChar( '"' ) )
else if ( currentChar == QChar( '"' ) && isStartOfValue )
{
isInsideQuotes = true;
currentValue += currentChar;
}
else if ( currentChar == QChar( '[' ) || currentChar == QChar( '(' ) )
else if ( ( currentChar == QChar( '[' ) || currentChar == QChar( '(' ) ) &&
nestedContainersAreSupported && ( isStartOfValue || nestingDepth > 0 ) )
{
nestingDepth++;
currentValue += currentChar;
}
else if ( currentChar == QChar( ']' ) && nestingDepth == 0 )
{
break;
}
else if ( currentChar == QChar( ']' ) || currentChar == QChar( ')' ) )
else if ( nestingDepth > 0 && ( currentChar == QChar( ']' ) || currentChar == QChar( ')' ) ) )
{
nestingDepth--;
currentValue += currentChar;
}
else if ( currentChar == QChar( ']' ) )
{
// End of the array
break;
}
else if ( currentChar == QChar( ',' ) && nestingDepth == 0 )
{
QString trimmedValue = currentValue.trimmed();
if ( !trimmedValue.isEmpty() ) allValues.push_back( trimmedValue );
currentValue = "";
}
else if ( currentChar.isSpace() && currentValue.isEmpty() )
else if ( currentChar.isSpace() && isStartOfValue )
{
// Skip white space in front of a value
}