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
@@ -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;
10 changes: 10 additions & 0 deletions include/OpenColorIO/OpenColorIO.h
Original file line number Diff line number Diff line change
@@ -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
@@ -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;
145 changes: 144 additions & 1 deletion src/OpenColorIO/Config.cpp
Original file line number Diff line number Diff line change
@@ -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());
}
}
@@ -4005,6 +4005,88 @@ const char * Config::getActiveDisplays() const
return getImpl()->m_activeDisplaysStr.c_str();
}

void Config::addActiveDisplay(const char * view)
{
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());
}

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());
}

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;
}

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();
@@ -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());
6 changes: 6 additions & 0 deletions src/OpenColorIO/LookParse.cpp
Original file line number Diff line number Diff line change
@@ -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);
}

m_options.push_back(tokens);
}

19 changes: 15 additions & 4 deletions src/OpenColorIO/OCIOYaml.cpp
Original file line number Diff line number Diff line change
@@ -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;

const std::string inactiveCSs = config.getInactiveColorSpaces();
129 changes: 117 additions & 12 deletions src/OpenColorIO/ParseUtils.cpp
Original file line number Diff line number Diff line change
@@ -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 ",".
// 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;
}
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

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];
}
}

return result;
}

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