Skip to content

Commit

Permalink
Add get_indexed() to ParmValueList and AttrDelegate. (AcademySoftware…
Browse files Browse the repository at this point in the history
…Foundation#2526)

This lets you pull out a single base value from an aggregate and/or
array attribute.
  • Loading branch information
lgritz committed Mar 25, 2020
1 parent fca673c commit a653c53
Show file tree
Hide file tree
Showing 5 changed files with 86 additions and 4 deletions.
27 changes: 27 additions & 0 deletions src/include/OpenImageIO/attrdelegate.h
Original file line number Diff line number Diff line change
Expand Up @@ -149,6 +149,33 @@ template<class C> class AttrDelegate {
return m_obj->getattribute(m_name, TypeString, &s) ? T(s) : defaultval;
}

// `Delegate->get_indexed<T>(int index, defaultval=T())` retrieves the
// index-th base value in the data as type T, or the defaultval if no
// such named data exists or is not the designated type.
template<typename T,
typename std::enable_if<!pvt::is_string<T>::value, int>::type = 0>
inline T get_indexed(int index, const T& defaultval = T()) const
{
T result;
if (!m_obj->getattribute_indexed(m_name, index,
TypeDescFromC<T>::value(), &result))
result = defaultval;
return result;
}

// Using enable_if, make a slightly different version of get_indexed<>
// for strings, which need to do some ustring magic because we can't
// directly store in a std::string or string_view.
template<typename T = string_view,
typename std::enable_if<pvt::is_string<T>::value, int>::type = 1>
inline T get_indexed(int index, const T& defaultval = T()) const
{
ustring s;
return m_obj->getattribute_indexed(m_name, index, TypeString, &s)
? T(s)
: defaultval;
}

// `Delegate->as_string(defaultval="")` returns the data, no matter its
// type, as a string. Returns the defaultval if no such data exists at
// all.
Expand Down
9 changes: 9 additions & 0 deletions src/include/OpenImageIO/paramlist.h
Original file line number Diff line number Diff line change
Expand Up @@ -368,6 +368,15 @@ class OIIO_API ParamValueList : public std::vector<ParamValue> {
bool getattribute(string_view name, std::string& value,
bool casesensitive = false) const;

/// Retrieve from list: If found its data type is reasonably convertible
/// to `type`, copy/convert the value into val[...] and return true.
/// Otherwise, return false and don't modify what val points to.
bool getattribute_indexed(string_view name, int index, TypeDesc type,
void* value, bool casesensitive = false) const;
/// Shortcut for retrieving a single string via getattribute.
bool getattribute_indexed(string_view name, int index, std::string& value,
bool casesensitive = false) const;

/// Sort alphabetically, optionally case-insensitively, locale-
/// independently, and with all the "un-namespaced" items appearing
/// first, followed by items with "prefixed namespaces" (e.g. "z" comes
Expand Down
8 changes: 4 additions & 4 deletions src/include/OpenImageIO/typedesc.h
Original file line number Diff line number Diff line change
Expand Up @@ -222,9 +222,9 @@ struct OIIO_API TypeDesc {
/// ignoring whether it's an array).
size_t elementsize () const noexcept { return aggregate * basesize(); }

// /// Return just the underlying C scalar type, i.e., strip out the
// /// array-ness and the aggregateness.
// BASETYPE basetype () const { return TypeDesc(base); }
/// Return just the underlying C scalar type, i.e., strip out the
/// array-ness and the aggregateness.
constexpr TypeDesc scalartype() const { return TypeDesc(BASETYPE(basetype)); }

/// Return the base type size, i.e., stripped of both array-ness
/// and aggregateness.
Expand All @@ -240,7 +240,7 @@ struct OIIO_API TypeDesc {
/// Shortcut: is it UNKNOWN?
constexpr bool is_unknown () const noexcept { return (basetype == UNKNOWN); }

/// if (typespec) is the same as asking whether it's not UNKNOWN.
/// if (typedesc) is the same as asking whether it's not UNKNOWN.
constexpr operator bool () const noexcept { return (basetype != UNKNOWN); }

/// Set *this to the type described in the string. Return the
Expand Down
43 changes: 43 additions & 0 deletions src/libutil/paramlist.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -677,6 +677,49 @@ ParamValueList::getattribute(string_view name, std::string& value,



bool
ParamValueList::getattribute_indexed(string_view name, int index, TypeDesc type,
void* value, bool casesensitive) const
{
auto p = find(name, TypeUnknown, casesensitive);
if (p != cend()) {
if (index >= int(p->type().basevalues()))
return false;
TypeDesc basetype = p->type().scalartype();
return convert_type(basetype,
(const char*)p->data() + index * basetype.size(),
type, value);
} else {
return false;
}
}



bool
ParamValueList::getattribute_indexed(string_view name, int index,
std::string& value,
bool casesensitive) const
{
auto p = find(name, TypeUnknown, casesensitive);
if (p != cend()) {
if (index >= int(p->type().basevalues()))
return false;
TypeDesc basetype = p->type().scalartype();
ustring s;
bool ok = convert_type(basetype,
(const char*)p->data() + index * basetype.size(),
TypeString, &s);
if (ok)
value = s.string();
return ok;
} else {
return false;
}
}



void
ParamValueList::sort(bool casesensitive)
{
Expand Down
3 changes: 3 additions & 0 deletions src/libutil/paramlist_test.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -328,6 +328,9 @@ test_delegates()
OIIO_CHECK_EQUAL(pl["bar4"].get<std::string>(), "barbarbar?");
OIIO_CHECK_EQUAL(pl["red"].get<Imath::Color3f>(),
Imath::Color3f(1.0f, 0.0f, 0.0f));
OIIO_CHECK_EQUAL(pl["red"].get_indexed<float>(0), 1.0f);
OIIO_CHECK_EQUAL(pl["red"].get_indexed<float>(1), 0.0f);
OIIO_CHECK_EQUAL(pl["red"].get_indexed<float>(2), 0.0f);
OIIO_CHECK_EQUAL(pl["xy"].get<Imath::V3f>(), Imath::V3f(0.5f, 0.5f, 0.0f));
OIIO_CHECK_EQUAL(pl["Tx"].get<Imath::M44f>(),
Imath::M44f(1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 42, 0, 0,
Expand Down

0 comments on commit a653c53

Please sign in to comment.