Skip to content

Commit

Permalink
api: extend TypeDesc and ParamType to represent ustringhash (#3915)
Browse files Browse the repository at this point in the history
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 <lg@larrygritz.com>
  • Loading branch information
lgritz authored Jul 30, 2023
1 parent 353e022 commit 6e60347
Show file tree
Hide file tree
Showing 6 changed files with 71 additions and 92 deletions.
5 changes: 5 additions & 0 deletions src/include/OpenImageIO/paramlist.h
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand Down
7 changes: 7 additions & 0 deletions src/include/OpenImageIO/typedesc.h
Original file line number Diff line number Diff line change
Expand Up @@ -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
};

Expand Down Expand Up @@ -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);



Expand Down Expand Up @@ -485,6 +487,10 @@ template<> struct TypeDescFromC<Imath::Box3i> { static const constexpr TypeDesc
#endif


class ustringhash; // forward declaration



/// A template mechanism for getting C type of TypeDesc::BASETYPE.
///
template<int b> struct CType {};
Expand All @@ -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; };



Expand Down
81 changes: 9 additions & 72 deletions src/libutil/paramlist.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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);
}
}

Expand All @@ -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<int>(index);
if (base == TypeDesc::UINT)
return (int)get<unsigned int>(index);
if (base == TypeDesc::INT16)
return get<short>(index);
if (base == TypeDesc::UINT16)
return get<unsigned short>(index);
if (base == TypeDesc::INT8)
return get<char>(index);
if (base == TypeDesc::UINT8)
return get<unsigned char>(index);
if (base == TypeDesc::INT64)
return get<long long>(index);
if (base == TypeDesc::UINT64)
return get<unsigned long long>(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<ustring>(index);
int val = defaultval;
if (Strutil::parse_int(str, val) && str.empty())
return val;
}
return defaultval; // Some nonstandard type, fail
#endif
}


Expand All @@ -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<float>(index);
if (base == TypeDesc::HALF)
return get<half>(index);
if (base == TypeDesc::DOUBLE)
return get<double>(index);
if (base == TypeDesc::INT) {
if (type().aggregate == TypeDesc::VEC2
&& type().vecsemantics == TypeDesc::RATIONAL) {
int num = get<int>(2 * index + 0);
int den = get<int>(2 * index + 1);
return den ? float(num) / float(den) : 0.0f;
}
return get<int>(index);
}
if (base == TypeDesc::UINT)
return get<unsigned int>(index);
if (base == TypeDesc::INT16)
return get<short>(index);
if (base == TypeDesc::UINT16)
return get<unsigned short>(index);
if (base == TypeDesc::INT8)
return get<char>(index);
if (base == TypeDesc::UINT8)
return get<unsigned char>(index);
if (base == TypeDesc::INT64)
return get<long long>(index);
if (base == TypeDesc::UINT64)
return get<unsigned long long>(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<ustring>(index);
float val = defaultval;
if (Strutil::parse_float(str, val) && str.empty())
return val;
}
return defaultval;
#endif
}


Expand Down Expand Up @@ -400,6 +331,8 @@ ParamValue::get_string_indexed(int index) const
} else if (element.basetype == TypeDesc::PTR) {
out += "ptr ";
formatType<void*>(*this, index, index + 1, "{:p}", out);
} else if (element.basetype == TypeDesc::USTRINGHASH) {
return get<ustringhash>(index).string();
} else {
out += Strutil::fmt::format(
"<unknown data type> (base {:d}, agg {:d} vec {:d})",
Expand All @@ -417,6 +350,8 @@ ParamValue::get_ustring(int maxsize) const
// super inexpensive.
if (type() == TypeDesc::STRING)
return get<ustring>();
if (type() == TypeDesc::USTRINGHASH)
return ustring(get<ustringhash>());
return ustring(get_string(maxsize));
}

Expand All @@ -429,6 +364,8 @@ ParamValue::get_ustring_indexed(int index) const
// super inexpensive.
if (type() == TypeDesc::STRING)
return get<ustring>(index);
if (type() == TypeDesc::USTRINGHASH)
return ustring(get<ustringhash>());
return ustring(get_string_indexed(index));
}

Expand Down
9 changes: 9 additions & 0 deletions src/libutil/paramlist_test.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -104,9 +104,18 @@ test_value_types()
const char* val = "hello";
ParamValue p("name", val);
OIIO_CHECK_EQUAL(p.get<ustring>(), "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<ustringhash>(), val);
}

{
const void* ptr = reinterpret_cast<const void*>(size_t(0xdeadbeef));
ParamValue p("name", TypeDesc::PTR, 1, &ptr);
Expand Down
58 changes: 38 additions & 20 deletions src/libutil/typedesc.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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
};

}
Expand Down Expand Up @@ -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];
Expand All @@ -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];
Expand All @@ -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[] = {
Expand All @@ -150,7 +154,8 @@ static const char* basetype_code[] = {
"f", // FLOAT
"d", // DOUBLE
"str", // STRING
"ptr" // PTR
"ptr", // PTR
"uh", // USTRINGHASH
};

} // namespace
Expand Down Expand Up @@ -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
}
Expand Down Expand Up @@ -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("<unknown data type> (base %d, agg %d vec %d)",
Expand Down Expand Up @@ -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;
}

Expand Down
3 changes: 3 additions & 0 deletions src/libutil/typedesc_test.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@

#include <OpenImageIO/typedesc.h>
#include <OpenImageIO/unittest.h>
#include <OpenImageIO/ustring.h>


using namespace OIIO;
Expand Down Expand Up @@ -144,6 +145,8 @@ main(int /*argc*/, char* /*argv*/[])
TypeFloat4, {});
test_type<const char*>("string", TypeDesc(TypeDesc::STRING), TypeString,
"hello", "hello");
test_type<ustringhash>("ustringhash", TypeDesc(TypeDesc::USTRINGHASH),
TypeUstringhash, ustringhash("hello"), "hello");
int i2[2] = { 1, 2 };
test_type<int[2]>("rational",
TypeDesc(TypeDesc::INT, TypeDesc::VEC2,
Expand Down

0 comments on commit 6e60347

Please sign in to comment.