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

Adding support for commas in active views list #26

Merged
merged 9 commits into from
Dec 13, 2024
4 changes: 4 additions & 0 deletions include/OpenColorIO/OpenColorAppHelpers.h
Original file line number Diff line number Diff line change
Expand Up @@ -666,9 +666,13 @@ class OCIOEXPORT ConfigMergingParameters

void setActiveDisplays(const char * displays);
const char * getActiveDisplays() const;
int getNumActiveDisplays() const;
const char * getActiveDisplay(int index) const;

void setActiveViews(const char * views);
const char * getActiveViews() const;
int getNumActiveViews() const;
const char * getActiveView(int index) const;

void setInactiveColorspaces(const char * colorspaces);
const char * getInactiveColorSpaces() const;
Expand Down
10 changes: 10 additions & 0 deletions include/OpenColorIO/OpenColorIO.h
Original file line number Diff line number Diff line change
Expand Up @@ -1086,6 +1086,11 @@ class OCIOEXPORT Config
*/
void setActiveDisplays(const char * displays);
const char * getActiveDisplays() const;
void addActiveDisplay(const char * view);
void removeActiveDisplay(const char * view);
void clearActiveDisplays();
const char * getActiveDisplay(int index) const;
int getNumActiveDisplays() const;

/**
* \brief
Expand All @@ -1104,6 +1109,11 @@ class OCIOEXPORT Config
*/
void setActiveViews(const char * views);
const char * getActiveViews() const;
void addActiveView(const char * view);
void removeActiveView(const char * view);
void clearActiveViews();
const char * getActiveView(int index) const;
int getNumActiveViews() const;

/// Get all displays in the config, ignoring the active_displays list.
int getNumDisplaysAll() const noexcept;
Expand Down
145 changes: 144 additions & 1 deletion src/OpenColorIO/Config.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -3411,7 +3411,7 @@ void Config::removeSharedView(const char * view)
{
std::ostringstream os;
os << "Shared view could not be removed from config. A shared view named '"
<< view << "' could be be found.";
<< view << "' could not be found.";
throw Exception(os.str().c_str());
}
}
Expand Down Expand Up @@ -4005,6 +4005,88 @@ const char * Config::getActiveDisplays() const
return getImpl()->m_activeDisplaysStr.c_str();
}

void Config::addActiveDisplay(const char * view)
doug-walker marked this conversation as resolved.
Show resolved Hide resolved
{
if( !view || !view[0] )
{
throw Exception("Active display could not be added to config, display name has to be a "
"non-empty name.");
}

auto it = std::find(getImpl()->m_activeDisplays.begin(),
getImpl()->m_activeDisplays.end(), view);

if( it != getImpl()->m_activeDisplays.end() )
{
std::ostringstream os;
os << "Active display could not be added to config. An active display named '"
<< view << "' already exists.";
throw Exception(os.str().c_str());
}
doug-walker marked this conversation as resolved.
Show resolved Hide resolved

getImpl()->m_activeDisplays.push_back(view);

getImpl()->m_displayCache.clear();

AutoMutex lock(getImpl()->m_cacheidMutex);
getImpl()->resetCacheIDs();
}

void Config::removeActiveDisplay(const char * display)
{
if( !display || !display[0] )
{
throw Exception("Active display could not be removed from config, display name has to be a "
"non-empty name.");
}

auto it = std::find(getImpl()->m_activeDisplays.begin(),
getImpl()->m_activeDisplays.end(), display);

if( it != getImpl()->m_activeDisplays.end() )
{
getImpl()->m_activeDisplays.erase(it);
}
else
{
std::ostringstream os;
os << "Active display could not be removed from config. An active display named '"
<< display << "' could not be found.";
throw Exception(os.str().c_str());
}
doug-walker marked this conversation as resolved.
Show resolved Hide resolved

getImpl()->m_displayCache.clear();

AutoMutex lock(getImpl()->m_cacheidMutex);
getImpl()->resetCacheIDs();
}

void Config::clearActiveDisplays()
{
getImpl()->m_activeDisplays.clear();

getImpl()->m_displayCache.clear();

AutoMutex lock(getImpl()->m_cacheidMutex);
getImpl()->resetCacheIDs();
}

