From 7f2e8e6921620f3b938aa5761e34db0c21442b8e Mon Sep 17 00:00:00 2001 From: Larry Gritz Date: Wed, 25 Dec 2024 14:53:20 -0800 Subject: [PATCH] paramlist.h: ParamValue as_span, as_cspan Convenience methods that give a bounded span of the data that a PV holds. Signed-off-by: Larry Gritz --- src/include/OpenImageIO/paramlist.h | 20 ++++++++++++++++++++ src/include/OpenImageIO/typedesc.h | 14 ++++++++++---- src/libutil/paramlist.cpp | 17 ++++++----------- 3 files changed, 36 insertions(+), 15 deletions(-) diff --git a/src/include/OpenImageIO/paramlist.h b/src/include/OpenImageIO/paramlist.h index 6d278a38df..dd5e15b34b 100644 --- a/src/include/OpenImageIO/paramlist.h +++ b/src/include/OpenImageIO/paramlist.h @@ -215,6 +215,26 @@ class OIIO_UTIL_API ParamValue { b = std::move(tmp); } + /// Return a `cspan` pointing to the bounded data. If the type `T` is + /// not the actual underlying base type, return an empty span. + template cspan as_cspan() const noexcept + { + return BaseTypeFromC::value == m_type.basetype + ? make_cspan(reinterpret_cast(data()), + size_t(m_nvalues * m_type.basevalues())) + : cspan(); + } + + /// Return a `span` pointing to the bounded data. If the type `T` is + /// not the actual underlying base type, return an empty span. + template span as_span() noexcept + { + return BaseTypeFromC::value == m_type.basetype + ? make_span(reinterpret_cast(const_cast(data())), + size_t(m_nvalues * m_type.basevalues())) + : span(); + } + // Use with extreme caution! This is just doing a cast. You'd better // be really sure you are asking for the right type. Note that for // "string" data, you can get or get, but it's not diff --git a/src/include/OpenImageIO/typedesc.h b/src/include/OpenImageIO/typedesc.h index a4bc6465f8..9263a209eb 100644 --- a/src/include/OpenImageIO/typedesc.h +++ b/src/include/OpenImageIO/typedesc.h @@ -395,12 +395,18 @@ OIIO_INLINE_CONSTEXPR TypeDesc TypeUstringhash(TypeDesc::USTRINGHASH); template struct BaseTypeFromC {}; template<> struct BaseTypeFromC { static const TypeDesc::BASETYPE value = TypeDesc::UINT8; }; template<> struct BaseTypeFromC { static const TypeDesc::BASETYPE value = TypeDesc::INT8; }; -template<> struct BaseTypeFromC { static const TypeDesc::BASETYPE value = TypeDesc::UINT16; }; -template<> struct BaseTypeFromC { static const TypeDesc::BASETYPE value = TypeDesc::INT16; }; -template<> struct BaseTypeFromC { static const TypeDesc::BASETYPE value = TypeDesc::UINT; }; -template<> struct BaseTypeFromC { static const TypeDesc::BASETYPE value = TypeDesc::INT; }; +template<> struct BaseTypeFromC { static const TypeDesc::BASETYPE value = TypeDesc::UINT16; }; +template<> struct BaseTypeFromC { static const TypeDesc::BASETYPE value = TypeDesc::INT16; }; +template<> struct BaseTypeFromC { static const TypeDesc::BASETYPE value = TypeDesc::UINT; }; +template<> struct BaseTypeFromC { static const TypeDesc::BASETYPE value = TypeDesc::INT; }; +template<> struct BaseTypeFromC { static const TypeDesc::BASETYPE value = TypeDesc::UINT64; }; +template<> struct BaseTypeFromC { static const TypeDesc::BASETYPE value = TypeDesc::INT64; }; +#if defined(__GNUC__) && !defined(__apple_build_version__) && __WORDSIZE == 64 +// gcc on some platforms consider int64_t and long long to be different +// types, even though they are actually the same size. template<> struct BaseTypeFromC { static const TypeDesc::BASETYPE value = TypeDesc::UINT64; }; template<> struct BaseTypeFromC { static const TypeDesc::BASETYPE value = TypeDesc::INT64; }; +#endif #if defined(_HALF_H_) || defined(IMATH_HALF_H_) template<> struct BaseTypeFromC { static const TypeDesc::BASETYPE value = TypeDesc::HALF; }; #endif diff --git a/src/libutil/paramlist.cpp b/src/libutil/paramlist.cpp index 8439a56ba2..93e0b774df 100644 --- a/src/libutil/paramlist.cpp +++ b/src/libutil/paramlist.cpp @@ -35,7 +35,6 @@ ParamValue::init_noclear(ustring _name, TypeDesc _type, int _nvalues, m_type = _type; m_nvalues = _nvalues; m_interp = _interp; - size_t n = (size_t)(m_nvalues * m_type.numelements()); size_t size = (size_t)(m_nvalues * m_type.size()); bool small = (size <= sizeof(m_data)); @@ -58,9 +57,9 @@ ParamValue::init_noclear(ustring _name, TypeDesc _type, int _nvalues, m_nonlocal = true; } if (m_type.basetype == TypeDesc::STRING && !_from_ustring) { - if (ustring* u = (ustring*)data()) - for (size_t i = 0; i < n; ++i) - u[i] = ustring(u[i].c_str()); + // Convert non-ustrings to ustrings + for (ustring& u : as_span()) + u = ustring(u.c_str()); } } else { // Big enough to warrant a malloc, but the caller said don't @@ -126,17 +125,13 @@ template static void parse_elements(string_view value, ParamValue& p) { - using namespace Strutil; - TypeDesc type = p.type(); - int num_items = type.numelements() * type.aggregate; - T* data = (T*)p.data(); - // Erase any leading whitespace + auto data = p.as_span(); value.remove_prefix(value.find_first_not_of(" \t")); - for (int i = 0; i < num_items; ++i) { + for (auto&& d : data) { // Make a temporary copy so we for sure have a 0-terminated string. std::string temp = value; // Grab the first value from it - data[i] = from_string(temp); + d = Strutil::from_string(temp); // Skip the value (eat until we find a delimiter -- space, comma, tab) value.remove_prefix(value.find_first_of(" ,\t")); // Skip the delimiter