diff --git a/lib/hydramoonray/ValueConverter.cc b/lib/hydramoonray/ValueConverter.cc index 135069f..03357e9 100644 --- a/lib/hydramoonray/ValueConverter.cc +++ b/lib/hydramoonray/ValueConverter.cc @@ -5,6 +5,9 @@ #include +#include +#include + #include namespace hdMoonray { @@ -17,6 +20,39 @@ static void _clearBinding(SceneObject* sceneObj, const Attribute* attribute) sceneObj->setBinding(*attribute,nullptr); } +static bool _extractIntegral64(const pxr::VtValue& val, std::int64_t* out) +{ + if (val.IsHolding()) { + *out = static_cast(val.UncheckedGet()); + return true; + } + if (val.IsHolding()) { + *out = static_cast(val.UncheckedGet()); + return true; + } + if (val.IsHolding()) { + *out = static_cast(val.UncheckedGet()); + return true; + } + return false; +} + +static bool _narrowIntChecked(SceneObject* sceneObj, + const Attribute* attribute, + std::int64_t value, + Int* out) +{ + constexpr std::int64_t kMin = static_cast(std::numeric_limits::min()); + constexpr std::int64_t kMax = static_cast(std::numeric_limits::max()); + if (value < kMin || value > kMax) { + Logger::error(sceneObj->getName(), '.', attribute->getName(), + ": integer value ", value, " out of Int range [", kMin, ", ", kMax, "]"); + return false; + } + *out = static_cast(value); + return true; +} + template static void _set(SceneObject* sceneObj, const Attribute* attribute, const T& value) { sceneObj->set(AttributeKey(*attribute), value); @@ -144,10 +180,15 @@ ValueConverter::setAttribute(SceneObject* sceneObj, const Attribute* attribute, key = &(val.UncheckedGet().GetString()); } else if (val.IsHolding()) { key = &(val.UncheckedGet()); - } else if (val.IsHolding() || val.IsHolding()) { - const int intVal = val.IsHolding() ? - static_cast(val.UncheckedGet()) : - val.UncheckedGet(); + } else { + std::int64_t int64Val = 0; + if (!_extractIntegral64(val, &int64Val)) { + break; // go print normal error message + } + Int intVal = 0; + if (!_narrowIntChecked(sceneObj, attribute, int64Val, &intVal)) { + return; + } int index = 0; for (auto it = attribute->beginEnumValues(); it != attribute->endEnumValues(); ++it) { if (index == intVal) { @@ -157,8 +198,6 @@ ValueConverter::setAttribute(SceneObject* sceneObj, const Attribute* attribute, ++index; } break; - } else { - break; // go print normal error message } for (auto it = attribute->beginEnumValues(); it != attribute->endEnumValues(); ++it) { if (it->second == *key) { @@ -170,10 +209,16 @@ ValueConverter::setAttribute(SceneObject* sceneObj, const Attribute* attribute, Logger::error(sceneObj->getName(), '.', attribute->getName(), ": Invalid enum key '", *key, "'"); return; - } else if (val.IsHolding()) { - sceneObj->set(AttributeKey(*attribute), static_cast(val.UncheckedGet())); - return; } else { + std::int64_t int64Val = 0; + if (_extractIntegral64(val, &int64Val)) { + Int intVal = 0; + if (!_narrowIntChecked(sceneObj, attribute, int64Val, &intVal)) { + return; + } + sceneObj->set(AttributeKey(*attribute), intVal); + return; + } if (_setAttributeRef(sceneObj, attribute, val)) return; } break;