const char * Config::getActiveDisplay( int index ) const
{
if( index<0 ||
index >= static_cast<int>(getImpl()->m_activeDisplays.size()))
{
return nullptr;
}
doug-walker marked this conversation as resolved.
Show resolved Hide resolved

return getImpl()->m_activeDisplays[index].c_str();
}

int Config::getNumActiveDisplays() const
{
return static_cast<int>(getImpl()->m_activeDisplays.size());
}

void Config::setActiveViews(const char * views)
{
getImpl()->m_activeViews.clear();
Expand All @@ -4022,6 +4104,67 @@ const char * Config::getActiveViews() const
return getImpl()->m_activeViewsStr.c_str();
}

void Config::addActiveView(const char * view)
{
if( !view || !view[0] )
{
throw Exception("Active view could not be added to config, view name has to be a "
"non-empty name.");
}

getImpl()->m_activeViews.push_back(view);

getImpl()->m_displayCache.clear();
AutoMutex lock(getImpl()->m_cacheidMutex);
getImpl()->resetCacheIDs();
}

void Config::removeActiveView(const char * view)
{
if( !view || !view[0] )
{
throw Exception("Active view could not be removed from config, view name has to be a "
"non-empty name.");
}

auto it = std::find(getImpl()->m_activeViews.begin(),
getImpl()->m_activeViews.end(), view);

if(it!=getImpl()->m_activeViews.end())
{
getImpl()->m_activeViews.erase(it);
}

getImpl()->m_displayCache.clear();
AutoMutex lock(getImpl()->m_cacheidMutex);
getImpl()->resetCacheIDs();
}

void Config::clearActiveViews()
{
getImpl()->m_activeViews.clear();

getImpl()->m_displayCache.clear();
AutoMutex lock(getImpl()->m_cacheidMutex);
getImpl()->resetCacheIDs();
}

const char * Config::getActiveView( int index ) const
{
if( index<0 ||
index >= static_cast<int>(getImpl()->m_activeViews.size()))
{
return nullptr;
}

return getImpl()->m_activeViews[index].c_str();
}

int Config::getNumActiveViews() const
{
return static_cast<int>(getImpl()->m_activeViews.size());
}

int Config::getNumDisplaysAll() const noexcept
{
return static_cast<int>(getImpl()->m_displays.size());
Expand Down
6 changes: 6 additions & 0 deletions src/OpenColorIO/LookParse.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -84,6 +84,12 @@ const LookParseResult::Options & LookParseResult::parse(const std::string & look
tokens.push_back(t);
}

if( vec.size() == 0 )
{
LookParseResult::Token t;
tokens.push_back(t);
}
doug-walker marked this conversation as resolved.
Show resolved Hide resolved

m_options.push_back(tokens);
}

Expand Down
19 changes: 15 additions & 4 deletions src/OpenColorIO/OCIOYaml.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -4992,13 +4992,24 @@ inline void save(YAML::Emitter & out, const Config & config)
out << YAML::Newline;
out << YAML::Key << "active_displays";
StringUtils::StringVec active_displays;
if(config.getActiveDisplays() != NULL && strlen(config.getActiveDisplays()) > 0)
active_displays = SplitStringEnvStyle(config.getActiveDisplays());
int nDisplays = config.getNumActiveDisplays();
active_displays.reserve( nDisplays );
for (int i = 0; i < nDisplays; i++)
{
active_displays.push_back(config.getActiveDisplay(i));
}

out << YAML::Value << YAML::Flow << active_displays;


out << YAML::Key << "active_views";
StringUtils::StringVec active_views;
if(config.getActiveViews() != NULL && strlen(config.getActiveViews()) > 0)
active_views = SplitStringEnvStyle(config.getActiveViews());
int nViews = config.getNumActiveViews();
active_views.reserve( nViews );
for (int i = 0; i < nViews; i++)
{
active_views.push_back(config.getActiveView(i));
}
out << YAML::Value << YAML::Flow << active_views;
doug-walker marked this conversation as resolved.
Show resolved Hide resolved

const std::string inactiveCSs = config.getInactiveColorSpaces();
Expand Down
129 changes: 117 additions & 12 deletions src/OpenColorIO/ParseUtils.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -690,33 +690,138 @@ bool StrEqualsCaseIgnore(const std::string & a, const std::string & b)
return 0 == Platform::Strcasecmp(a.c_str(), b.c_str());
}

