From 6e603475a875c0cd66856e37d5f4f9cd73a140fc Mon Sep 17 00:00:00 2001 From: Larry Gritz Date: Sun, 30 Jul 2023 16:47:01 -0700 Subject: [PATCH] api: extend TypeDesc and ParamType to represent ustringhash (#3915) I think it will be handy to be able to have ParamValue contain ustringhashes and have a TypeDesc that can describe it explicitly. Signed-off-by: Larry Gritz --- src/include/OpenImageIO/paramlist.h | 5 ++ src/include/OpenImageIO/typedesc.h | 7 +++ src/libutil/paramlist.cpp | 81 ++++------------------------- src/libutil/paramlist_test.cpp | 9 ++++ src/libutil/typedesc.cpp | 58 ++++++++++++++------- src/libutil/typedesc_test.cpp | 3 ++ 6 files changed, 71 insertions(+), 92 deletions(-) diff --git a/src/include/OpenImageIO/paramlist.h b/src/include/OpenImageIO/paramlist.h index 66b9576605..95daf9ac7f 100644 --- a/src/include/OpenImageIO/paramlist.h +++ b/src/include/OpenImageIO/paramlist.h @@ -110,6 +110,11 @@ class OIIO_UTIL_API ParamValue { : ParamValue(_name, ustring(value)) { } + ParamValue(string_view _name, ustringhash value) noexcept + { + init_noclear(ustring(_name), TypeDesc::USTRINGHASH, 1, &value, + Copy(true)); + } // Set from string -- parse ParamValue(string_view _name, TypeDesc type, string_view value); diff --git a/src/include/OpenImageIO/typedesc.h b/src/include/OpenImageIO/typedesc.h index 8569f1263f..6dcbb890f6 100644 --- a/src/include/OpenImageIO/typedesc.h +++ b/src/include/OpenImageIO/typedesc.h @@ -83,6 +83,7 @@ struct OIIO_UTIL_API TypeDesc { DOUBLE, ///< 64-bit IEEE floating point values, (C/C++ `double`). STRING, ///< Character string. PTR, ///< A pointer value. + USTRINGHASH, ///< The hash of a ustring LASTBASE }; @@ -404,6 +405,7 @@ OIIO_INLINE_CONSTEXPR TypeDesc TypeTimeCode (TypeDesc::UINT, TypeDesc::SCALAR, T OIIO_INLINE_CONSTEXPR TypeDesc TypeKeyCode (TypeDesc::INT, TypeDesc::SCALAR, TypeDesc::KEYCODE, 7); OIIO_INLINE_CONSTEXPR TypeDesc TypeRational(TypeDesc::INT, TypeDesc::VEC2, TypeDesc::RATIONAL); OIIO_INLINE_CONSTEXPR TypeDesc TypePointer(TypeDesc::PTR); +OIIO_INLINE_CONSTEXPR TypeDesc TypeUstringhash(TypeDesc::USTRINGHASH); @@ -485,6 +487,10 @@ template<> struct TypeDescFromC { static const constexpr TypeDesc #endif +class ustringhash; // forward declaration + + + /// A template mechanism for getting C type of TypeDesc::BASETYPE. /// template struct CType {}; @@ -501,6 +507,7 @@ template<> struct CType<(int)TypeDesc::HALF> { typedef half type; }; #endif template<> struct CType<(int)TypeDesc::FLOAT> { typedef float type; }; template<> struct CType<(int)TypeDesc::DOUBLE> { typedef double type; }; +template<> struct CType<(int)TypeDesc::USTRINGHASH> { typedef ustringhash type; }; diff --git a/src/libutil/paramlist.cpp b/src/libutil/paramlist.cpp index a3128f266d..e7fb21c3c9 100644 --- a/src/libutil/paramlist.cpp +++ b/src/libutil/paramlist.cpp @@ -171,6 +171,9 @@ ParamValue::ParamValue(string_view name, TypeDesc type, string_view value) } else if (type == TypeDesc::STRING) { ustring s(value); init(name, type, 1, &s); + } else if (type == TypeDesc::USTRINGHASH) { + ustringhash s(value); + init(name, type, 1, &s); } } @@ -187,40 +190,11 @@ ParamValue::get_int(int defaultval) const int ParamValue::get_int_indexed(int index, int defaultval) const { -#if 1 && OIIO_VERSION >= 20101 int val = defaultval; convert_type(type().elementtype(), (const char*)data() + index * type().basesize(), TypeInt, &val); return val; -#else - int base = type().basetype; - if (base == TypeDesc::INT) - return get(index); - if (base == TypeDesc::UINT) - return (int)get(index); - if (base == TypeDesc::INT16) - return get(index); - if (base == TypeDesc::UINT16) - return get(index); - if (base == TypeDesc::INT8) - return get(index); - if (base == TypeDesc::UINT8) - return get(index); - if (base == TypeDesc::INT64) - return get(index); - if (base == TypeDesc::UINT64) - return get(index); - if (base == TypeDesc::STRING) { - // Only succeed for a string if it exactly holds something that - // exactly parses to an int value. - string_view str = get(index); - int val = defaultval; - if (Strutil::parse_int(str, val) && str.empty()) - return val; - } - return defaultval; // Some nonstandard type, fail -#endif } @@ -236,54 +210,11 @@ ParamValue::get_float(float defaultval) const float ParamValue::get_float_indexed(int index, float defaultval) const { -#if 1 && OIIO_VERSION >= 20101 float val = defaultval; convert_type(type().elementtype(), (const char*)data() + index * type().basesize(), TypeFloat, &val); return val; -#else - int base = type().basetype; - if (base == TypeDesc::FLOAT) - return get(index); - if (base == TypeDesc::HALF) - return get(index); - if (base == TypeDesc::DOUBLE) - return get(index); - if (base == TypeDesc::INT) { - if (type().aggregate == TypeDesc::VEC2 - && type().vecsemantics == TypeDesc::RATIONAL) { - int num = get(2 * index + 0); - int den = get(2 * index + 1); - return den ? float(num) / float(den) : 0.0f; - } - return get(index); - } - if (base == TypeDesc::UINT) - return get(index); - if (base == TypeDesc::INT16) - return get(index); - if (base == TypeDesc::UINT16) - return get(index); - if (base == TypeDesc::INT8) - return get(index); - if (base == TypeDesc::UINT8) - return get(index); - if (base == TypeDesc::INT64) - return get(index); - if (base == TypeDesc::UINT64) - return get(index); - if (base == TypeDesc::STRING) { - // Only succeed for a string if it exactly holds something - // that exactly parses to a float value. - string_view str = get(index); - float val = defaultval; - if (Strutil::parse_float(str, val) && str.empty()) - return val; - } - - return defaultval; -#endif } @@ -400,6 +331,8 @@ ParamValue::get_string_indexed(int index) const } else if (element.basetype == TypeDesc::PTR) { out += "ptr "; formatType(*this, index, index + 1, "{:p}", out); + } else if (element.basetype == TypeDesc::USTRINGHASH) { + return get(index).string(); } else { out += Strutil::fmt::format( " (base {:d}, agg {:d} vec {:d})", @@ -417,6 +350,8 @@ ParamValue::get_ustring(int maxsize) const // super inexpensive. if (type() == TypeDesc::STRING) return get(); + if (type() == TypeDesc::USTRINGHASH) + return ustring(get()); return ustring(get_string(maxsize)); } @@ -429,6 +364,8 @@ ParamValue::get_ustring_indexed(int index) const // super inexpensive. if (type() == TypeDesc::STRING) return get(index); + if (type() == TypeDesc::USTRINGHASH) + return ustring(get()); return ustring(get_string_indexed(index)); } diff --git a/src/libutil/paramlist_test.cpp b/src/libutil/paramlist_test.cpp index 49d4e5fbfe..b98e5c72e2 100644 --- a/src/libutil/paramlist_test.cpp +++ b/src/libutil/paramlist_test.cpp @@ -104,9 +104,18 @@ test_value_types() const char* val = "hello"; ParamValue p("name", val); OIIO_CHECK_EQUAL(p.get(), "hello"); + OIIO_CHECK_EQUAL(p.get_ustring(), "hello"); OIIO_CHECK_EQUAL(p.get_string(), "hello"); } + { + ustringhash val("hello"); + ParamValue p("name", val); + OIIO_CHECK_EQUAL(p.get_string(), "hello"); + OIIO_CHECK_EQUAL(p.get_ustring(), "hello"); + OIIO_CHECK_EQUAL(p.get(), val); + } + { const void* ptr = reinterpret_cast(size_t(0xdeadbeef)); ParamValue p("name", TypeDesc::PTR, 1, &ptr); diff --git a/src/libutil/typedesc.cpp b/src/libutil/typedesc.cpp index e507fa5a89..66937a5101 100644 --- a/src/libutil/typedesc.cpp +++ b/src/libutil/typedesc.cpp @@ -47,7 +47,8 @@ static int basetype_size[TypeDesc::LASTBASE] = { sizeof(float), // FLOAT sizeof(double), // DOUBLE sizeof(char*), // STRING - sizeof(void*) // PTR + sizeof(void*), // PTR + sizeof(ustringhash), // USTRINGHASH }; } @@ -81,7 +82,8 @@ TypeDesc::is_floating_point() const noexcept 1, // FLOAT 1, // DOUBLE 0, // STRING - 0 // PTR + 0, // PTR + 0, // USTRINGHASH }; OIIO_DASSERT(basetype < TypeDesc::LASTBASE); return isfloat[basetype]; @@ -107,7 +109,8 @@ TypeDesc::is_signed() const noexcept 1, // FLOAT 1, // DOUBLE 0, // STRING - 0 // PTR + 0, // PTR + 0, // USTRINGHASH }; OIIO_DASSERT(basetype < TypeDesc::LASTBASE); return issigned[basetype]; @@ -118,21 +121,22 @@ TypeDesc::is_signed() const noexcept namespace { static const char* basetype_name[] = { - "unknown", // UNKNOWN - "void", // VOID/NONE - "uint8", // UCHAR - "int8", // CHAR - "uint16", // USHORT - "int16", // SHORT - "uint", // UINT - "int", // INT - "uint64", // ULONGLONG - "int64", // LONGLONG - "half", // HALF - "float", // FLOAT - "double", // DOUBLE - "string", // STRING - "pointer" // PTR + "unknown", // UNKNOWN + "void", // VOID/NONE + "uint8", // UCHAR + "int8", // CHAR + "uint16", // USHORT + "int16", // SHORT + "uint", // UINT + "int", // INT + "uint64", // ULONGLONG + "int64", // LONGLONG + "half", // HALF + "float", // FLOAT + "double", // DOUBLE + "string", // STRING + "pointer", // PTR + "ustringhash", // USTRINGHASH }; static const char* basetype_code[] = { @@ -150,7 +154,8 @@ static const char* basetype_code[] = { "f", // FLOAT "d", // DOUBLE "str", // STRING - "ptr" // PTR + "ptr", // PTR + "uh", // USTRINGHASH }; } // namespace @@ -318,6 +323,8 @@ TypeDesc::fromstring(string_view typestring) t = TypeKeyCode; else if (type == "pointer") t = TypePointer; + else if (type == "ustringhash") + t = TypeUstringhash; else { return 0; // unknown } @@ -625,6 +632,14 @@ tostring(TypeDesc type, const void* data, const tostring_formatting& fmt) return fmt.use_sprintf ? sprint_type(type, fmt.ptr_fmt, fmt, (void**)data) : format_type(type, fmt.ptr_fmt, fmt, (void**)data); + case TypeDesc::USTRINGHASH: { + const char* v = ((const ustringhash*)data)->c_str(); + if (!type.is_array() + && !(fmt.flags & tostring_formatting::quote_single_string)) + return v ? v : ""; + return fmt.use_sprintf ? sprint_type(type, fmt.string_fmt, fmt, &v) + : format_type(type, fmt.string_fmt, fmt, &v); + } default: #ifndef NDEBUG return Strutil::sprintf(" (base %d, agg %d vec %d)", @@ -780,7 +795,10 @@ convert_type(TypeDesc srctype, const void* src, TypeDesc dsttype, void* dst, } if (dsttype == TypeString) { - (*(ustring*)dst) = ustring(tostring(srctype, src)); + if (srctype == TypeUstringhash) + (*(ustring*)dst) = ustring::from_hash(*(const ustring::hash_t*)src); + else + (*(ustring*)dst) = ustring(tostring(srctype, src)); return true; } diff --git a/src/libutil/typedesc_test.cpp b/src/libutil/typedesc_test.cpp index e53a5c7f3b..bed535fed0 100644 --- a/src/libutil/typedesc_test.cpp +++ b/src/libutil/typedesc_test.cpp @@ -18,6 +18,7 @@ #include #include +#include using namespace OIIO; @@ -144,6 +145,8 @@ main(int /*argc*/, char* /*argv*/[]) TypeFloat4, {}); test_type("string", TypeDesc(TypeDesc::STRING), TypeString, "hello", "hello"); + test_type("ustringhash", TypeDesc(TypeDesc::USTRINGHASH), + TypeUstringhash, ustringhash("hello"), "hello"); int i2[2] = { 1, 2 }; test_type("rational", TypeDesc(TypeDesc::INT, TypeDesc::VEC2,