|
Boost-Commit : |
Subject: [Boost-commit] svn:boost r71141 - in sandbox/conversion/boost/conversion: . boost std
From: vicente.botet_at_[hidden]
Date: 2011-04-09 05:52:49
Author: viboes
Date: 2011-04-09 05:52:46 EDT (Sat, 09 Apr 2011)
New Revision: 71141
URL: http://svn.boost.org/trac/boost/changeset/71141
Log:
Conversion: cleanup and added some comments
Text files modified:
sandbox/conversion/boost/conversion/boost/array.hpp | 4
sandbox/conversion/boost/conversion/boost/chrono_duration_to_posix_time_duration.hpp | 4
sandbox/conversion/boost/conversion/boost/chrono_posix_time.hpp | 4
sandbox/conversion/boost/conversion/boost/chrono_time_point_to_posix_time_ptime.hpp | 4
sandbox/conversion/boost/conversion/boost/interval.hpp | 4
sandbox/conversion/boost/conversion/boost/optional.hpp | 4
sandbox/conversion/boost/conversion/boost/rational.hpp | 4
sandbox/conversion/boost/conversion/boost/tuple.hpp | 4
sandbox/conversion/boost/conversion/ca_wrapper.hpp | 106 +++++++++++++++++++++++++++------------
sandbox/conversion/boost/conversion/convert_to.hpp | 92 ++++++++++++++++++++++------------
sandbox/conversion/boost/conversion/convert_to_via.hpp | 6 +-
sandbox/conversion/boost/conversion/pack.hpp | 9 +-
sandbox/conversion/boost/conversion/std/complex.hpp | 4
sandbox/conversion/boost/conversion/std/pair.hpp | 4
sandbox/conversion/boost/conversion/std/string.hpp | 4
sandbox/conversion/boost/conversion/std/vector.hpp | 26 +++++----
16 files changed, 175 insertions(+), 108 deletions(-)
Modified: sandbox/conversion/boost/conversion/boost/array.hpp
==============================================================================
--- sandbox/conversion/boost/conversion/boost/array.hpp (original)
+++ sandbox/conversion/boost/conversion/boost/array.hpp 2011-04-09 05:52:46 EDT (Sat, 09 Apr 2011)
@@ -8,8 +8,8 @@
//
//////////////////////////////////////////////////////////////////////////////
-#ifndef BOOST_CONVERT_TO_ARRAY_HPP
-#define BOOST_CONVERT_TO_ARRAY_HPP
+#ifndef BOOST_CONVERSION_ARRAY_HPP
+#define BOOST_CONVERSION_ARRAY_HPP
#include <boost/array.hpp>
#include <boost/conversion/convert_to.hpp>
Modified: sandbox/conversion/boost/conversion/boost/chrono_duration_to_posix_time_duration.hpp
==============================================================================
--- sandbox/conversion/boost/conversion/boost/chrono_duration_to_posix_time_duration.hpp (original)
+++ sandbox/conversion/boost/conversion/boost/chrono_duration_to_posix_time_duration.hpp 2011-04-09 05:52:46 EDT (Sat, 09 Apr 2011)
@@ -8,8 +8,8 @@
//
//////////////////////////////////////////////////////////////////////////////
-#ifndef BOOST_CONVERT_TO_CHRONO_DURATION_TO_POSIX_TIME_DURATION_HPP
-#define BOOST_CONVERT_TO_CHRONO_DURATION_TO_POSIX_TIME_DURATION_HPP
+#ifndef BOOST_CONVERSION_CHRONO_DURATION_TO_POSIX_TIME_DURATION_HPP
+#define BOOST_CONVERSION_CHRONO_DURATION_TO_POSIX_TIME_DURATION_HPP
#include <boost/chrono/chrono.hpp>
#include <boost/date_time/posix_time/posix_time_types.hpp>
Modified: sandbox/conversion/boost/conversion/boost/chrono_posix_time.hpp
==============================================================================
--- sandbox/conversion/boost/conversion/boost/chrono_posix_time.hpp (original)
+++ sandbox/conversion/boost/conversion/boost/chrono_posix_time.hpp 2011-04-09 05:52:46 EDT (Sat, 09 Apr 2011)
@@ -8,8 +8,8 @@
//
//////////////////////////////////////////////////////////////////////////////
-#ifndef BOOST_CONVERT_TO_CHRONO_POSIX_TIME_HPP
-#define BOOST_CONVERT_TO_CHRONO_POSIX_TIME_HPP
+#ifndef BOOST_CONVERSION_CHRONO_POSIX_TIME_HPP
+#define BOOST_CONVERSION_CHRONO_POSIX_TIME_HPP
#include <boost/conversion/boost/chrono_time_point_to_posix_time_ptime.hpp>
#include <boost/conversion/boost/chrono_duration_to_posix_time_duration.hpp>
Modified: sandbox/conversion/boost/conversion/boost/chrono_time_point_to_posix_time_ptime.hpp
==============================================================================
--- sandbox/conversion/boost/conversion/boost/chrono_time_point_to_posix_time_ptime.hpp (original)
+++ sandbox/conversion/boost/conversion/boost/chrono_time_point_to_posix_time_ptime.hpp 2011-04-09 05:52:46 EDT (Sat, 09 Apr 2011)
@@ -9,8 +9,8 @@
//////////////////////////////////////////////////////////////////////////////
//[CHRONO_TIME_POINT_TO_POSIX_TIME_PTIME_HPP
-#ifndef BOOST_CONVERT_TO_CHRONO_TIME_POINT_TO_POSIX_TIME_PTIME_HPP
-#define BOOST_CONVERT_TO_CHRONO_TIME_POINT_TO_POSIX_TIME_PTIME_HPP
+#ifndef BOOST_CONVERSION_CHRONO_TIME_POINT_TO_POSIX_TIME_PTIME_HPP
+#define BOOST_CONVERSION_CHRONO_TIME_POINT_TO_POSIX_TIME_PTIME_HPP
#include <boost/chrono/chrono.hpp>
#include <boost/date_time/posix_time/posix_time_types.hpp>
Modified: sandbox/conversion/boost/conversion/boost/interval.hpp
==============================================================================
--- sandbox/conversion/boost/conversion/boost/interval.hpp (original)
+++ sandbox/conversion/boost/conversion/boost/interval.hpp 2011-04-09 05:52:46 EDT (Sat, 09 Apr 2011)
@@ -8,8 +8,8 @@
//
//////////////////////////////////////////////////////////////////////////////
-#ifndef BOOST_CONVERT_TO_INTERVAL_HPP
-#define BOOST_CONVERT_TO_INTERVAL_HPP
+#ifndef BOOST_CONVERSION_INTERVAL_HPP
+#define BOOST_CONVERSION_INTERVAL_HPP
#include <boost/numeric/interval.hpp>
#include <boost/conversion/convert_to.hpp>
Modified: sandbox/conversion/boost/conversion/boost/optional.hpp
==============================================================================
--- sandbox/conversion/boost/conversion/boost/optional.hpp (original)
+++ sandbox/conversion/boost/conversion/boost/optional.hpp 2011-04-09 05:52:46 EDT (Sat, 09 Apr 2011)
@@ -9,8 +9,8 @@
//////////////////////////////////////////////////////////////////////////////
//[OPTIONAL_HPP
-#ifndef BOOST_CONVERT_TO_OPTIONAL_HPP
-#define BOOST_CONVERT_TO_OPTIONAL_HPP
+#ifndef BOOST_CONVERSION_OPTIONAL_HPP
+#define BOOST_CONVERSION_OPTIONAL_HPP
#include <boost/optional.hpp>
#include <boost/none.hpp>
Modified: sandbox/conversion/boost/conversion/boost/rational.hpp
==============================================================================
--- sandbox/conversion/boost/conversion/boost/rational.hpp (original)
+++ sandbox/conversion/boost/conversion/boost/rational.hpp 2011-04-09 05:52:46 EDT (Sat, 09 Apr 2011)
@@ -8,8 +8,8 @@
//
//////////////////////////////////////////////////////////////////////////////
-#ifndef BOOST_CONVERT_TO_PAIR__HPP
-#define BOOST_CONVERT_TO_PAIR__HPP
+#ifndef BOOST_CONVERSION_PAIR__HPP
+#define BOOST_CONVERSION_PAIR__HPP
#include <boost/rational.hpp>
#include <boost/conversion/convert_to.hpp>
Modified: sandbox/conversion/boost/conversion/boost/tuple.hpp
==============================================================================
--- sandbox/conversion/boost/conversion/boost/tuple.hpp (original)
+++ sandbox/conversion/boost/conversion/boost/tuple.hpp 2011-04-09 05:52:46 EDT (Sat, 09 Apr 2011)
@@ -8,8 +8,8 @@
//
//////////////////////////////////////////////////////////////////////////////
-#ifndef BOOST_CONVERT_TO_TUPLE_HPP
-#define BOOST_CONVERT_TO_TUPLE_HPP
+#ifndef BOOST_CONVERSION_TUPLE_HPP
+#define BOOST_CONVERSION_TUPLE_HPP
#include <boost/fusion/tuple.hpp>
#include <boost/conversion/convert_to.hpp>
Modified: sandbox/conversion/boost/conversion/ca_wrapper.hpp
==============================================================================
--- sandbox/conversion/boost/conversion/ca_wrapper.hpp (original)
+++ sandbox/conversion/boost/conversion/ca_wrapper.hpp 2011-04-09 05:52:46 EDT (Sat, 09 Apr 2011)
@@ -4,50 +4,88 @@
// Software License, Version 1.0. (See accompanying file
// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
//
-// See http://www.boost.org/libs/synchro for documentation.
+// See http://www.boost.org/libs/conversion for documentation.
//
//////////////////////////////////////////////////////////////////////////////
-#ifndef BOOST_CA_WRAPPER_HPP
-#define BOOST_CA_WRAPPER_HPP
+/*!
+ \file
+ \brief
+ Defines the free function @c mca.
+ */
+#ifndef BOOST_CONVERSION_CA_WRAPPER_HPP
+#define BOOST_CONVERSION_CA_WRAPPER_HPP
#include <boost/conversion/convert_to.hpp>
#include <boost/conversion/assign_to.hpp>
namespace boost {
- namespace conversion {
+ namespace conversion {
- template <typename T>
- class ca_wrapper {
- public:
- T& ref_;
- ca_wrapper(ca_wrapper const& r) : ref_(r.ref_) { }
- ca_wrapper(T& r) : ref_(r) {}
- template <typename U>
- operator U() {
- return boost::convert_to<U>(ref_);
- }
- ca_wrapper& operator =(ca_wrapper<T> const& u) {
- ref_ = u.ref_;
- return *this;
- }
- template <typename U>
- ca_wrapper& operator =(ca_wrapper<U> const& u) {
- boost::assign_to(ref_, u.ref_);
- return *this;
- }
- template <typename U>
- ca_wrapper& operator =(U const& u) {
- boost::assign_to(ref_, u);
- return *this;
- }
- };
- }
- template <typename T>
- conversion::ca_wrapper<T> mca(T& r) {
- return conversion::ca_wrapper<T>(r);
- }
+ //! wrapper providing assignement and conversion operations from a reference.
+ template <typename T>
+ class ca_wrapper {
+ public:
+ T& ref_;
+ //! copy constructor
+ //! @NoThrow.
+ ca_wrapper(ca_wrapper const& r) : ref_(r.ref_) { }
+
+ //! constructor from a reference
+ //! @NoThrow.
+ ca_wrapper(T& r) : ref_(r) {}
+
+ //! Implicit conversion to @c U.
+ //! @Effect Forwards the conversion from the reference using @c conver_to.
+ //! @Returns @c *this
+ //! @Throws Whatever @c convert_to throws.
+ template <typename U>
+ operator U() {
+ return boost::convert_to<U>(ref_);
+ }
+
+ //! Assignement.
+ //!
+ //! @Effect Forwards the assignement to the reference.
+ //! @Returns @c *this
+ //! @Throws Whatever @c T aasignement can throws.
+ ca_wrapper& operator =(ca_wrapper<T> const& u) {
+ ref_ = u.ref_;
+ return *this;
+ }
+
+ //! Assignement from a converter assigner wrapping a type U convertible to T.
+ //!
+ //! @Effect Forwards the assignement to the reference using assign_to.
+ //! @Returns @c *this
+ //! @Throws Whatever @c assign_to throws.
+ template <typename U>
+ ca_wrapper& operator =(ca_wrapper<U> const& u) {
+ boost::assign_to(ref_, u.ref_);
+ return *this;
+ }
+
+ //! Assignement from a type U convertible to T.
+ //!
+ //! @Effect Forwards the assignement to the reference using assign_to
+ //! @Returns @c *this
+ //! @Throws Whatever @c assign_to throws.
+ template <typename U>
+ ca_wrapper& operator =(U const& u) {
+ boost::assign_to(ref_, u);
+ return *this;
+ }
+ };
+ }
+ //! makes a converter assigner wrapper of the reference parameter.
+
+ //! The result is able to transform conversion by convert_to calls and assignments by assign_to calls.
+ //! @NoThrow.
+ template <typename T>
+ conversion::ca_wrapper<T> mca(T& r) {
+ return conversion::ca_wrapper<T>(r);
+ }
}
#endif
Modified: sandbox/conversion/boost/conversion/convert_to.hpp
==============================================================================
--- sandbox/conversion/boost/conversion/convert_to.hpp (original)
+++ sandbox/conversion/boost/conversion/convert_to.hpp 2011-04-09 05:52:46 EDT (Sat, 09 Apr 2011)
@@ -4,49 +4,75 @@
// Software License, Version 1.0. (See accompanying file
// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
//
-// See http://www.boost.org/libs/synchro for documentation.
+// See http://www.boost.org/libs/conversion for documentation.
//
//////////////////////////////////////////////////////////////////////////////
+/*!
+ \file
+ \brief
+ Defines the free function @c convert_to.
+
+ The @c convert_to function converts the @c from parameter to a @c To type. The default implementation applies the conversion @c To operator of the @c From class or
+ the copy constructor of the @c To class.
+ Of course if both exist the conversion is ambiguous.
+ A user adapting another type could need to specialize the @c convert_to free function if the default behavior is not satisfactory.
+
+The user can add the @c convert_to overloading on any namespace found by ADL from the @c Source or the @c Target.
+A trick is used to overload on the return type by adding a dummy parameter having the Target.
+
+But sometimes, as it is the case for the standard classes,
+we can not add new functions on the std namespace, so we need a different technique.
+
+The technique consists in partially specialize on the function @c convert_to on the @c boost::conversion namespace.
+For compilers for which we can not partially specialize a function a trick is used: instead of calling directly to the @c convert_to member function,
+@c convert_to calls to the static operation apply on a class with the same name in the namespace @c partial_specializationworkaround.
+Thus the user can specialize partially this class.
+ */
-#ifndef BOOST_CONVERT_TO_HPP
-#define BOOST_CONVERT_TO_HPP
-
-#include <cstddef> //for std::size_t
+#ifndef BOOST_CONVERSION_CONVERT_TO_HPP
+#define BOOST_CONVERSION_CONVERT_TO_HPP
namespace boost {
- namespace dummy {
- template <typename T> struct base_tag {};
- template <typename T> struct type_tag : public base_tag<T> {};
- }
- namespace conversion {
- namespace partial_specialization_workaround {
- template < typename To, typename From >
- struct convert_to {
- inline static To apply(const From& val)
- {
- return To((val));
- }
- };
- }
-
- template < typename To, typename From >
- To convert_to(const From& val, dummy::type_tag<To> const&) {
- return conversion::partial_specialization_workaround::convert_to<To,From>::apply(val);
+ namespace dummy {
+ template <typename T> struct base_tag {
+ //base_tag() {}
+ };
+ template <typename T> struct type_tag : public base_tag<T> {};
+ }
+ namespace conversion {
+ namespace partial_specialization_workaround {
+ template < typename To, typename From >
+ struct convert_to {
+ inline static To apply(const From& val)
+ {
+ return To((val));
}
+ };
}
- namespace conversion_impl {
- template <typename Target, typename Source>
- Target convert_to_impl(Source const& from) {
- using namespace boost::conversion;
- //use boost::conversion::convert_to if ADL fails
- return convert_to(from, boost::dummy::type_tag<Target>());
- }
+
+ template < typename To, typename From >
+ To convert_to(const From& val, dummy::type_tag<To> const&) {
+ return conversion::partial_specialization_workaround::convert_to<To,From>::apply(val);
}
+ }
+ namespace conversion_impl {
template <typename Target, typename Source>
- Target convert_to(Source const& from, boost::dummy::base_tag<Target> const& p=boost::dummy::base_tag<Target>()) {
- (void)p;
- return conversion_impl::convert_to_impl<Target>(from);
+ Target convert_to_impl(Source const& from) {
+ using namespace boost::conversion;
+ //use boost::conversion::convert_to if ADL fails
+ return convert_to(from, boost::dummy::type_tag<Target>());
}
+ }
+
+ //!
+ //! @Effects Converts the @c from parameter to an instance of the @c To type, using by default the conversion operator or copy constructor.
+ //! @Throws Whatever the underlying conversion @c To operator of the @c From class or the copy constructor of the @c To class throws.
+ //! This function can be partialy specialized on compilers supporting it. A trick is used to partialy specialize on the return type by adding a dummy parameter.
+ template <typename Target, typename Source>
+ Target convert_to(Source const& from, boost::dummy::base_tag<Target> const& p=boost::dummy::base_tag<Target>()) {
+ (void)p;
+ return conversion_impl::convert_to_impl<Target>(from);
+ }
}
Modified: sandbox/conversion/boost/conversion/convert_to_via.hpp
==============================================================================
--- sandbox/conversion/boost/conversion/convert_to_via.hpp (original)
+++ sandbox/conversion/boost/conversion/convert_to_via.hpp 2011-04-09 05:52:46 EDT (Sat, 09 Apr 2011)
@@ -4,12 +4,12 @@
// Software License, Version 1.0. (See accompanying file
// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
//
-// See http://www.boost.org/libs/synchro for documentation.
+// See http://www.boost.org/libs/conversion for documentation.
//
//////////////////////////////////////////////////////////////////////////////
-#ifndef BOOST_CONVERT_TO_VIA_HPP
-#define BOOST_CONVERT_TO_VIA_HPP
+#ifndef BOOST_CONVERSION_CONVERT_TO_VIA_HPP
+#define BOOST_CONVERSION_CONVERT_TO_VIA_HPP
#include <boost/conversion/convert_to.hpp>
Modified: sandbox/conversion/boost/conversion/pack.hpp
==============================================================================
--- sandbox/conversion/boost/conversion/pack.hpp (original)
+++ sandbox/conversion/boost/conversion/pack.hpp 2011-04-09 05:52:46 EDT (Sat, 09 Apr 2011)
@@ -4,7 +4,7 @@
// Software License, Version 1.0. (See accompanying file
// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
//
-// See http://www.boost.org/libs/synchro for documentation.
+// See http://www.boost.org/libs/conversion for documentation.
//
//////////////////////////////////////////////////////////////////////////////
@@ -15,13 +15,14 @@
#include <boost/fusion/adapted/std_pair.hpp>
#include <boost/fusion/tuple.hpp>
#include <boost/fusion/include/at_c.hpp>
+#include <boost/fusion/support/pair.hpp>
namespace boost { namespace conversion {
-
+
namespace result_of {
template <typename T1, typename T2> struct pack2 {
- typedef
+ typedef
std::pair<
//~ fusion::tuple<
boost::reference_wrapper<T1>
@@ -36,7 +37,7 @@
> type;
};
}
-
+
template <typename T1, typename T2>
typename boost::conversion::result_of::pack2<T1 const, T2 const>::type pack(
T1 const& t1, T2 const& t2) {
Modified: sandbox/conversion/boost/conversion/std/complex.hpp
==============================================================================
--- sandbox/conversion/boost/conversion/std/complex.hpp (original)
+++ sandbox/conversion/boost/conversion/std/complex.hpp 2011-04-09 05:52:46 EDT (Sat, 09 Apr 2011)
@@ -8,8 +8,8 @@
//
//////////////////////////////////////////////////////////////////////////////
-#ifndef BOOST_CONVERT_TO_COMPLEX_HPP
-#define BOOST_CONVERT_TO_COMPLEX_HPP
+#ifndef BOOST_CONVERSION_STD_COMPLEX_HPP
+#define BOOST_CONVERSION_STD_COMPLEX_HPP
#include <complex>
#include <boost/conversion/convert_to.hpp>
Modified: sandbox/conversion/boost/conversion/std/pair.hpp
==============================================================================
--- sandbox/conversion/boost/conversion/std/pair.hpp (original)
+++ sandbox/conversion/boost/conversion/std/pair.hpp 2011-04-09 05:52:46 EDT (Sat, 09 Apr 2011)
@@ -9,8 +9,8 @@
//////////////////////////////////////////////////////////////////////////////
//[PAIR_HPP
-#ifndef BOOST_CONVERT_TO_PAIR_HPP
-#define BOOST_CONVERT_TO_PAIR_HPP
+#ifndef BOOST_CONVERSION_STD_PAIR_HPP
+#define BOOST_CONVERSION_STD_PAIR_HPP
#include <utility>
//#include <boost/conversion/convert_to.hpp>
Modified: sandbox/conversion/boost/conversion/std/string.hpp
==============================================================================
--- sandbox/conversion/boost/conversion/std/string.hpp (original)
+++ sandbox/conversion/boost/conversion/std/string.hpp 2011-04-09 05:52:46 EDT (Sat, 09 Apr 2011)
@@ -8,8 +8,8 @@
//
//////////////////////////////////////////////////////////////////////////////
-#ifndef BOOST_CONVERT_TO_PAIR_HPP
-#define BOOST_CONVERT_TO_PAIR_HPP
+#ifndef BOOST_CONVERSION_STD_STRING_HPP
+#define BOOST_CONVERSION_STD_STRING_HPP
#include <string>
#include <boost/conversion/convert_to.hpp>
Modified: sandbox/conversion/boost/conversion/std/vector.hpp
==============================================================================
--- sandbox/conversion/boost/conversion/std/vector.hpp (original)
+++ sandbox/conversion/boost/conversion/std/vector.hpp 2011-04-09 05:52:46 EDT (Sat, 09 Apr 2011)
@@ -9,8 +9,8 @@
//////////////////////////////////////////////////////////////////////////////
//[VECTOR_HPP
-#ifndef BOOST_CONVERT_TO_PAIR_HPP
-#define BOOST_CONVERT_TO_PAIR_HPP
+#ifndef BOOST_CONVERSION_STD_VECTOR_HPP
+#define BOOST_CONVERSION_STD_VECTOR_HPP
#include <vector>
#include <boost/conversion/convert_to.hpp>
@@ -34,7 +34,7 @@
template < class T1, class A1, class T2, class A2>
struct assign_to< std::vector<T1,A1>, std::vector<T2,A2> > {
inline static std::vector<T1,A1>& apply(
- std::vector<T1,A1>& to,
+ std::vector<T1,A1>& to,
std::vector<T2,A2> const & from)
{
to.resize(from.size());
@@ -44,26 +44,28 @@
return to;
}
};
-
+
template < class T1, class A1, class T2, class A2>
- struct convert_to< std::vector<T1,A1>,
- //~ typename boost::conversion::result_of::pack2<std::vector<T2,A2> const, A1 const>::type
+ struct convert_to< std::vector<T1,A1>,
+ //~ typename boost::conversion::result_of::pack2<std::vector<T2,A2> const, A1 const>::type
//~ boost::fusion::tuple<
std::pair<
- boost::reference_wrapper<std::vector<T2,A2> const>,
- boost::reference_wrapper<A1 const>
- >
+ boost::reference_wrapper<std::vector<T2,A2> const>,
+ boost::reference_wrapper<A1 const>
+ >
> {
inline static std::vector<T1,A1> apply(
- typename boost::conversion::result_of::pack2<std::vector<T2,A2> const, A1 const>::type
+ typename boost::conversion::result_of::pack2<std::vector<T2,A2> const, A1 const>::type
const & pack)
{
- std::vector<T1,A1> res(fusion::at_c<1>(pack));
+ std::vector<T1,A1> res(fusion::at_c<1>(pack).get());
boost::assign_to(res, fusion::at_c<0>(pack).get());
+ //std::vector<T1,A1> res(pack.second.get());
+ //boost::assign_to(res, pack.first.get());
return res;
}
};
-
+
}
}}
Boost-Commit list run by bdawes at acm.org, david.abrahams at rcn.com, gregod at cs.rpi.edu, cpdaniel at pacbell.net, john at johnmaddock.co.uk