// Find the end of a name from a list contained in a string.
// The element of the list are separeted by ":" or ",".
doug-walker marked this conversation as resolved.
Show resolved Hide resolved
// The name can be surrounded by quotes to enable name including theses symbols.
static int findEndOfName(const std::string & s, size_t start)
{
int currentPos = start;
int nameEndPos = currentPos;
bool isEndFound = false;

while( !isEndFound )
{
nameEndPos = s.find_first_of("\",:", currentPos);
if(nameEndPos == (int)std::string::npos)
{
// We reached the end of the list
nameEndPos = s.size();
isEndFound = true;
}
else if( s[nameEndPos] == '"' )
{
// We found a quote, we need to find the next one
nameEndPos = s.find_first_of("\"", nameEndPos + 1);
if(nameEndPos == (int)std::string::npos)
{
// We reached the end of the list instead
nameEndPos = s.size();
isEndFound = true;
doug-walker marked this conversation as resolved.
Show resolved Hide resolved
}
else
{
// We found the second quote,
// we need to continue the search for a symbol separating the elements (: or ,)
currentPos = nameEndPos + 1;
}
}
else if( s[nameEndPos] == ',' ||
s[nameEndPos] == ':' )
{
// We found a symbol separating the elements, we stop here
isEndFound = true;
}
}

return nameEndPos;
}

StringUtils::StringVec SplitStringEnvStyle(const std::string & str)
{
StringUtils::StringVec outputvec;
const std::string s = StringUtils::Trim(str);
if (StringUtils::Find(s, ",") != std::string::npos)
if( s.size() == 0 )
{
outputvec = StringUtils::Split(s, ',');
return {};
}
else if (StringUtils::Find(s, ":") != std::string::npos)
{
outputvec = StringUtils::Split(s, ':');
}
else
doug-walker marked this conversation as resolved.
Show resolved Hide resolved

StringUtils::StringVec outputvec;
int currentPos = 0;
while( s.size() > 0 &&
currentPos <= (int) s.size() )
{
outputvec.push_back(s);
int nameEndPos = findEndOfName(s, currentPos);
if(nameEndPos > currentPos)
{
outputvec.push_back(s.substr(currentPos, nameEndPos - currentPos));
currentPos = nameEndPos + 1;
}
else
{
outputvec.push_back("");
currentPos += 1;
}
}

for (auto & val : outputvec)
for ( auto & val : outputvec )
{
val = StringUtils::Trim(val);
const std::string trimmedValue = StringUtils::Trim(val);

// If the trimmed value is surrounded by quotes, we remove them
if( trimmedValue.size() > 1 &&
trimmedValue[0] == '"' &&
trimmedValue[trimmedValue.size() - 1] == '"' )
{
val = trimmedValue.substr(1, trimmedValue.size() - 2);
}
else
{
val = trimmedValue;
}
}

return outputvec;
}

std::string JoinStringEnvStyle(const StringUtils::StringVec & outputvec)
{
return StringUtils::Join(outputvec, ',');
std::string result;
const int nElement = static_cast<int>(outputvec.size());
if( nElement == 0 )
{
return "";
}

// We check if the value contains a symbol that could be interpreted as a separator
// and if it is not already surrounded by quotes
const std::string& firstValue = outputvec[0];
if( firstValue.find_first_of(",:") != std::string::npos &&
firstValue.size() > 1 &&
firstValue[0] != '"' &&
firstValue[firstValue.size() - 1] != '"' )
{
result += "\"" + firstValue + "\"";
}
else
{
result += firstValue;
}

for( int i = 1; i < nElement; ++i )
{
if( outputvec[i].find_first_of(",:") != std::string::npos &&
outputvec[i].size() > 1 &&
outputvec[i][0] != '"' &&
outputvec[i][outputvec[i].size() - 1] != '"' )
{
result += ", \"" + outputvec[i] + "\"";
}
else
{
result += ", " + outputvec[i];
}
}
doug-walker marked this conversation as resolved.
Show resolved Hide resolved

return result;
}

// Return a vector of strings that are both in vec1 and vec2.
Expand Down
Loading
Loading