From 7e9a7a6fd6214e42cd31a74c699843a7fad4ed33 Mon Sep 17 00:00:00 2001 From: Dan Goodliffe Date: Sat, 29 Jul 2023 13:49:35 +0100 Subject: Centralise lots of value conversion functions --- icespider/core/Jamfile.jam | 3 +- icespider/core/ihttpRequest.h | 37 ++++---------------- icespider/core/util.cpp | 7 ++++ icespider/core/util.h | 63 +++++++++++++++++++++++++++++++++++ icespider/core/xwwwFormUrlEncoded.cpp | 6 ++-- 5 files changed, 80 insertions(+), 36 deletions(-) diff --git a/icespider/core/Jamfile.jam b/icespider/core/Jamfile.jam index 0654c78..26a30f6 100644 --- a/icespider/core/Jamfile.jam +++ b/icespider/core/Jamfile.jam @@ -2,7 +2,7 @@ lib adhocutil : : : : /usr/include/adhocutil ; lib slicer : : : : /usr/include/slicer ; lib stdc++fs ; -obj util-test : util-test.cpp ; +obj util-test : util-test.cpp : adhocutil ; obj routeOptions : routeOptions.ice : tidy:none ; lib icespider-core : @@ -17,6 +17,7 @@ lib icespider-core : routeOptions : : . + adhocutil ../common//icespider-common ../common//icespider-common routeOptions diff --git a/icespider/core/ihttpRequest.h b/icespider/core/ihttpRequest.h index 99de25a..6876c2b 100644 --- a/icespider/core/ihttpRequest.h +++ b/icespider/core/ihttpRequest.h @@ -1,6 +1,7 @@ #pragma once #include "exceptions.h" +#include "util.h" #include #include #include @@ -60,36 +61,12 @@ namespace IceSpider { virtual std::ostream & dump(std::ostream & s) const = 0; - static_assert(std::is_constructible_v); - static_assert(std::is_convertible_v); - template [[nodiscard]] inline std::optional getFrom(const K key, OptionalString (IHttpRequest::*src)(const K) const) const { if (auto v = (this->*src)(key)) { - if constexpr (std::is_convertible::value) { - return *v; - } - else if constexpr (std::is_constructible::value) { - return std::optional {std::in_place, *v}; - } - else if constexpr (requires(T out) { std::from_chars(v->begin(), v->end(), out); }) { - if (T out {}; std::from_chars(v->begin(), v->end(), out).ec == std::errc {}) { - return out; - } - else { - throw Http400_BadRequest(); - } - } - else { - try { - return boost::lexical_cast(*v); - } - catch (const boost::bad_lexical_cast & e) { - throw Http400_BadRequest(); - } - } + return convert(*v); } else { return std::nullopt; @@ -117,13 +94,11 @@ namespace IceSpider { if (!map) { return {}; } - auto i = map->find(key); - if (i == map->end()) { - return {}; - } - else { - return boost::lexical_cast(i->second); + + if (const auto i = map->find(key); i != map->end()) { + return convert(i->second); } + return {}; } void responseRedirect(const std::string_view url, const OptionalString & = {}) const; diff --git a/icespider/core/util.cpp b/icespider/core/util.cpp index 62de195..b330f79 100644 --- a/icespider/core/util.cpp +++ b/icespider/core/util.cpp @@ -1,6 +1,13 @@ #include "util.h" +#include "exceptions.h" namespace IceSpider { + void + conversion_failure() + { + throw Http400_BadRequest(); + } + void remove_trailing(std::string_view & in, const char c) { diff --git a/icespider/core/util.h b/icespider/core/util.h index f4d559b..d31c7da 100644 --- a/icespider/core/util.h +++ b/icespider/core/util.h @@ -2,8 +2,11 @@ #include #include +#include +#include #include #include +#include namespace std::experimental::Ice { template @@ -116,6 +119,66 @@ private: }; namespace IceSpider { + [[noreturn]] DLL_PUBLIC void conversion_failure(); + + static_assert(std::is_constructible_v); + static_assert(std::is_convertible_v); + + template + inline T + from_chars(const std::string_view v, T && out) + { + if (std::from_chars(v.begin(), v.end(), out).ec != std::errc {}) { + conversion_failure(); + } + return out; + } + + template + inline T + lexical_cast(const std::string_view v) + { + try { + return boost::lexical_cast(v); + } + catch (const boost::bad_lexical_cast & e) { + conversion_failure(); + } + } + + template + inline void + convert(const std::string_view v, T & out) + { + if constexpr (std::is_assignable_v) { + out = v; + } + if constexpr (requires { std::from_chars(v.begin(), v.end(), out); }) { + from_chars(v, out); + } + else { + out = lexical_cast(v); + } + } + + template + inline T + convert(const std::string_view v) + { + if constexpr (std::is_convertible_v) { + return v; + } + else if constexpr (std::is_constructible_v) { + return T {v}; + } + else if constexpr (requires(T out) { std::from_chars(v.begin(), v.end(), out); }) { + return from_chars(v, {}); + } + else { + return lexical_cast(v); + } + } + void remove_trailing(std::string_view & in, const char c); void remove_leading(std::string_view & in, const char c); } diff --git a/icespider/core/xwwwFormUrlEncoded.cpp b/icespider/core/xwwwFormUrlEncoded.cpp index 73f77b8..639b07a 100644 --- a/icespider/core/xwwwFormUrlEncoded.cpp +++ b/icespider/core/xwwwFormUrlEncoded.cpp @@ -1,11 +1,11 @@ #include "xwwwFormUrlEncoded.h" #include "exceptions.h" +#include "util.h" #include #include #include #include #include -#include #include #include #include @@ -181,9 +181,7 @@ namespace IceSpider { /* NOLINTNEXTLINE(bugprone-macro-parentheses) */ \ void set(T & t) const override \ { \ - if (const auto v = s.value(); std::from_chars(v.begin(), v.end(), t).ec != std::errc {}) { \ - throw Http400_BadRequest(); \ - } \ + convert(s, t); \ } SET(Ice::Byte); -- cgit v1.2.3