diff options
| author | Jason M. Bills <jason.m.bills@linux.intel.com> | 2018-11-06 15:44:38 -0800 |
|---|---|---|
| committer | Ed Tanous <ed.tanous@intel.com> | 2018-11-16 22:37:11 +0000 |
| commit | 771cfa0fb06de042f9f304abb27d5be80bc163df (patch) | |
| tree | 35ce49463af04ef289d639ac8ea551395bb877ed /redfish-core/include/utils | |
| parent | c4bf6374242b5a9b98fa92a7ecfbc586724a9ca2 (diff) | |
| download | bmcweb-771cfa0fb06de042f9f304abb27d5be80bc163df.tar.gz bmcweb-771cfa0fb06de042f9f304abb27d5be80bc163df.zip | |
Add automatic range-checking and type-casting for readJson
This change allows numerical types to be passed to readJson
with the desired type. They will then be automatically
range-checked and cast to that type.
Tested: Requested variables of type uint64_t, uint8_t, int,
int16_t, and int8_t and confirmed that the range was correctly
checked for each.
Change-Id: Ia55cb03ba2c4321a7de35a7c7b566980a72c5449
Signed-off-by: Jason M. Bills <jason.m.bills@linux.intel.com>
Diffstat (limited to 'redfish-core/include/utils')
| -rw-r--r-- | redfish-core/include/utils/json_utils.hpp | 83 |
1 files changed, 64 insertions, 19 deletions
diff --git a/redfish-core/include/utils/json_utils.hpp b/redfish-core/include/utils/json_utils.hpp index e56a0d6..778a905 100644 --- a/redfish-core/include/utils/json_utils.hpp +++ b/redfish-core/include/utils/json_utils.hpp @@ -42,19 +42,74 @@ bool processJsonFromRequest(crow::Response& res, const crow::Request& req, nlohmann::json& reqJson); namespace details { -template <typename Type> struct unpackValue + +template <typename Type> struct is_optional : std::false_type { - using isRequired = std::true_type; - using JsonType = std::add_const_t<std::add_pointer_t<Type>>; }; -template <typename OptionalType> -struct unpackValue<boost::optional<OptionalType>> +template <typename Type> +struct is_optional<boost::optional<Type>> : std::true_type { - using isRequired = std::false_type; - using JsonType = std::add_const_t<std::add_pointer_t<OptionalType>>; }; +template <typename Type> +constexpr bool is_optional_v = is_optional<Type>::value; + +template <typename Type> +void unpackValue(nlohmann::json& jsonValue, const std::string& key, + crow::Response& res, Type& value) +{ + if constexpr (std::is_arithmetic_v<Type>) + { + using NumType = + std::conditional_t<std::is_signed_v<Type>, int64_t, uint64_t>; + + NumType* jsonPtr = jsonValue.get_ptr<NumType*>(); + if (jsonPtr == nullptr) + { + BMCWEB_LOG_DEBUG + << "Value for key " << key + << " was incorrect type: " << jsonValue.type_name(); + messages::propertyValueTypeError(res, jsonValue.dump(), key); + return; + } + if (*jsonPtr > std::numeric_limits<Type>::max()) + { + BMCWEB_LOG_DEBUG << "Value for key " << key + << " was out of range: " << jsonValue.type_name(); + messages::propertyValueNotInList(res, jsonValue.dump(), key); + return; + } + if (*jsonPtr < std::numeric_limits<Type>::min()) + { + BMCWEB_LOG_DEBUG << "Value for key " << key + << " was out of range: " << jsonValue.type_name(); + messages::propertyValueNotInList(res, jsonValue.dump(), key); + return; + } + value = static_cast<Type>(*jsonPtr); + } + else if constexpr (is_optional_v<Type>) + { + value.emplace(); + unpackValue<typename Type::value_type>(jsonValue, key, res, *value); + } + else + { + using JsonType = std::add_const_t<std::add_pointer_t<Type>>; + JsonType jsonPtr = jsonValue.get_ptr<JsonType>(); + if (jsonPtr == nullptr) + { + BMCWEB_LOG_DEBUG + << "Value for key " << key + << " was incorrect type: " << jsonValue.type_name(); + messages::propertyValueTypeError(res, jsonValue.dump(), key); + return; + } + value = std::move(*jsonPtr); + } +} + template <size_t Count, size_t Index> void readJsonValues(const std::string& key, nlohmann::json& jsonValue, crow::Response& res, std::bitset<Count>& handled) @@ -78,17 +133,7 @@ void readJsonValues(const std::string& key, nlohmann::json& jsonValue, handled.set(Index); - using UnpackType = typename unpackValue<ValueType>::JsonType; - UnpackType value = jsonValue.get_ptr<UnpackType>(); - if (value == nullptr) - { - BMCWEB_LOG_DEBUG << "Value for key " << key - << " was incorrect type: " << jsonValue.type_name(); - messages::propertyValueTypeError(res, jsonValue.dump(), key); - return; - } - - valueToFill = *value; + unpackValue<ValueType>(jsonValue, key, res, valueToFill); } template <size_t Index = 0, size_t Count> @@ -101,7 +146,7 @@ template <size_t Index = 0, size_t Count, typename ValueType, void handleMissing(std::bitset<Count>& handled, crow::Response& res, const char* key, ValueType& unused, UnpackTypes&... in) { - if (!handled.test(Index) && unpackValue<ValueType>::isRequired::value) + if (!handled.test(Index) && !is_optional_v<ValueType>) { messages::propertyMissing(res, key); } |

