summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDan Goodliffe <dan@randomdan.homeip.net>2023-07-29 13:49:35 +0100
committerDan Goodliffe <dan@randomdan.homeip.net>2023-07-29 13:49:35 +0100
commit7e9a7a6fd6214e42cd31a74c699843a7fad4ed33 (patch)
treea1846263c81b63bbe7ad289f00e6fd1392a0c3be
parentUse std::to_string in setCooke if possible (diff)
downloadicespider-7e9a7a6fd6214e42cd31a74c699843a7fad4ed33.tar.bz2
icespider-7e9a7a6fd6214e42cd31a74c699843a7fad4ed33.tar.xz
icespider-7e9a7a6fd6214e42cd31a74c699843a7fad4ed33.zip
Centralise lots of value conversion functions
-rw-r--r--icespider/core/Jamfile.jam3
-rw-r--r--icespider/core/ihttpRequest.h37
-rw-r--r--icespider/core/util.cpp7
-rw-r--r--icespider/core/util.h63
-rw-r--r--icespider/core/xwwwFormUrlEncoded.cpp6
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 : : : : <include>/usr/include/adhocutil ;
lib slicer : : : : <include>/usr/include/slicer ;
lib stdc++fs ;
-obj util-test : util-test.cpp ;
+obj util-test : util-test.cpp : <use>adhocutil ;
obj routeOptions : routeOptions.ice : <toolset>tidy:<checker>none ;
lib icespider-core :
@@ -17,6 +17,7 @@ lib icespider-core :
<implicit-dependency>routeOptions
: :
<include>.
+ <use>adhocutil
<library>../common//icespider-common
<implicit-dependency>../common//icespider-common
<implicit-dependency>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 <Ice/Current.h>
#include <boost/lexical_cast.hpp>
#include <c++11Helpers.h>
@@ -60,36 +61,12 @@ namespace IceSpider {
virtual std::ostream & dump(std::ostream & s) const = 0;
- static_assert(std::is_constructible_v<std::string, std::string_view>);
- static_assert(std::is_convertible_v<std::string_view, std::string_view>);
-
template<typename T, typename K>
[[nodiscard]] inline std::optional<T>
getFrom(const K key, OptionalString (IHttpRequest::*src)(const K) const) const
{
if (auto v = (this->*src)(key)) {
- if constexpr (std::is_convertible<std::string_view, T>::value) {
- return *v;
- }
- else if constexpr (std::is_constructible<T, std::string_view>::value) {
- return std::optional<T> {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<T>(*v);
- }
- catch (const boost::bad_lexical_cast & e) {
- throw Http400_BadRequest();
- }
- }
+ return convert<T>(*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<T>(i->second);
+
+ if (const auto i = map->find(key); i != map->end()) {
+ return convert<T>(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,7 +1,14 @@
#include "util.h"
+#include "exceptions.h"
namespace IceSpider {
void
+ conversion_failure()
+ {
+ throw Http400_BadRequest();
+ }
+
+ void
remove_trailing(std::string_view & in, const char c)
{
if (const auto n = in.find_last_not_of(c); n != std::string_view::npos) {
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 <Ice/Optional.h>
#include <array>
+#include <boost/lexical_cast.hpp>
+#include <charconv>
#include <optional>
#include <string_view>
+#include <visibility.h>
namespace std::experimental::Ice {
template<typename T, typename TF>
@@ -116,6 +119,66 @@ private:
};
namespace IceSpider {
+ [[noreturn]] DLL_PUBLIC void conversion_failure();
+
+ static_assert(std::is_constructible_v<std::string, std::string_view>);
+ static_assert(std::is_convertible_v<std::string_view, std::string_view>);
+
+ template<typename T>
+ 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<typename T>
+ inline T
+ lexical_cast(const std::string_view v)
+ {
+ try {
+ return boost::lexical_cast<T>(v);
+ }
+ catch (const boost::bad_lexical_cast & e) {
+ conversion_failure();
+ }
+ }
+
+ template<typename T>
+ inline void
+ convert(const std::string_view v, T & out)
+ {
+ if constexpr (std::is_assignable_v<std::string_view, T>) {
+ out = v;
+ }
+ if constexpr (requires { std::from_chars(v.begin(), v.end(), out); }) {
+ from_chars(v, out);
+ }
+ else {
+ out = lexical_cast<T>(v);
+ }
+ }
+
+ template<typename T>
+ inline T
+ convert(const std::string_view v)
+ {
+ if constexpr (std::is_convertible_v<std::string_view, T>) {
+ return v;
+ }
+ else if constexpr (std::is_constructible_v<T, std::string_view>) {
+ return T {v};
+ }
+ else if constexpr (requires(T out) { std::from_chars(v.begin(), v.end(), out); }) {
+ return from_chars<T>(v, {});
+ }
+ else {
+ return lexical_cast<T>(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 <Ice/Config.h>
#include <algorithm>
#include <array>
#include <boost/algorithm/string/compare.hpp>
#include <boost/algorithm/string/finder.hpp>
-#include <charconv>
#include <cstddef>
#include <cstdint>
#include <factory.h>
@@ -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<T>(s, t); \
}
SET(Ice::Byte);