Skip to content

Commit c5da8db

Browse files
committed
Add get_indexed() to ParamValueList and AttrDelegate.
This lets you pull out a single base value from an aggregate and/or array attribute.
1 parent cc53a0e commit c5da8db

File tree

5 files changed

+86
-4
lines changed

5 files changed

+86
-4
lines changed

src/include/OpenImageIO/attrdelegate.h

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -149,6 +149,33 @@ template<class C> class AttrDelegate {
149149
return m_obj->getattribute(m_name, TypeString, &s) ? T(s) : defaultval;
150150
}
151151

152+
// `Delegate->get_indexed<T>(int index, defaultval=T())` retrieves the
153+
// index-th base value in the data as type T, or the defaultval if no
154+
// such named data exists or is not the designated type.
155+
template<typename T,
156+
typename std::enable_if<!pvt::is_string<T>::value, int>::type = 0>
157+
inline T get_indexed(int index, const T& defaultval = T()) const
158+
{
159+
T result;
160+
if (!m_obj->getattribute_indexed(m_name, index,
161+
TypeDescFromC<T>::value(), &result))
162+
result = defaultval;
163+
return result;
164+
}
165+
166+
// Using enable_if, make a slightly different version of get_indexed<>
167+
// for strings, which need to do some ustring magic because we can't
168+
// directly store in a std::string or string_view.
169+
template<typename T = string_view,
170+
typename std::enable_if<pvt::is_string<T>::value, int>::type = 1>
171+
inline T get_indexed(int index, const T& defaultval = T()) const
172+
{
173+
ustring s;
174+
return m_obj->getattribute_indexed(m_name, index, TypeString, &s)
175+
? T(s)
176+
: defaultval;
177+
}
178+
152179
// `Delegate->as_string(defaultval="")` returns the data, no matter its
153180
// type, as a string. Returns the defaultval if no such data exists at
154181
// all.

src/include/OpenImageIO/paramlist.h

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -352,6 +352,15 @@ class OIIO_API ParamValueList : public std::vector<ParamValue> {
352352
bool getattribute(string_view name, std::string& value,
353353
bool casesensitive = false) const;
354354

355+
/// Retrieve from list: If found its data type is reasonably convertible
356+
/// to `type`, copy/convert the value into val[...] and return true.
357+
/// Otherwise, return false and don't modify what val points to.
358+
bool getattribute_indexed(string_view name, int index, TypeDesc type,
359+
void* value, bool casesensitive = false) const;
360+
/// Shortcut for retrieving a single string via getattribute.
361+
bool getattribute_indexed(string_view name, int index, std::string& value,
362+
bool casesensitive = false) const;
363+
355364
/// Sort alphabetically, optionally case-insensitively, locale-
356365
/// independently, and with all the "un-namespaced" items appearing
357366
/// first, followed by items with "prefixed namespaces" (e.g. "z" comes

src/include/OpenImageIO/typedesc.h

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -222,9 +222,9 @@ struct OIIO_API TypeDesc {
222222
/// ignoring whether it's an array).
223223
size_t elementsize () const noexcept { return aggregate * basesize(); }
224224

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

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

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

246246
/// Set *this to the type described in the string. Return the

src/libutil/paramlist.cpp

Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -597,6 +597,49 @@ ParamValueList::getattribute(string_view name, std::string& value,
597597

598598

599599

600+
bool
601+
ParamValueList::getattribute_indexed(string_view name, int index, TypeDesc type,
602+
void* value, bool casesensitive) const
603+
{
604+
auto p = find(name, TypeUnknown, casesensitive);
605+
if (p != cend()) {
606+
if (index >= int(p->type().basevalues()))
607+
return false;
608+
TypeDesc basetype = p->type().scalartype();
609+
return convert_type(basetype,
610+
(const char*)p->data() + index * basetype.size(),
611+
type, value);
612+
} else {
613+
return false;
614+
}
615+
}
616+
617+
618+
619+
bool
620+
ParamValueList::getattribute_indexed(string_view name, int index,
621+
std::string& value,
622+
bool casesensitive) const
623+
{
624+
auto p = find(name, TypeUnknown, casesensitive);
625+
if (p != cend()) {
626+
if (index >= int(p->type().basevalues()))
627+
return false;
628+
TypeDesc basetype = p->type().scalartype();
629+
ustring s;
630+
bool ok = convert_type(basetype,
631+
(const char*)p->data() + index * basetype.size(),
632+
TypeString, &s);
633+
if (ok)
634+
value = s.string();
635+
return ok;
636+
} else {
637+
return false;
638+
}
639+
}
640+
641+
642+
600643
void
601644
ParamValueList::sort(bool casesensitive)
602645
{

src/libutil/paramlist_test.cpp

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -347,6 +347,9 @@ test_delegates()
347347
OIIO_CHECK_EQUAL(pl["bar4"].get<std::string>(), "barbarbar?");
348348
OIIO_CHECK_EQUAL(pl["red"].get<Imath::Color3f>(),
349349
Imath::Color3f(1.0f, 0.0f, 0.0f));
350+
OIIO_CHECK_EQUAL(pl["red"].get_indexed<float>(0), 1.0f);
351+
OIIO_CHECK_EQUAL(pl["red"].get_indexed<float>(1), 0.0f);
352+
OIIO_CHECK_EQUAL(pl["red"].get_indexed<float>(2), 0.0f);
350353
OIIO_CHECK_EQUAL(pl["xy"].get<Imath::V3f>(), Imath::V3f(0.5f, 0.5f, 0.0f));
351354
OIIO_CHECK_EQUAL(pl["Tx"].get<Imath::M44f>(),
352355
Imath::M44f(1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 42, 0, 0,

0 commit comments

Comments
 (0)