summaryrefslogtreecommitdiffstats
path: root/redfish-core/include/utils
diff options
context:
space:
mode:
authorJason M. Bills <jason.m.bills@linux.intel.com>2018-11-06 15:44:38 -0800
committerEd Tanous <ed.tanous@intel.com>2018-11-16 22:37:11 +0000
commit771cfa0fb06de042f9f304abb27d5be80bc163df (patch)
tree35ce49463af04ef289d639ac8ea551395bb877ed /redfish-core/include/utils
parentc4bf6374242b5a9b98fa92a7ecfbc586724a9ca2 (diff)
downloadbmcweb-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.hpp83
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);
}
OpenPOWER on IntegriCloud